Я ищу помощь с моим приложением. Вот пример код первого (урезанный от около 2k линий ...), и я попытаюсь объяснить, что я ищу позже:ndb модели, декораторы, вложенные функции
from google.appengine.ext import ndb
import webapp2
import json
class User(ndb.Model):
company_ = ndb.KeyProperty(repeated=True)
@property
def company(self):
return {} if not self.company_ else self.company_
@company.setter
def company(self, value):
if value:
self.company_ = self.company_.expand(value) if self.company_ else [value]
else:
self.company_ = []
self.put()
class Company(ndb.Model):
administrator = ndb.KeyProperty(kind=User, repeated=True)
manager = ndb.KeyProperty(kind=User, repeated=True)
# FAKE decorator
@staticmethod
def administrator(handler):
def check_requirements(self, *a, **kw):
if True:
return
else:
return handler(self, *a, **kw)
return check_requirements
class BaseHandler(webapp2.RequestHandler):
def jwrite(self, **kw):
return self.response.out.write(json.dumps(kw))
class require(BaseHandler):
@staticmethod
def login(handler):
def check_requirements(self, *a, **kw):
if not self.auth.get_user_by_session():
self.redirect('/', abort=True)
else:
return handler(self, *a, **kw)
return check_requirements
class ApiHandler(BaseHandler):
@require.login
def post(self, model, action, key=''):
method = '_post_%s' % model
try:
getattr(self, method)(action, key)
except Exception as error:
return self.jwrite(error = error)
def _post_company(self, action, key):
if action == 'create':
data = dict(self.request.POST)
""" Company.create(data) method:
Populates Company instance with POST data.
Assigns first user that created the company
both administrator and manager roles.
"""
key_ = Company.create(data)
if key_:
self.user.company = key_
return
elif action == 'delete':
@Company.administrator
def delete_all_user_companies(self):
ndb.delete_multi(self.user.company)
self.user.company = None
return
companies = ndb.get_multi(self.user.company)
if self.user.key in map(lambda c: c.administrator, companies):
delete_all_user_companies(self)
elif action == 'update':
@Company.manager
def update_company(self, key):
data = dict(self.request.POST)
""" Company.update(key, data) method:
Populates Company instance with POST data
"""
key_ = Company.update(key, data)
if key_:
return
company = ndb.Key(Company, key).get()
if self.user.key in company.manager.extend(company.administrator):
update_company(self)
Как вы можете видеть, у меня есть пользователи и Компания модель. Пользователь может иметь несколько компаний и компаний, которые могут иметь несколько пользователей, которые могут быть администраторами или менеджерами. Вы заметите некоторые декораторы и вложенные функции - большинство из них поддельные (но это то, что я ищу ...
Я делаю базовую регистрационную проверку с @ require.login decorator (I ' я поместил его в отдельный класс, просто потому, что он выглядит более чистым в коде - @ require.login vs @ BaseHandler.require_login). С его помощью я «защитил» почтовый метод моего API, и теперь мне нужно выполнить дополнительную проверку роли - администраторы могут делать некоторые вещи, которые не могут выполнять менеджеры. Мне нужно будет сделать эту проверку в нескольких других местах, поэтому я думаю, что это будет хорошее место для декораторских функций, но я не могу понять, как их писать. :
Что было бы хорошим местом для этого декоратора? Должен ли я помещать его в класс компании или где-то в классе ApiHandler? Мой первый инстинкт заключается в том, чтобы поместить его в класс компании, но я не уверен, как справиться с областью - мне нужно получить экземпляр пользователя (список self.user.company) там как-то ...
Следующая вещь менеджер декоратор. Как я пишу это как декоратор:
company = ndb.Key(Company, key).get() if self.user.key in company.manager.extend(company.administrator): update_company(self)
и использовать его в качестве @ Company.manager или @ requre.manager, в зависимости от ответа на мой первый вопрос?
Другой декоратор для администратора, что это немного сложнее - я должен проверить, если пользователь администратором для всех его компаний, а также удалять те, где он, сохраняя при этом те, где он не является:
companies = ndb.get_multi(self.user.company) if self.user.key in map(lambda c: c.administrator, companies): delete_all_user_companies(self)
Я даже не уверен, правильна ли эта функция map(), и если код будет работать, еще не пробовал - это просто псевдозапись на данный момент ...
Последний вопрос: Я беспокоюсь о взломе запроса POST? Исходя из приведенного выше примера кода, возможно ли, что некоторый пользователь может создавать пользовательские POST-запросы и удалять или обновлять компанию, а не его? !
Любая помощь, комментарии или идеи будут оценены (; спасибо
Это нормально принять на свой вопрос! –