class UserISCore(UIRESTModelISCore): model = User form_class = UserForm ui_list_fields = ('id', 'created_issues_count', '_obj_name') permission = PermissionsSet( create=IsSuperuser(), read=IsSuperuser() | (IsAdminUser() & (IsNoObject() | IsLoggedUser())), update=IsSuperuser() | (IsAdminUser() & (IsNoObject() | IsLoggedUser())), delete=IsSuperuser() & ~IsObjectSuperuser()) def get_queryset(self, request): qs = super().get_queryset(request) if not request.user.is_superuser: qs = qs.filter(pk=request.user.pk) return qs def get_rest_patterns(self): rest_patterns = super().get_rest_patterns() rest_patterns['api-user-issue'] = self.default_rest_pattern_class( 'api-number-issues', self.site_name, r'(?P<pk>[-\w]+)/issue-number/', NumberOfUserIssuesResource, self) return rest_patterns def created_issues_count(self, obj): return obj.created_issues.count()
class RESTModelCoreResourcePermissionsMixin(RESTObjectPermissionsMixin): pk_name = 'pk' permission = PermissionsSet( # HTTP permissions head=CoreReadAllowed(), options=CoreReadAllowed(), post=CoreCreateAllowed(), get=CoreReadAllowed(), put=CoreUpdateAllowed(), patch=CoreUpdateAllowed(), delete=CoreDeleteAllowed(), # Serializer permissions create_obj=CoreCreateAllowed(), read_obj=CoreReadAllowed(), update_obj=CoreUpdateAllowed(), delete_obj=CoreDeleteAllowed(), # Other permissions **{ DEFAULT_PERMISSION: CoreAllowed(), } ) def _get_perm_obj_or_none(self, pk=None): pk = pk or self.kwargs.get(self.pk_name) if pk: return get_object_or_none(self.core.model, pk=pk) else: return None
def test_fields_set_permission_sould_return_right_readonly_fields(self): field_set_permission = FieldsSetPermission( FieldsListPermission( permission=PermissionsSet(read=ObjIsNotNonePermission()), fields=('a', 'b', 'c')), FieldsListPermission(permission=PermissionsSet( read=AllowAny(), edit=ObjIsNotNonePermission()), fields=('a', 'b', 'd')), FieldsListPermission( permission=PermissionsSet(read=ObjIsNotNonePermission()), fields=('e', )), ) assert_equal( field_set_permission.get_readonly_fields(None, None, None), {'a', 'b', 'c', 'd', 'e'}) assert_equal(field_set_permission.get_readonly_fields(None, None, ''), {'a', 'b', 'c', 'e'})
def test_fields_list_permission_sould_return_right_disallowed_fields(self): field_list_permission = FieldsListPermission( permission=PermissionsSet(read=ObjIsNotNonePermission()), fields=('a', 'b', 'c')) assert_equal( field_list_permission.get_disallowed_fields(None, None, None), {'a', 'b', 'c'}) assert_equal( field_list_permission.get_disallowed_fields(None, None, ''), set())
def test_permissions_set_should_return_permissions_according_to_name(self): permission = PermissionsSet( none=ObjIsNonePermission(), not_none=ObjIsNotNonePermission(), string=ObjIsStringPermission(), self_note=SelfPermission('none'), ) assert_true(permission.has_permission('none', None, None, None)) assert_false(permission.has_permission('none', None, None, '')) assert_false(permission.has_permission('invalid', None, None, None)) assert_false(permission.has_permission('not_none', None, None, None)) assert_true(permission.has_permission('string', None, None, '')) assert_true(permission.has_permission('self_note', None, None, None)) assert_false(permission.has_permission('self_note', None, None, ''))
class ReadonlyDetailModelFormView(DetailModelFormView): show_save_and_continue = False permission = PermissionsSet(get=CoreReadAllowed(), **{ DEFAULT_PERMISSION: CoreAllowed(), }) def is_readonly(self): return True
class DefaultCoreViewMixin(DefaultViewMixin): core = None view_type = None title = None permission = PermissionsSet(get=CoreReadAllowed(), **{ DEFAULT_PERMISSION: CoreAllowed(), }) def __init__(self): super(DefaultCoreViewMixin, self).__init__() self.site_name = self.core.site_name self.menu_groups = self.core.get_menu_groups() @classmethod def __init_core__(cls, core, pattern): cls.core = core cls.pattern = pattern def dispatch(self, request, *args, **kwargs): self.core.init_ui_request(request) return super(DefaultCoreViewMixin, self).dispatch(request, *args, **kwargs) def get_title(self): return self.title @property def view_name(self): return '%s-%s' % (self.view_type, '-'.join(self.menu_groups)) def get_context_data(self, **kwargs): context_data = super(DefaultCoreViewMixin, self).get_context_data(**kwargs) extra_context_data = { 'core_permission': self.core.permission, 'permission': self.permission, 'view': self } extra_context_data.update(context_data) return extra_context_data
class AddModelFormView(DefaultCoreModelFormView): template_name = 'is_core/generic_views/add_form.html' form_template = 'is_core/forms/model_add_form.html' view_type = 'add' messages = { 'success': _('The %(name)s "%(obj)s" was added successfully.'), 'error': _('Please correct the error below.') } permission = PermissionsSet(get=CoreCreateAllowed(), post=CoreCreateAllowed(), **{ DEFAULT_PERMISSION: CoreAllowed(), }) def get_title(self): return (self.title or self.model._ui_meta.add_verbose_name % { 'verbose_name': self.model._meta.verbose_name, 'verbose_name_plural': self.model._meta.verbose_name_plural })
class BulkChangeFormView(DefaultModelFormView): form_template = 'is_core/views/bulk-change-view.html' is_ajax_form = False permission = PermissionsSet(get=CoreUpdateAllowed(), post=CoreUpdateAllowed(), **{ DEFAULT_PERMISSION: CoreAllowed(), }) def get_form_class_base(self): return self.form_class or self.core.get_rest_form_edit_class( self.request) def dispatch(self, request, *args, **kwargs): if 'snippet' not in request.GET: raise Http404 return super().dispatch(request, *args, **kwargs) def get_fields(self): return self.core.get_ui_bulk_change_fields( self.request) if self.fields is None else self.fields def get_fieldsets(self): return ((None, {'fields': self.get_fields()}), ) def generate_fieldsets(self, **kwargs): return get_fieldsets_without_disallowed_fields( self.request, self.get_fieldsets(), (self._get_disallowed_fields_from_permissions() | set(self.generate_readonly_fields()) | set(self.get_exclude()))) def get_readonly_fields(self): return () def get_is_bulk(self): return True
def _init_permission(self, permission): return PermissionsSet( read=SelfPermission('read_own') | SelfPermission('read_all'), read_own=self.read_own_permission, read_all=self.read_all_permission, )
class DetailModelFormView(GetCoreObjViewMixin, DefaultCoreModelFormView): template_name = 'is_core/generic_views/detail_form.html' form_template = 'is_core/forms/model_detail_form.html' view_type = 'detail' messages = { 'success': _('The %(name)s "%(obj)s" was changed successfully.'), 'error': _('Please correct the error below.') } pk_name = 'pk' permission = PermissionsSet(get=CoreReadAllowed() | CoreUpdateAllowed(), post=CoreUpdateAllowed(), **{ DEFAULT_PERMISSION: CoreAllowed(), }) @property def detail_verbose_name(self): return self.model._ui_meta.detail_verbose_name def get_title(self): return (self.title or self.detail_verbose_name % { 'verbose_name': self.model._meta.verbose_name, 'verbose_name_plural': self.model._meta.verbose_name_plural, 'obj': self.get_obj(True) }) def is_readonly(self): return not self.has_permission('post') def link(self, arguments=None, **kwargs): if arguments is None: arguments = (self.kwargs[self.pk_name], ) return super().link(arguments=arguments, **kwargs) # TODO: get_obj should not be inside core get_obj and _get_perm_obj_or_404 should have same implementation def _get_perm_obj_or_404(self, pk=None): """ If is send parameter pk is returned object according this pk, else is returned object from get_obj method, but it search only inside filtered values for current user, finally if object is still None is returned according the input key from all objects. If object does not exist is raised Http404 """ if pk: obj = get_object_or_none(self.core.model, pk=pk) else: try: obj = self.get_obj(False) except Http404: obj = get_object_or_none(self.core.model, **self.get_obj_filters()) if not obj: raise Http404 return obj def _get_export_types(self): return self.core.get_ui_detail_export_types( self.request) if self.export_types is None else self.export_types def _get_export_fields(self): return list( self.core.get_ui_detail_export_fields(self.request, self.get_obj(True))) def _generate_rest_detail_export_fieldset(self): return ModelFlatRESTFields.create_from_flat_list( self._get_export_fields(), self.model) def get_context_data(self, form=None, inline_form_views=None, **kwargs): context_data = super().get_context_data( form=form, inline_form_views=inline_form_views, **kwargs) if self._get_export_types() and self._get_export_fields(): context_data.update({ 'export_types': get_export_types_with_content_type(self._get_export_types()), 'rest_detail_export_fieldset': self._generate_rest_detail_export_fieldset(), 'api_url': self.core.get_api_detail_url(self.request, self.get_obj(True)) }) return context_data