Как мне переписать это на что-то более сухое и удобное в обслуживании?

риложение для фляги сосредоточено вокруг модификации моделей на основе SQLAlchemy. Поэтому я считаю, что flask-admin отличный плагин, потому что он отображает мои модели SQLA на формы с представлениями, уже определенными с настраиваемым интерфейсом, который опробован и протестирован.

Я понимаю, что Flask-admin предназначен для плагинов дляадминистраторы управление данными своего сайта. Однако я не понимаю, почему я не могу использовать FA в качестве основы для своих пользователей, чтобы CRUD их данные.

Для этого я написал следующее:

class AuthorizationRequiredView(BaseView):

  def get_roles(self):
    raise NotImplemented("Override AuthorizationRequiredView.get_roles not set.")

  def is_accessible(self):
    if not is_authenticated():
      return False
    if not current_user.has_role(*self.get_roles()):
      return False
    return True

  def inaccessible_callback(self, name, **kwargs):
    if not is_authenticated():
      return current_app.user_manager.unauthenticated_view_function()
    if not current_user.has_role(*self.get_roles()):
      return current_app.user_manager.unauthorized_view_function()


class InstructionModelView(DefaultModelView, AuthorizationRequiredView):

  def get_roles(self):
    return ["admin", "member"]

  def get_query(self):
    """Jails the user to only see their instructions.
    """
    base = super(InstructionModelView, self).get_query()
    if current_user.has_role('admin'):
      return base
    else:
      return base.filter(Instruction.user_id == current_user.id)

  @expose('/edit/', methods=('GET', 'POST'))
  def edit_view(self):
    if not current_user.has_role('admin'):
      instruction_id = request.args.get('id', None)
      if instruction_id:
        m = self.get_one(instruction_id)
        if m.user_id != current_user.id:
          return current_app.user_manager.unauthorized_view_function()
    return super(InstructionModelView, self).edit_view()

  @expose('/delete/', methods=('POST',))
  def delete_view(self):
    return_url = get_redirect_target() or self.get_url('.index_view')

    if not self.can_delete:
      return redirect(return_url)

    form = self.delete_form()

    if self.validate_form(form):
      # id is InputRequired()
      id = form.id.data

      model = self.get_one(id)

      if model is None:
        flash(gettext('Record does not exist.'), 'error')
        return redirect(return_url)

      # message is flashed from within delete_model if it fails
      if self.delete_model(model):

        if not current_user.has_role('admin') \
            and model.user_id != current_user.id:
          # Denial: NOT admin AND NOT user_id match
          return current_app.user_manager.unauthorized_view_function()

        flash(gettext('Record was successfully deleted.'), 'success')
        return redirect(return_url)
    else:
      flash_errors(form, message='Failed to delete record. %(error)s')

    return redirect(return_url)

Примечание: я использую Flask-User, который построен поверх Flask-Login.

Код выше работает. Тем не менее, трудно абстрагироваться как базовый класс для других моделей, в которых я хотел бы реализовать контроль доступа для операций CRUD и представлений Индекс / Правка / Детали / Удалить.

В основном проблемы:

метод API,is_accessible, не предоставляет первичный ключ модели. Этот ключ необходим, потому что почти во всех случаях отношения между пользователями и объектами почти всегда хранятся через отношения или непосредственно в таблице модели (то есть, имея user_id в таблице модели).

некоторые взгляды, такие какdelete_view, не предоставляйте идентификатор экземпляра, который можно легко получить. Вdelete_viewМне пришлось скопировать всю функцию, чтобы добавить еще одну строку, чтобы проверить, принадлежит ли она нужному пользователю.

Конечно, кто-то думал об этих проблемах.

Как мне переписать это на что-то более сухое и удобное в обслуживании?

Ответы на вопрос(0)

Ваш ответ на вопрос