class Log(models.Model): ADD = 1 EDIT = 2 DELETE = 3 OPERATION_CHOICES = [[ADD, u'Cadastro'], [EDIT, u'Edição'], [DELETE, u'Exclusão']] content_type = models.ForeignKey(ContentType, verbose_name=u'Objeto', filter=True) operation = models.IntegerField(verbose_name=u'Operação', choices=OPERATION_CHOICES, filter=True) user = models.ForeignKey('admin.User', filter=True) date = models.DateTimeField(verbose_name=u'Data/Hora', auto_now=True, filter=True) object_id = models.IntegerField(verbose_name=u'Identificador', search=True) object_description = models.CharField(verbose_name=u'Descrição do Objeto') content = models.TextField(verbose_name=u'Conteúdo', null=True) fieldsets = ( (u'Dados Gerais', {'fields': ( ('content_type', 'operation'), ('user', 'date'), ('object_id', 'object_description'), 'get_tags')}), (u'Índices', {'relations': ('logindex_set',)}), ) objects = models.Manager() class Meta: verbose_name = u'Log' verbose_name_plural = u'Logs' icon = 'fa-history' list_per_page = 25 def __unicode__(self): return 'Log #%s' % self.pk def can_add(self): return False def can_edit(self): return False def can_delete(self): return False def get_action_description(self): return (u'adicionou', u'editou', u'removeu')[self.operation - 1] def get_style(self): return ('success', 'info', 'danger')[self.operation - 1] def get_icon(self): return ('plus', 'pencil', 'trash-o')[self.operation - 1] @meta(u'Tags', formatter='log_tags') def get_tags(self): return json.loads(self.content) def create_indexes(self, instance): for log_index in get_metadata(instance.__class__, 'logging', (), iterable=True): index_object = getattr2(instance, log_index) if index_object: index_content_type = ContentType.objects.get_for_model(index_object.__class__) LogIndex.objects.create(log=self, content_type=index_content_type, object_id=index_object.pk)
class Role(models.Model): user = models.ForeignKey('admin.User', verbose_name='Usuário', composition=True) group = models.ForeignKey('admin.Group', verbose_name='Grupo') scope = models.ForeignKey('admin.Scope', verbose_name='Scope', null=True, blank=True) active = models.BooleanField(verbose_name='Active', default=True) fieldsets = ( ('Dados Gerais', { 'fields': ('user', 'group') }), ('Scope', { 'fields': ('scope', 'active') }), ) objects = models.Manager() class Meta: verbose_name = 'Função' verbose_name_plural = 'Funções' can_admin = 'Gerenciador de Usuários' def save(self, *args, **kwargs): super(Role, self).save(*args, **kwargs) if self.active: self.user.groups.add(self.group) def __str__(self): return '{}'.format(self.group)
class Log(models.Model): ADD = 1 EDIT = 2 DELETE = 3 OPERATION_CHOICES = [[ADD, _('Add')], [EDIT, _('Edit')], [DELETE, _('Delete')]] content_type = models.ForeignKey(ContentType, verbose_name=_('Content Type'), filter=True) operation = models.IntegerField(verbose_name=_('Operation'), choices=OPERATION_CHOICES, filter=True) user = models.ForeignKey('admin.User', filter=True, verbose_name=_('User')) date = models.DateTimeField(verbose_name=_('Date/Time'), auto_now=True, filter=True) object_id = models.IntegerField(verbose_name=_('Identifier'), search=True) object_description = models.CharField(verbose_name=_('Object Description')) content = models.TextField(verbose_name=_('Content'), null=True) fieldsets = ( (_('General Data'), {'fields': ( ('content_type', 'operation'), ('user', 'date'), ('object_id', 'object_description'), 'get_tags')}), (_('Indexes'), {'relations': ('logindex_set',)}), ) objects = models.Manager() class Meta: verbose_name = _('Log') verbose_name_plural = _('Logs') icon = 'fa-history' list_per_page = 25 def __str__(self): return 'Log #{}'.format(self.pk) def can_add(self): return False def can_edit(self): return False def can_delete(self): return False def get_action_description(self): return (_('added'), _('edited'), _('deleted'))[self.operation - 1] def get_style(self): return ('success', 'info', 'danger')[self.operation - 1] def get_icon(self): return ('plus', 'pencil', 'trash-o')[self.operation - 1] @meta('Tags') def get_tags(self): return json.loads(self.content) def create_indexes(self, instance): for log_index in get_metadata(instance.__class__, 'logging', (), iterable=True): index_object = getattr2(instance, log_index) if index_object: index_content_type = ContentType.objects.get_for_model(index_object.__class__) LogIndex.objects.create(log=self, content_type=index_content_type, object_id=index_object.pk)
class Role(models.Model): user = models.ForeignKey('admin.User', verbose_name=u'Usuário', composition=True) group = models.ForeignKey('admin.Group', verbose_name=u'Grupo') organizations = models.ManyToManyField(Organization, through='admin.OrganizationRole', verbose_name=u'Organizações', exclude=True, blank=True) units = models.ManyToManyField(Unit, through='admin.UnitRole', verbose_name=u'Unidades', exclude=True, blank=True) fieldsets = ( (u'Dados Gerais', {'fields': ('user', 'group')}), (u'Organizações', {'fields': ('organizations',)}), (u'Unidades', {'fields': ('units',)}), ) objects = models.Manager() class Meta: verbose_name = u'Função' verbose_name_plural = u'Funções' db_table = 'admin_user_groups' managed = False list_display = role_list_display can_admin = u'Gerenciador de Usuários' def __unicode__(self): return u'%s' % self.group @meta(u'Organizações') def get_organizations(self): return self.organizations.all() @meta(u'Unidades') def get_units(self): return self.units.all() def can_edit(self): return False def can_add(self): return True def can_define_organizations(self): return Organization.objects.exclude(pk=0).exists() def can_define_roles(self): return Unit.objects.exclude(pk=0).exists() @action(u'Definir Organizações', condition='can_define_organizations', message=u'Organização(ões) definida(s) com sucesso.', inline=True) def define_organizations(self, organizations): self.organizationrole_set.all().delete() for organization in organizations: OrganizationRole.objects.get_or_create(role=self, organization=organization) @action(u'Definir Unidades', condition='can_define_roles', message=u'Unidade(s) definida(s) com sucesso.', inline=True) def define_units(self, units): self.unitrole_set.all().delete() for unit in units: UnitRole.objects.get_or_create(role=self, unit=unit)
class UnitRole(models.Model): role = models.ForeignKey(Role, verbose_name=u'Função', composition=True) unit = models.ForeignKey(Unit, verbose_name=u'Unidade') class Meta: verbose_name = u'Função na Unidade' verbose_name_plural = u'Funções na Unidade' def __unicode__(self): return u'%s - %s' % (self.role, self.unit)
class OrganizationRole(models.Model): role = models.ForeignKey(Role, verbose_name=u'Função', composition=True) organization = models.ForeignKey(Organization, verbose_name=u'Organização') class Meta: verbose_name = u'Papel na Organização' verbose_name_plural = u'Papeis na Organização' def __unicode__(self): return u'%s - %s' % (self.role, self.organization)
class LogIndex(models.Model): log = models.ForeignKey(Log, verbose_name=u'Log', composition=True) content_type = models.ForeignKey('contenttypes.ContentType', verbose_name=u'Dado') object_id = models.IntegerField(verbose_name=u'Identificador', search=True) class Meta: verbose_name = u'Index' verbose_name_plural = u'Indexes' def __unicode__(self): return u'Index #%s' % self.pk
class LogIndex(models.Model): log = models.ForeignKey(Log, verbose_name=_('Log'), composition=True) content_type = models.ForeignKey('contenttypes.ContentType', verbose_name=_('Content Type')) object_id = models.IntegerField(verbose_name=_('Identifier'), search=True) class Meta: verbose_name = _('Index') verbose_name_plural = _('Indexes') def __str__(self): return 'Index #{}'.format(self.pk)
class Role(models.Model): user = models.ForeignKey('admin.User', verbose_name=_('User'), composition=True) group = models.ForeignKey('admin.Group', verbose_name=_('Group')) scope = models.ForeignKey('admin.Scope', verbose_name=_('Scope'), null=True, blank=True) active = models.BooleanField(verbose_name=_('Active'), default=True) fieldsets = ( (_('General Data'), {'fields': ('user', 'group')}), (_('Scope'), {'fields': ('scope', 'active')}), ) objects = models.Manager() class Meta: verbose_name = _('Role') verbose_name_plural = _('Roles') can_admin = _('User Manager') def save(self, *args, **kwargs): super(Role, self).save(*args, **kwargs) if self.active: self.user.groups.add(self.group) def __str__(self): return '{}'.format(self.group)
class LogIndex(models.Model): log = models.ForeignKey(Log, verbose_name=_('Log'), composition=True) content_type = models.ForeignKey('contenttypes.ContentType', verbose_name=_('Content Type')) object_id = models.IntegerField(verbose_name=_('Identifier'), search=True) class Meta: verbose_name = _('Index') verbose_name_plural = _('Indexes') list_display = 'content_type', 'object_id', 'get_tags' def __str__(self): return 'Index #{}'.format(self.pk) @meta('Alterações') def get_tags(self): data = [] date = datetime.datetime(self.log.date.year, self.log.date.month, self.log.date.day, self.log.date.hour, self.log.date.minute, self.log.date.second) qs = Log.objects.filter(content_type=self.content_type, user=self.log.user, date__startswith=date, object_id=self.object_id) for log in qs: for attr, old, new in json.loads(log.content): data.append('{} : {} >> {}'.format(attr, old, new)) return ' | '.join(data)
class Log(models.Model): ADD = 1 EDIT = 2 DELETE = 3 OPERATION_CHOICES = [[ADD, _('Add')], [EDIT, _('Edit')], [DELETE, _('Delete')]] content_type = models.ForeignKey(ContentType, verbose_name=_('Content Type'), filter=True) operation = models.IntegerField(verbose_name=_('Operation'), choices=OPERATION_CHOICES, filter=True) user = models.ForeignKey('admin.User', filter=True, verbose_name=_('User')) date = models.DateTimeField(verbose_name=_('Date/Time'), auto_now=True, filter=True) object_id = models.IntegerField(verbose_name=_('Identifier'), search=True) object_description = models.CharField(verbose_name=_('Object Description')) content = models.TextField(verbose_name=_('Content'), null=True, search=True) fieldsets = ( (_('General Data'), {'fields': ( ('content_type', 'operation'), ('user', 'date'), ('object_id', 'object_description'), 'get_tags')}), (_('Indexes'), {'relations': ('logindex_set',), 'condition': 'has_index'}), ) objects = models.Manager() class Meta: verbose_name = _('Log') verbose_name_plural = _('Logs') icon = 'fa-history' list_per_page = 25 list_display = 'content_type', 'object_id', 'operation', 'user', 'date', 'get_tags' order_by = '-date' def __str__(self): return 'Log #{}'.format(self.pk) def can_add(self): return False def can_edit(self): return False def can_delete(self): return False def has_index(self): return self.logindex_set.exists() def get_action_description(self): return (_('added'), _('edited'), _('deleted'))[self.operation - 1] def get_style(self): return ('success', 'info', 'danger')[self.operation - 1] def get_icon(self): return ('plus', 'pencil', 'trash-o')[self.operation - 1] @meta('Alterações') def get_tags(self): data = [] for attr, old, new in json.loads(self.content): data.append('{} : {} >> {}'.format(attr, old, new)) for log_index in self.logindex_set.all(): date = datetime.datetime( log_index.log.date.year, log_index.log.date.month, log_index.log.date.day, log_index.log.date.hour, log_index.log.date.minute, log_index.log.date.second ) qs = Log.objects.filter( content_type=log_index.content_type, user=log_index.log.user, date__startswith=date, object_id=log_index.object_id ) for log in qs: for attr, old, new in json.loads(log.content): data.append('{} : {} >> {}'.format(attr, old, new)) return ' | '.join(data) def create_indexes(self, instance): for log_index in get_metadata(instance.__class__, 'logging', (), iterable=True): index_object = getattr2(instance, log_index) if index_object: index_content_type = ContentType.objects.get_for_model(index_object.__class__) LogIndex.objects.create(log=self, content_type=index_content_type, object_id=index_object.pk)
class User(AbstractBaseUser, PermissionsMixin): USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] name = models.CharField(_('Name'), max_length=100, blank=True, search=True) username = models.CharField(_('Username'), max_length=30, unique=True, search=True) email = models.CharField(_('E-mail'), max_length=75, blank=True, default='') active = models.BooleanField(verbose_name=_('Active'), default=True, filter=True) photo = models.ImageField(upload_to='profiles', null=True, blank=True, default='/static/images/user.png', verbose_name=_('Photo'), exclude=True) token = models.CharField(verbose_name='Token', null=True, exclude=True) permission_mapping = models.JsonField(verbose_name=_('Permissions Mapping'), exclude=True, display=False) scope = models.ForeignKey(Scope, verbose_name='Scope', null=True, exclude=True, blank=True) objects = UserManager() fieldsets = ( (_('Identification'), {'fields': (('name', 'email'),), 'image': 'photo'}), (_('Access'), {'fields': (('username', 'is_superuser'), ('active',))}), (_('Roles'), {'relations': ('role_set',)}), (_('Permissions Mapping'), {'fields': ('permission_mapping',)}), ) class Meta: verbose_name = _('User') verbose_name_plural = _('Users') list_display = 'photo', 'username', 'name', 'email', 'groups' add_form = 'UserForm' can_admin = _('User Manager') icon = 'fa-users' expose = True # list_template = 'image_cards.html' def __init__(self, *args, **kwargs): super(User, self).__init__(*args, **kwargs) def save(self, *args, **kwargs): if not self.token: self.token = binascii.hexlify(os.urandom(20)).decode() if not self.password: if settings.DEBUG or 'test' in sys.argv or True: password = settings.DEFAULT_PASSWORD else: password = uuid.uuid4().hex self.set_password(password) super(User, self).save(*args, **kwargs) if self.is_superuser: group = Group.objects.get_or_create(name=_('Superuser'))[0] self.groups.add(group) group = Group.objects.get_or_create(name=_('User'))[0] self.groups.add(group) def __str__(self): return self.name or self.username @action(_('Change Password'), input='ChangePasswordForm', inline=True) def change_password(self, new_password, confirm_password): self.set_password(new_password) self.save() @action(_('Send Access Invitation'), inline=True, condition='email', category=None) def send_access_invitation(self): self.send_access_invitation_for_group(None) def send_reset_password_notification(self): project_name = Settings.default().initials subject = '{} - "{}"'.format(_('Reset Password'), project_name) message = _('Click on the button bellow to (re)define your password.') actions = [(_('Reset Password!'), '/admin/password/{}/{}/'.format(self.pk, signing.dumps(self.password)))] send_mail(subject, message, self.email, actions=actions) def send_access_invitation_for_group(self, group): project_name = Settings.default().initials subject = '{} - "{}"'.format(_('System Access'), project_name) if group: extra = _('''If you are already a user, click on the button "Access now!" to authenticate. Otherwise, click on the button "Define password!" to provide your access password.''') message = '''{} <b>{}</b> {} <b>{}</b>. {} '''.format(_('You were registered in the system.'), project_name, _(' as '), group, extra) actions = [ (_('Access now!'), '/admin/'), (_('Define password!'), '/admin/password/{}/{}/'.format(self.pk, signing.dumps(self.password))) ] else: extra = _('Click on the button bellow to (re)define your password.') message = '''{} <b>{}</b>. {}. '''.format(_('You were registered in the system'), project_name, extra) actions = [(_('Access now!'), '/admin/password/{}/{}/'.format(self.pk, signing.dumps(self.password)))] send_mail(subject, message, self.email, actions=actions) def units(self, group_name=None): qs = self.role_set.all() if group_name: qs = qs.filter(group__name=group_name) return qs.values_list('scope', flat=True) def in_group(self, *group_names): return self.role_set.filter(group__name__in=group_names).exists() def in_other_group(self, group_name): return self.is_superuser or self.role_set.exclude(group__name=group_name).exists() def get_appliable_scopes(self): scopes = [] for scope in Scope.objects.filter(pk__in=self.role_set.values_list('scope', flat=True)): if scope not in scopes: scopes.append(scope) if scope.is_organization(): for unit in scope.organization.get_units(): scopes.append(unit) return scopes def apply_current_scope(self, queryset): if self.scope: filters = [] organization_lookups, unit_lookups, role_lookups = self.get_lookups(queryset.model) if self.scope.is_organization(): lookups = organization_lookups else: lookups = unit_lookups for lookup in lookups: filters.append(Q(**{lookup: self.scope.pk})) if filters: queryset = queryset.filter(reduce(operator.__and__, filters)) return queryset def get_lookups(self, model): from djangoplus.cache import CACHE organization_lookups = [] unit_lookups = [] role_lookups = dict() for lookup in get_metadata(model, 'list_lookups', (), iterable=True): field = get_field(model, lookup) if hasattr(field.remote_field.model, 'organization_ptr') or hasattr(field.remote_field.model, 'unit_ptr'): if hasattr(field.remote_field.model, 'organization_ptr'): organization_lookups.append(lookup) if hasattr(field.remote_field.model, 'unit_ptr'): unit_lookups.append(lookup) else: role_username = get_metadata(field.remote_field.model, 'role_username') if role_username: role_lookups[get_metadata(field.remote_field.model, 'verbose_name')] = '{}__{}'.format( lookup, role_username) for subclass in field.remote_field.model.__subclasses__(): role_username = get_metadata(subclass, 'role_username') if role_username: role_lookups[get_metadata(subclass, 'verbose_name')] = '{}__{}__{}'.format( lookup, subclass.__name__.lower(), role_username) if hasattr(model, 'organization_ptr') and 'id' not in organization_lookups: organization_lookups.append('id') if hasattr(model, 'unit_ptr') and 'id' not in unit_lookups: unit_lookups.append('id') if get_metadata(model, 'role_username') and 'id' not in role_lookups: role_lookups[get_metadata(model, 'verbose_name')] = get_metadata(model, 'role_username') for field in get_metadata(model, 'fields') + get_metadata(model, 'many_to_many'): if field.remote_field and field.remote_field.model: if field.remote_field.model in CACHE['ROLE_MODELS']: role_lookups[get_metadata(field.remote_field.model, 'verbose_name')] = '{}__{}'.format(field.name, CACHE['ROLE_MODELS'][field.remote_field.model]['username_field']) if field.remote_field.model in CACHE['ABSTRACT_ROLE_MODELS']: for to in CACHE['ABSTRACT_ROLE_MODELS'][field.remote_field.model]: role_lookups[get_metadata(to, 'verbose_name')] = '{}__{}__{}'.format( field.name, to.__name__.lower(), CACHE['ROLE_MODELS'][to]) if hasattr(field.remote_field.model, 'unit_ptr_id') and field.name not in unit_lookups: unit_lookups.append(field.name) if hasattr(field.remote_field.model, 'organization_ptr_id') and field.name not in organization_lookups: organization_lookups.append(field.name) for organization_lookup in organization_lookups: if CACHE['UNIT_MODEL']: for field in get_metadata(CACHE['ORGANIZATION_MODEL'], 'fields'): if field.remote_field and hasattr(field.remote_field.model, 'unit_ptr'): if organization_lookup == 'id': unit_lookup = field.name else: unit_lookup = '{}__{}'.format(organization_lookup, field.name) if unit_lookup not in unit_lookups and not hasattr(model, 'unit_ptr'): unit_lookups.append(unit_lookup) break for unit_lookup in unit_lookups: if CACHE['ORGANIZATION_MODEL']: for field in get_metadata(CACHE['UNIT_MODEL'], 'fields'): if field.remote_field and hasattr(field.remote_field.model, 'organization_ptr'): if unit_lookup == 'id': organization_lookup = field.name else: organization_lookup = '{}__{}'.format(unit_lookup, field.name) if organization_lookup not in organization_lookups and not hasattr(model, 'organization_ptr'): organization_lookups.append(organization_lookup) return organization_lookups, unit_lookups, role_lookups def get_permission_mapping(self, model, obj=None): from djangoplus.cache import CACHE permission_mapping_key = obj and '{}:{}'.format(model.__name__, type(obj).__name__) or model.__name__ if permission_mapping_key in self.permission_mapping: return self.permission_mapping[permission_mapping_key] organization_lookups, unit_lookups, role_lookups = self.get_lookups(model) lookups = dict(list_lookups=[], edit_lookups=[], delete_lookups=[]) groups = dict() unit_organization_lookup = 'scope__organization' unit_organization_field_name = Unit.get_organization_field_name() if CACHE['UNIT_MODEL'] and unit_organization_field_name: unit_organization_lookup = 'scope__unit__{}__{}'.format( CACHE['UNIT_MODEL'].__name__.lower(), unit_organization_field_name ) scope_queryset = self.role_set.filter( active=True).values_list('group__name', 'scope__organization', 'scope__unit', unit_organization_lookup) for group_name, organization_id, unit_id, unit_organization_id in scope_queryset: if group_name not in groups: groups[group_name] = dict(username_lookups=[], organization_ids=[], unit_ids=[]) if group_name in role_lookups: groups[group_name]['username_lookups'].append(role_lookups[group_name]) if organization_id: groups[group_name]['organization_ids'].append(organization_id) if unit_id: groups[group_name]['unit_ids'].append(unit_id) if unit_organization_id: groups[group_name]['organization_ids'].append(unit_organization_id) if model in CACHE['PERMISSIONS_BY_SCOPE']: can_view_globally = can_edit_globally = can_delete_globally = False for group_name in groups: username_lookups = groups[group_name]['username_lookups'] unit_ids = list(set(groups[group_name]['unit_ids'])) organization_ids = list(set(groups[group_name]['organization_ids'])) can_view = can_view_by_role = can_view_by_unit = can_view_by_organization = False if obj: if type(obj) in CACHE['PERMISSIONS_BY_SCOPE']: can_view = group_name in CACHE['PERMISSIONS_BY_SCOPE'][type(obj)].get('add', []) can_view_by_unit = group_name in CACHE['PERMISSIONS_BY_SCOPE'][type(obj)].get('add_by_unit', []) can_view_by_organization = group_name in CACHE['PERMISSIONS_BY_SCOPE'][type(obj)].get( 'add_by_organization', []) if (can_view or can_view_by_role or can_view_by_unit or can_view_by_organization) is False: can_view = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get('view', []) can_view_by_role = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get('view_by_role', []) can_view_by_unit = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get('view_by_unit', []) can_view_by_organization = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get( 'view_by_organization', []) if can_view: can_view_globally = True else: if can_view_by_role: for username_lookup in username_lookups: lookups['list_lookups'].append((username_lookup, (self.username,))) if can_view_by_unit: if unit_ids: for unit_lookup in unit_lookups: lookups['list_lookups'].append(('{}'.format(unit_lookup), unit_ids)) if can_view_by_organization: if organization_ids: for organization_lookup in organization_lookups: lookups['list_lookups'].append(('{}'.format(organization_lookup), organization_ids)) can_edit = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get('edit', []) can_edit_by_role = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get('edit_by_role', []) can_edit_by_unit = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get('edit_by_unit', []) can_edit_by_organization = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get( 'edit_by_organization', []) if can_edit: can_edit_globally = True else: if can_edit_by_role: for username_lookup in username_lookups: lookups['edit_lookups'].append((username_lookup, (self.username,))) if can_edit_by_unit and unit_ids: for unit_lookup in unit_lookups: lookups['edit_lookups'].append((unit_lookup, unit_ids)) if can_edit_by_organization and organization_ids: for organization_lookup in organization_lookups: lookups['edit_lookups'].append((organization_lookup, organization_ids)) can_delete = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get('delete', []) can_delete_by_role = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get('delete_by_role', []) can_delete_by_unit = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get('delete_by_unit', []) can_delete_by_organization = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get( 'delete_by_organization', []) if can_delete: can_delete_globally = True else: if can_delete_by_role: for username_lookup in username_lookups: lookups['delete_lookups'].append((username_lookup, (self.username,))) if can_delete_by_unit and unit_ids: for unit_lookup in unit_lookups: lookups['delete_lookups'].append((unit_lookup, unit_ids)) if can_delete_by_organization and organization_ids: for organization_lookup in organization_lookups: lookups['delete_lookups'].append((organization_lookup, organization_ids)) for actions_dict in (CACHE['INSTANCE_ACTIONS'], CACHE['QUERYSET_ACTIONS']): for category in actions_dict.get(model, ()): for key in list(actions_dict[model][category].keys()): execute_lookups = [] view_name = actions_dict[model][category][key]['view_name'] can_execute = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get('{}'.format( view_name), []) can_execute_by_role = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get( '{}_by_role'.format(view_name), []) can_execute_by_unit = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get( '{}_by_unit'.format(view_name), []) can_execute_by_organization = group_name in CACHE['PERMISSIONS_BY_SCOPE'][model].get( '{}_by_organization'.format(view_name), []) if can_execute: execute_lookups = None else: if can_execute_by_role: for username_lookup in username_lookups: execute_lookups.append((username_lookup, (self.username,))) if can_execute_by_unit and unit_ids: for unit_lookup in unit_lookups: execute_lookups.append((unit_lookup, unit_ids)) if can_execute_by_organization and organization_ids: for organization_lookup in organization_lookups: execute_lookups.append((organization_lookup, organization_ids)) if execute_lookups: if view_name not in lookups: lookups[view_name] = [] lookups[view_name] += execute_lookups if can_view_globally: lookups['list_lookups'] = [] if can_edit_globally: lookups['edit_lookups'] = [] if can_delete_globally: lookups['delete_lookups'] = [] for codename in ('view', 'list'): if model in CACHE['PERMISSIONS_BY_SCOPE']: if CACHE['PERMISSIONS_BY_SCOPE'][model].get('{}_by_unit'.format(codename)) and not unit_lookups: raise Exception('A "lookup" meta-attribute must point to a Unit model in {}'.format(model)) if CACHE['PERMISSIONS_BY_SCOPE'][model].get('{}_by_organization'.format(codename)) and ( not organization_lookups and not unit_lookups): raise Exception('A "lookup" meta-attribute must point to a Unit or Organization model in {}'.format( model)) if CACHE['PERMISSIONS_BY_SCOPE'][model].get('{}_by_role'.format(codename)) and not role_lookups: raise Exception('A "lookup" meta-attribute must point to a role model in {}'.format(model)) self.permission_mapping[permission_mapping_key] = lookups self.save() return self.permission_mapping[permission_mapping_key] # given a set of group or permission names, this method returns the groups the user belongs to def find_groups(self, perm_or_group, exclude=None): qs = self.groups.all() if perm_or_group: permissions = [] groups = [] for item in perm_or_group: if '.' in item: permissions.append(item.split('.')[1]) else: groups.append(item) if permissions: qs = qs.filter(permissions__codename__in=permissions) if groups: qs = qs.filter(name__in=groups) if exclude: qs = qs.exclude(name=exclude) return qs def email_user(self, subject, message, from_email=None, **kwargs): send_mail(subject, message, from_email, [self.email], **kwargs) def check_role_groups(self): for group in self.groups.all(): self.groups.remove(group) for group in self.role_set.filter(active=True).values_list('group', flat=True).distinct(): self.groups.add(group)
class User(AbstractBaseUser, PermissionsMixin): USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] name = models.CharField(u'Nome', max_length=30, blank=True, search=True) username = models.CharField(u'Login', max_length=30, unique=True) email = models.CharField(u'E-mail', max_length=75, blank=True, default='') active = models.BooleanField(verbose_name=u'Ativo?', default=True, filter=True) photo = models.ImageField(upload_to='profiles', null=True, blank=True, default='', verbose_name=u'Foto', exclude=True) permission_mapping = models.TextField(verbose_name=u'Mapeamento de Permissão', default='{}', exclude=True, display=False) organization = models.ForeignKey(Organization, verbose_name=u'Organização', null=True, blank=True, display=False) unit = models.ForeignKey(Unit, verbose_name=u'Unidade', null=True, blank=True, display=False) objects = UserManager() fieldsets = ( (u'Identificação', {'fields': (('name', 'email'),)}), (u'Acesso', {'fields': (('username', 'is_superuser'), ('active',))}), (u'Funções', {'relations': ('role_set',)}), (u'Mapeamento de Permissão', {'fields': (('organization', 'unit'), 'permission_mapping')}), ) class Meta(): verbose_name = u'Usuário' verbose_name_plural = u'Usuários' list_display = 'username', 'name', 'groups' add_form = 'UserForm' can_admin = u'Gerenciador de Usuários' icon = 'fa-user' def save(self, *args, **kwargs): super(User, self).save(*args, **kwargs) def __unicode__(self): return self.name or self.username @action('Alterar Senha', input='ChangePasswordForm', inline=True) def change_password(self, new_password, confirm_password): self.set_password(new_password) self.save() def units(self, group_name=None): qs = self.role_set.all() if group_name: qs = qs.filter(group__name=group_name) return qs.values_list('units', flat=True) def in_group(self, *group_names): return self.role_set.filter(group__name__in=group_names).exists() def in_other_group(self, group_name): return self.is_superuser or self.role_set.exclude(group__name=group_name).exists() def get_permission_mapping(self, model, obj=None): from djangoplus.cache import loader import json permission_mapping = json.loads(self.permission_mapping or '{}') permission_mapping_key = obj and '%s:%s' % (model.__name__, type(obj).__name__) or model.__name__ if 0 and permission_mapping_key in permission_mapping: return permission_mapping[permission_mapping_key] organization_lookups = [] unit_lookups = [] role_lookups = dict() lookups = dict(list_lookups=[], edit_lookups=[], delete_lookups=[]) for lookup in get_metadata(model, 'list_lookups', (), iterable=True): field = get_field(model, lookup) if hasattr(field.rel.to, 'organization_ptr') or hasattr(field.rel.to, 'unit_ptr'): if hasattr(field.rel.to, 'organization_ptr'): organization_lookups.append(lookup) if hasattr(field.rel.to, 'unit_ptr'): unit_lookups.append(lookup) else: role_username = get_metadata(field.rel.to, 'role_username') if role_username: role_lookups[get_metadata(field.rel.to, 'verbose_name')] = '%s__%s' % (lookup, role_username) for subclass in field.rel.to.__subclasses__(): role_username = get_metadata(subclass, 'role_username') if role_username: role_lookups[get_metadata(subclass, 'verbose_name')] = '%s__%s__%s' % ( lookup, subclass.__name__.lower(), role_username) if hasattr(model, 'organization_ptr') and 'id' not in organization_lookups: organization_lookups.append('id') if hasattr(model, 'unit_ptr') and 'id' not in unit_lookups: unit_lookups.append('id') if get_metadata(model, 'role_username') and 'id' not in role_lookups: role_lookups[get_metadata(model, 'verbose_name')] = get_metadata(model, 'role_username') for field in get_metadata(model, 'fields'): if hasattr(field, 'rel') and field.rel and hasattr(field.rel, 'to') and field.rel.to: if field.rel.to in loader.role_models: role_lookups[get_metadata(field.rel.to, 'verbose_name')] = '%s__%s' % (field.name, loader.role_models[field.rel.to]['username_field']) if field.rel.to in loader.abstract_role_models: for to in loader.abstract_role_models[field.rel.to]: role_lookups[get_metadata(to, 'verbose_name')] = '%s__%s__%s' % ( field.name, to.__name__.lower(), loader.role_models[to]) if hasattr(field.rel.to, 'unit_ptr_id') and field.name not in unit_lookups: unit_lookups.append(field.name) if hasattr(field.rel.to, 'organization_ptr_id') and field.name not in organization_lookups: organization_lookups.append(field.name) for organization_lookup in organization_lookups: if loader.unit_model: if organization_lookup == 'id': unit_lookup = loader.unit_model.__name__.lower() else: unit_lookup = '%s__%s' % (organization_lookup, loader.unit_model.__name__.lower()) if unit_lookup not in unit_lookups and not hasattr(model, 'unit_ptr'): unit_lookups.append(unit_lookup) for unit_lookup in unit_lookups: if loader.organization_model: if unit_lookup == 'id': organization_lookup = loader.organization_model.__name__.lower() else: organization_lookup = '%s__%s' % (unit_lookup, loader.organization_model.__name__.lower()) if organization_lookup not in organization_lookups and not hasattr(model, 'organization_ptr'): organization_lookups.append(organization_lookup) groups = dict() for group_name, organization_id, unit_id in self.role_set.values_list('group__name', 'organizations', 'units'): if group_name not in groups: groups[group_name] = dict(username_lookups=[], organization_ids=[], unit_ids=[]) if group_name in role_lookups: groups[group_name]['username_lookups'].append(role_lookups[group_name]) if organization_id and not self.unit_id and (organization_id == self.organization_id or not self.organization_id): groups[group_name]['organization_ids'].append(organization_id) if self.unit_id or unit_id: groups[group_name]['unit_ids'].append(self.unit_id or unit_id) if model in loader.permissions_by_scope: for group_name in groups: username_lookups = groups[group_name]['username_lookups'] unit_ids = list(set(groups[group_name]['unit_ids'])) organization_ids = list(set(groups[group_name]['organization_ids'])) if obj: can_list = can_list_by_role = can_list_by_unit = can_list_by_organization = False if type(obj) in loader.permissions_by_scope: can_list = group_name in loader.permissions_by_scope[type(obj)].get('add', []) can_list_by_role = group_name in loader.permissions_by_scope[type(obj)].get('add_by_role', []) can_list_by_unit = group_name in loader.permissions_by_scope[type(obj)].get('add_by_unit', []) can_list_by_organization = group_name in loader.permissions_by_scope[type(obj)].get('add_by_organization', []) if (can_list or can_list_by_role or can_list_by_unit or can_list_by_organization) is False: can_list = group_name in loader.permissions_by_scope[type(obj)].get('list', []) can_list_by_role = group_name in loader.permissions_by_scope[type(obj)].get('list_by_role', []) can_list_by_unit = group_name in loader.permissions_by_scope[type(obj)].get('list_by_unit', []) can_list_by_organization = group_name in loader.permissions_by_scope[type(obj)].get('list_by_organization', []) if (can_list or can_list_by_role or can_list_by_unit or can_list_by_organization) is False: can_list = group_name in loader.permissions_by_scope[model].get('list', []) can_list_by_role = group_name in loader.permissions_by_scope[model].get('list_by_role', []) can_list_by_unit = group_name in loader.permissions_by_scope[model].get('list_by_unit', []) can_list_by_organization = group_name in loader.permissions_by_scope[model].get('list_by_organization', []) else: can_list = group_name in loader.permissions_by_scope[model].get('list', []) can_list_by_role = group_name in loader.permissions_by_scope[model].get('list_by_role', []) can_list_by_unit = group_name in loader.permissions_by_scope[model].get('list_by_unit', []) can_list_by_organization = group_name in loader.permissions_by_scope[model].get('list_by_organization', []) if can_list: lookups['list_lookups'] = [] else: if can_list_by_role: for username_lookup in username_lookups: lookups['list_lookups'].append((username_lookup, (self.username,))) if can_list_by_unit or self.unit_id: if unit_ids and 0 not in unit_ids: for unit_lookup in unit_lookups: lookups['list_lookups'].append(('%s' % unit_lookup, unit_ids)) if can_list_by_organization: if organization_ids and 0 not in organization_ids: for organization_lookup in organization_lookups: lookups['list_lookups'].append(('%s' % organization_lookup, organization_ids)) can_edit = group_name in loader.permissions_by_scope[model].get('edit', []) can_edit_by_role = group_name in loader.permissions_by_scope[model].get('edit_by_role', []) can_edit_by_unit = group_name in loader.permissions_by_scope[model].get('edit_by_unit', []) can_edit_by_organization = group_name in loader.permissions_by_scope[model].get('edit_by_organization', []) if can_edit: lookups['edit_lookups'] = None else: if can_edit_by_role: for username_lookup in username_lookups: lookups['edit_lookups'].append((username_lookup, (self.username,))) if can_edit_by_unit and unit_ids: for unit_lookup in unit_lookups: lookups['edit_lookups'].append((unit_lookup, unit_ids)) if can_edit_by_organization and organization_ids: for organization_lookup in organization_lookups: lookups['edit_lookups'].append((organization_lookup, organization_ids)) can_delete = group_name in loader.permissions_by_scope[model].get('delete', []) can_delete_by_role = group_name in loader.permissions_by_scope[model].get('delete_by_role', []) can_delete_by_unit = group_name in loader.permissions_by_scope[model].get('delete_by_unit', []) can_delete_by_organization = group_name in loader.permissions_by_scope[model].get('delete_by_organization', []) if can_delete: lookups['delete_lookups'] = None else: if can_delete_by_role: for username_lookup in username_lookups: lookups['delete_lookups'].append((username_lookup, (self.username,))) if can_delete_by_unit and unit_ids: for unit_lookup in unit_lookups: lookups['delete_lookups'].append((unit_lookup, unit_ids)) if can_delete_by_organization and organization_ids: for organization_lookup in organization_lookups: lookups['delete_lookups'].append((organization_lookup, organization_ids)) for actions_dict in (loader.actions, loader.class_actions): for category in actions_dict.get(model, ()): for key in actions_dict[model][category].keys(): execute_lookups = [] view_name = actions_dict[model][category][key]['view_name'] can_execute = group_name in loader.permissions_by_scope[model].get('%s' % view_name, []) can_execute_by_role = group_name in loader.permissions_by_scope[model].get('%s_by_role' % view_name, []) can_execute_by_unit = group_name in loader.permissions_by_scope[model].get('%s_by_unit' % view_name, []) can_execute_by_organization = group_name in loader.permissions_by_scope[model].get('%s_by_organization' % view_name, []) if can_execute: execute_lookups = None else: if can_execute_by_role: for username_lookup in username_lookups: execute_lookups.append((username_lookup, (self.username,))) if can_execute_by_unit and unit_ids: for unit_lookup in unit_lookups: execute_lookups.append((unit_lookup, unit_ids)) if can_execute_by_organization and organization_ids: for organization_lookup in organization_lookups: execute_lookups.append((organization_lookup, organization_ids)) if execute_lookups: if view_name not in lookups: lookups[view_name] = [] lookups[view_name] += execute_lookups if loader.permissions_by_scope[model].get('list_by_unit') and not unit_lookups: raise Exception('A "lookup" meta-attribute must point to a Unit model in %s' % model) if loader.permissions_by_scope[model].get('list_by_organization') and (not organization_lookups and not unit_lookups): raise Exception('A "lookup" meta-attribute must point to a Unit or Organization model in %s' % model) if loader.permissions_by_scope[model].get('list_by_role') and not role_lookups: raise Exception('A "lookup" meta-attribute must point to a role model in %s' % model) permission_mapping[permission_mapping_key] = lookups self.permission_mapping = json.dumps(permission_mapping) self.save() return permission_mapping[permission_mapping_key] # gieve a set of group or permission names, this method returns the groups the user belongs to def find_groups(self, perm_or_group, exclude=None): qs = self.groups.all() if perm_or_group: permissions = [] groups = [] for item in perm_or_group: if '.' in item: permissions.append(item.split('.')[1]) else: groups.append(item) if permissions: qs = qs.filter(permissions__codename__in=permissions) if groups: qs = qs.filter(name__in=groups) if exclude: qs = qs.exclude(name=exclude) return qs def email_user(self, subject, message, from_email=None, **kwargs): send_mail(subject, message, from_email, [self.email], **kwargs)