refactored roles, refactored response for User detail view

This commit is contained in:
Anatoly 2020-01-14 18:40:30 +03:00
parent 1ed384ded2
commit 5c95c4923f
12 changed files with 225 additions and 41 deletions

View File

@ -8,11 +8,13 @@ from account import models
@admin.register(models.Role) @admin.register(models.Role)
class RoleAdmin(admin.ModelAdmin): class RoleAdmin(admin.ModelAdmin):
list_display = ['role', 'country'] list_display = ['role', 'country']
raw_id_fields = ['country', ]
@admin.register(models.UserRole) @admin.register(models.UserRole)
class UserRoleAdmin(admin.ModelAdmin): class UserRoleAdmin(admin.ModelAdmin):
list_display = ['user', 'role', 'establishment'] list_display = ['user', 'role', 'establishment', ]
raw_id_fields = ['user', 'role', 'establishment', 'requester', ]
@admin.register(models.User) @admin.register(models.User)

View File

@ -0,0 +1,26 @@
# Generated by Django 2.2.7 on 2020-01-14 13:11
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('main', '0046_auto_20200114_1218'),
('account', '0031_user_last_country'),
]
operations = [
migrations.AddField(
model_name='role',
name='navigation_bar_permission',
field=models.ForeignKey(blank=True, help_text='navigation bar item permission', null=True, on_delete=django.db.models.deletion.SET_NULL, to='main.NavigationBarPermission', verbose_name='navigation bar permission'),
),
migrations.AlterField(
model_name='userrole',
name='requester',
field=models.ForeignKey(blank=True, default=None, help_text='A user (REQUESTER) who requests a role change for a USER', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='roles_requested', to=settings.AUTH_USER_MODEL),
),
]

View File

@ -53,6 +53,7 @@ class Role(ProjectBaseMixin):
(LIQUOR_REVIEWER, 'Liquor reviewer'), (LIQUOR_REVIEWER, 'Liquor reviewer'),
(PRODUCT_REVIEWER, 'Product reviewer'), (PRODUCT_REVIEWER, 'Product reviewer'),
) )
role = models.PositiveIntegerField(verbose_name=_('Role'), choices=ROLE_CHOICES, role = models.PositiveIntegerField(verbose_name=_('Role'), choices=ROLE_CHOICES,
null=False, blank=False) null=False, blank=False)
country = models.ForeignKey(Country, verbose_name=_('Country'), country = models.ForeignKey(Country, verbose_name=_('Country'),
@ -62,6 +63,11 @@ class Role(ProjectBaseMixin):
establishment_subtype = models.ForeignKey(EstablishmentSubType, establishment_subtype = models.ForeignKey(EstablishmentSubType,
verbose_name=_('Establishment subtype'), verbose_name=_('Establishment subtype'),
null=True, blank=True, on_delete=models.SET_NULL) null=True, blank=True, on_delete=models.SET_NULL)
navigation_bar_permission = models.ForeignKey('main.NavigationBarPermission',
blank=True, null=True,
on_delete=models.SET_NULL,
help_text='navigation bar item permission',
verbose_name=_('navigation bar permission'))
class UserManager(BaseUserManager): class UserManager(BaseUserManager):
@ -348,6 +354,7 @@ class UserRole(ProjectBaseMixin):
(CANCELLED, _('cancelled')), (CANCELLED, _('cancelled')),
(REJECTED, _('rejected')) (REJECTED, _('rejected'))
) )
user = models.ForeignKey( user = models.ForeignKey(
'account.User', verbose_name=_('User'), on_delete=models.CASCADE) 'account.User', verbose_name=_('User'), on_delete=models.CASCADE)
role = models.ForeignKey( role = models.ForeignKey(
@ -358,9 +365,11 @@ class UserRole(ProjectBaseMixin):
state = models.CharField( state = models.CharField(
_('state'), choices=STATE_CHOICES, max_length=10, default=PENDING) _('state'), choices=STATE_CHOICES, max_length=10, default=PENDING)
requester = models.ForeignKey( requester = models.ForeignKey('account.User', on_delete=models.SET_NULL,
'account.User', blank=True, null=True, default=None, related_name='roles_requested', blank=True, null=True, default=None,
on_delete=models.SET_NULL) related_name='roles_requested',
help_text='A user (REQUESTER) who requests a '
'role change for a USER')
class Meta: class Meta:
unique_together = ['user', 'role', 'establishment', 'state'] unique_together = ['user', 'role', 'establishment', 'state']

View File

@ -0,0 +1,3 @@
from account.serializers.common import *
from account.serializers.web import *
from account.serializers.back import *

View File

@ -3,15 +3,7 @@ from rest_framework import serializers
from account import models from account import models
from account.models import User from account.models import User
from main.models import SiteSettings from main.models import SiteSettings
# from account.serializers.common import RoleBaseSerializer
class RoleSerializer(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = [
'role',
'country'
]
class _SiteSettingsSerializer(serializers.ModelSerializer): class _SiteSettingsSerializer(serializers.ModelSerializer):
@ -26,6 +18,7 @@ class _SiteSettingsSerializer(serializers.ModelSerializer):
class BackUserSerializer(serializers.ModelSerializer): class BackUserSerializer(serializers.ModelSerializer):
last_country = _SiteSettingsSerializer(read_only=True) last_country = _SiteSettingsSerializer(read_only=True)
# roles = RoleBaseSerializer(many=True, read_only=True)
class Meta: class Meta:
model = User model = User
@ -45,12 +38,12 @@ class BackUserSerializer(serializers.ModelSerializer):
'unconfirmed_email', 'unconfirmed_email',
'email_confirmed', 'email_confirmed',
'newsletter', 'newsletter',
'roles',
'password', 'password',
'city', 'city',
'locale', 'locale',
'last_ip', 'last_ip',
'last_country', 'last_country',
# 'roles',
) )
extra_kwargs = { extra_kwargs = {
'password': {'write_only': True}, 'password': {'write_only': True},

View File

@ -1,7 +1,7 @@
"""Common account serializers""" """Common account serializers"""
from django.conf import settings from django.conf import settings
from django.utils.translation import gettext_lazy as _
from django.contrib.auth import password_validation as password_validators from django.contrib.auth import password_validation as password_validators
from django.utils.translation import gettext_lazy as _
from fcm_django.models import FCMDevice from fcm_django.models import FCMDevice
from rest_framework import exceptions from rest_framework import exceptions
from rest_framework import serializers from rest_framework import serializers
@ -11,9 +11,25 @@ from account import models, tasks
from notification.models import Subscriber from notification.models import Subscriber
from utils import exceptions as utils_exceptions from utils import exceptions as utils_exceptions
from utils import methods as utils_methods from utils import methods as utils_methods
from main.serializers import NavigationBarPermissionBaseSerializer
# User serializers # User serializers
class RoleBaseSerializer(serializers.ModelSerializer):
"""Serializer for model Role."""
role_display = serializers.CharField(source='get_role_display', read_only=True)
navigation_bar_permission = NavigationBarPermissionBaseSerializer(read_only=True)
class Meta:
"""Meta class."""
model = models.Role
fields = [
'id',
'role_display',
'navigation_bar_permission',
]
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
"""User serializer.""" """User serializer."""
# RESPONSE # RESPONSE
@ -26,6 +42,7 @@ class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField( email = serializers.EmailField(
validators=(rest_validators.UniqueValidator(queryset=models.User.objects.all()),), validators=(rest_validators.UniqueValidator(queryset=models.User.objects.all()),),
required=False) required=False)
roles = RoleBaseSerializer(many=True, read_only=True)
class Meta: class Meta:
model = models.User model = models.User
@ -39,6 +56,7 @@ class UserSerializer(serializers.ModelSerializer):
'email', 'email',
'email_confirmed', 'email_confirmed',
'newsletter', 'newsletter',
'roles',
] ]
extra_kwargs = { extra_kwargs = {
'first_name': {'required': False, 'write_only': True, }, 'first_name': {'required': False, 'write_only': True, },

View File

@ -6,9 +6,9 @@ from account.views import back as views
app_name = 'account' app_name = 'account'
urlpatterns = [ urlpatterns = [
path('role/', views.RoleLstView.as_view(), name='role-list-create'), path('role/', views.RoleListView.as_view(), name='role-list-create'),
path('user-role/', views.UserRoleLstView.as_view(), name='user-role-list-create'), path('user-role/', views.UserRoleListView.as_view(), name='user-role-list-create'),
path('user/', views.UserLstView.as_view(), name='user-create-list'), path('user/', views.UserListView.as_view(), name='user-create-list'),
path('user/<int:id>/', views.UserRUDView.as_view(), name='user-rud'), path('user/<int:id>/', views.UserRUDView.as_view(), name='user-rud'),
path('user/<int:id>/csv/', views.get_user_csv, name='user-csv'), path('user/<int:id>/csv/', views.get_user_csv, name='user-csv'),
] ]

View File

@ -8,19 +8,20 @@ from rest_framework.authtoken.models import Token
from account import models from account import models
from account.models import User from account.models import User
from account.serializers import back as serializers from account.serializers import back as serializers
from account.serializers.common import RoleBaseSerializer
class RoleLstView(generics.ListCreateAPIView): class RoleListView(generics.ListCreateAPIView):
serializer_class = serializers.RoleSerializer serializer_class = RoleBaseSerializer
queryset = models.Role.objects.all() queryset = models.Role.objects.all()
class UserRoleLstView(generics.ListCreateAPIView): class UserRoleListView(generics.ListCreateAPIView):
serializer_class = serializers.UserRoleSerializer serializer_class = serializers.UserRoleSerializer
queryset = models.UserRole.objects.all() queryset = models.UserRole.objects.all()
class UserLstView(generics.ListCreateAPIView): class UserListView(generics.ListCreateAPIView):
"""User list create view.""" """User list create view."""
queryset = User.objects.prefetch_related('roles') queryset = User.objects.prefetch_related('roles')
serializer_class = serializers.BackUserSerializer serializer_class = serializers.BackUserSerializer

View File

@ -14,6 +14,14 @@ class SiteSettingsAdmin(admin.ModelAdmin):
inlines = [SiteSettingsInline, ] inlines = [SiteSettingsInline, ]
@admin.register(models.SiteFeature)
class SiteFeatureAdmin(admin.ModelAdmin):
"""Site feature admin conf."""
list_display = ['id', 'site_settings', 'feature',
'published', 'main', 'backoffice', ]
raw_id_fields = ['site_settings', 'feature', ]
@admin.register(models.Feature) @admin.register(models.Feature)
class FeatureAdmin(admin.ModelAdmin): class FeatureAdmin(admin.ModelAdmin):
"""Feature admin conf.""" """Feature admin conf."""
@ -80,3 +88,14 @@ class PanelAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'user', 'created',) list_display = ('id', 'name', 'user', 'created',)
raw_id_fields = ('user',) raw_id_fields = ('user',)
list_display_links = ('id', 'name',) list_display_links = ('id', 'name',)
@admin.register(models.NavigationBarPermission)
class NavigationBarPermissionAdmin(admin.ModelAdmin):
"""NavigationBarPermission admin."""
list_display = ('section', 'permission_mode_display', )
raw_id_fields = ('section', )
def permission_mode_display(self, obj):
"""Get permission mode display."""
return obj.get_permission_mode_display()

View File

@ -0,0 +1,44 @@
# Generated by Django 2.2.7 on 2020-01-14 12:18
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('main', '0045_carousel_is_international'),
]
operations = [
migrations.AddField(
model_name='sitefeature',
name='backoffice',
field=models.BooleanField(default=False, help_text='shows on backoffice page', verbose_name='backoffice'),
),
migrations.AlterField(
model_name='sitefeature',
name='main',
field=models.BooleanField(default=False, help_text='shows on main page', verbose_name='Main'),
),
migrations.AlterField(
model_name='sitefeature',
name='nested',
field=models.ManyToManyField(to='main.SiteFeature', blank=True),
),
migrations.CreateModel(
name='NavigationBarPermission',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('permission_mode', models.PositiveSmallIntegerField(choices=[(0, 'read'), (1, 'write')], default=0, help_text='READ - allows only retrieve data,WRITE - allows to perform any operations over the object', verbose_name='permission mode')),
('section', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.SiteFeature', verbose_name='section')),
],
options={
'verbose_name': 'Navigation bar item permission',
'verbose_name_plural': 'Navigation bar item permissions',
},
),
]

View File

@ -6,10 +6,11 @@ from django.contrib.contenttypes import fields as generic
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.fields import JSONField from django.contrib.postgres.fields import JSONField
from django.core.validators import EMPTY_VALUES from django.core.validators import EMPTY_VALUES
from django.db import connections, connection from django.db import connections
from django.db import models from django.db import models
from django.db.models import Q from django.db.models import Q
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from mptt.models import MPTTModel, TreeForeignKey
from rest_framework import exceptions from rest_framework import exceptions
from configuration.models import TranslationSettings from configuration.models import TranslationSettings
@ -144,9 +145,15 @@ class SiteFeature(ProjectBaseMixin):
site_settings = models.ForeignKey(SiteSettings, on_delete=models.CASCADE) site_settings = models.ForeignKey(SiteSettings, on_delete=models.CASCADE)
feature = models.ForeignKey(Feature, on_delete=models.PROTECT) feature = models.ForeignKey(Feature, on_delete=models.PROTECT)
published = models.BooleanField(default=False, verbose_name=_('Published')) published = models.BooleanField(default=False, verbose_name=_('Published'))
main = models.BooleanField(default=False, verbose_name=_('Main')) main = models.BooleanField(default=False,
nested = models.ManyToManyField('self', symmetrical=False) help_text='shows on main page',
verbose_name=_('Main'),)
backoffice = models.BooleanField(default=False,
help_text='shows on backoffice page',
verbose_name=_('backoffice'),)
nested = models.ManyToManyField('self', blank=True, symmetrical=False)
old_id = models.IntegerField(null=True, blank=True) old_id = models.IntegerField(null=True, blank=True)
objects = SiteFeatureQuerySet.as_manager() objects = SiteFeatureQuerySet.as_manager()
@ -520,3 +527,29 @@ class Panel(ProjectBaseMixin):
params = params + new_params params = params + new_params
query = self.query + limit_offset query = self.query + limit_offset
return query, params return query, params
class NavigationBarPermission(ProjectBaseMixin):
"""Model for navigation bar item permissions."""
READ = 0
WRITE = 1
PERMISSION_MODES = (
(READ, _('read')),
(WRITE, _('write')),
)
section = models.ForeignKey('main.SiteFeature',
on_delete=models.CASCADE,
verbose_name=_('section'))
permission_mode = models.PositiveSmallIntegerField(choices=PERMISSION_MODES,
default=READ,
help_text='READ - allows only retrieve data,'
'WRITE - allows to perform any '
'operations over the object',
verbose_name=_('permission mode'))
class Meta:
"""Meta class."""
verbose_name = _('Navigation bar item permission')
verbose_name_plural = _('Navigation bar item permissions')

View File

@ -2,11 +2,11 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from rest_framework import serializers from rest_framework import serializers
from account.models import User
from account.serializers.back import BackUserSerializer
from location.serializers import CountrySerializer from location.serializers import CountrySerializer
from main import models from main import models
from utils.serializers import ProjectModelSerializer, TranslatedField, RecursiveFieldSerializer from utils.serializers import ProjectModelSerializer, TranslatedField, RecursiveFieldSerializer
from account.serializers.back import BackUserSerializer
from account.models import User
class FeatureSerializer(serializers.ModelSerializer): class FeatureSerializer(serializers.ModelSerializer):
@ -84,24 +84,43 @@ class FooterBackSerializer(FooterSerializer):
class SiteFeatureSerializer(serializers.ModelSerializer): class SiteFeatureSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(source='feature.id') id = serializers.IntegerField(source='feature.id', allow_null=True)
slug = serializers.CharField(source='feature.slug') slug = serializers.CharField(source='feature.slug', allow_null=True)
priority = serializers.IntegerField(source='feature.priority') priority = serializers.IntegerField(source='feature.priority', allow_null=True)
route = serializers.CharField(source='feature.route.name') route = serializers.CharField(source='feature.route.name', allow_null=True)
source = serializers.IntegerField(source='feature.source') source = serializers.IntegerField(source='feature.source', allow_null=True)
nested = RecursiveFieldSerializer(many=True, allow_null=True) nested = RecursiveFieldSerializer(many=True, read_only=True, allow_null=True)
class Meta: class Meta:
"""Meta class.""" """Meta class."""
model = models.SiteFeature model = models.SiteFeature
fields = ('main', fields = (
'id', 'id',
'slug', 'main',
'priority', 'slug',
'route', 'priority',
'source', 'route',
'nested', 'source',
) 'nested',
)
class NavigationBarSectionBaseSerializer(SiteFeatureSerializer):
"""Serializer for navigation bar."""
source_display = serializers.CharField(source='feature.get_source_display',
read_only=True)
class Meta(SiteFeatureSerializer.Meta):
model = models.SiteFeature
fields = [
'id',
'slug',
'route',
'source',
'source_display',
'priority',
'nested',
]
class SiteSettingsSerializer(serializers.ModelSerializer): class SiteSettingsSerializer(serializers.ModelSerializer):
@ -331,3 +350,20 @@ class PanelExecuteSerializer(serializers.ModelSerializer):
'user', 'user',
'user_id' 'user_id'
] ]
class NavigationBarPermissionBaseSerializer(serializers.ModelSerializer):
"""Navigation bar permission serializer."""
section = NavigationBarSectionBaseSerializer(read_only=True)
permission_mode_display = serializers.CharField(source='get_permission_mode_display',
read_only=True)
class Meta:
"""Meta class."""
model = models.NavigationBarPermission
fields = [
'id',
'section',
'permission_mode_display',
]