mirror of
https://github.com/lemeow125/DRF_Template.git
synced 2025-06-28 16:15:44 +08:00
Clean up docker-compose and run Black formatter over entire codebase
This commit is contained in:
parent
6c232b3e89
commit
069aba80b1
60 changed files with 1946 additions and 1485 deletions
|
@ -6,11 +6,13 @@ from .models import CustomUser
|
|||
|
||||
class CustomUserAdmin(UserAdmin):
|
||||
model = CustomUser
|
||||
list_display = ('id', 'is_active', 'user_group',) + UserAdmin.list_display
|
||||
list_display = (
|
||||
"id",
|
||||
"is_active",
|
||||
"user_group",
|
||||
) + UserAdmin.list_display
|
||||
# Editable fields per instance
|
||||
fieldsets = UserAdmin.fieldsets + (
|
||||
(None, {'fields': ('avatar',)}),
|
||||
)
|
||||
fieldsets = UserAdmin.fieldsets + ((None, {"fields": ("avatar",)}),)
|
||||
|
||||
|
||||
admin.site.register(CustomUser, CustomUserAdmin)
|
||||
|
|
|
@ -2,8 +2,8 @@ from django.apps import AppConfig
|
|||
|
||||
|
||||
class AccountsConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'accounts'
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "accounts"
|
||||
|
||||
def ready(self):
|
||||
import accounts.signals
|
||||
|
|
|
@ -13,38 +13,145 @@ class Migration(migrations.Migration):
|
|||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('user_groups', '0001_initial'),
|
||||
("auth", "0012_alter_user_first_name_max_length"),
|
||||
("user_groups", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CustomUser',
|
||||
name="CustomUser",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
|
||||
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
|
||||
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
|
||||
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
|
||||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||
('avatar', django_resized.forms.ResizedImageField(crop=None, force_format='WEBP', keep_meta=True, null=True, quality=100, scale=None, size=[1920, 1080], upload_to='avatars/')),
|
||||
('onboarding', models.BooleanField(default=True)),
|
||||
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
|
||||
('user_group', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='user_groups.usergroup')),
|
||||
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("password", models.CharField(max_length=128, verbose_name="password")),
|
||||
(
|
||||
"last_login",
|
||||
models.DateTimeField(
|
||||
blank=True, null=True, verbose_name="last login"
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_superuser",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text="Designates that this user has all permissions without explicitly assigning them.",
|
||||
verbose_name="superuser status",
|
||||
),
|
||||
),
|
||||
(
|
||||
"username",
|
||||
models.CharField(
|
||||
error_messages={
|
||||
"unique": "A user with that username already exists."
|
||||
},
|
||||
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
|
||||
max_length=150,
|
||||
unique=True,
|
||||
validators=[
|
||||
django.contrib.auth.validators.UnicodeUsernameValidator()
|
||||
],
|
||||
verbose_name="username",
|
||||
),
|
||||
),
|
||||
(
|
||||
"first_name",
|
||||
models.CharField(
|
||||
blank=True, max_length=150, verbose_name="first name"
|
||||
),
|
||||
),
|
||||
(
|
||||
"last_name",
|
||||
models.CharField(
|
||||
blank=True, max_length=150, verbose_name="last name"
|
||||
),
|
||||
),
|
||||
(
|
||||
"email",
|
||||
models.EmailField(
|
||||
blank=True, max_length=254, verbose_name="email address"
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_staff",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text="Designates whether the user can log into this admin site.",
|
||||
verbose_name="staff status",
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_active",
|
||||
models.BooleanField(
|
||||
default=True,
|
||||
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
|
||||
verbose_name="active",
|
||||
),
|
||||
),
|
||||
(
|
||||
"date_joined",
|
||||
models.DateTimeField(
|
||||
default=django.utils.timezone.now, verbose_name="date joined"
|
||||
),
|
||||
),
|
||||
(
|
||||
"avatar",
|
||||
django_resized.forms.ResizedImageField(
|
||||
crop=None,
|
||||
force_format="WEBP",
|
||||
keep_meta=True,
|
||||
null=True,
|
||||
quality=100,
|
||||
scale=None,
|
||||
size=[1920, 1080],
|
||||
upload_to="avatars/",
|
||||
),
|
||||
),
|
||||
("onboarding", models.BooleanField(default=True)),
|
||||
(
|
||||
"groups",
|
||||
models.ManyToManyField(
|
||||
blank=True,
|
||||
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
|
||||
related_name="user_set",
|
||||
related_query_name="user",
|
||||
to="auth.group",
|
||||
verbose_name="groups",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user_group",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="user_groups.usergroup",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user_permissions",
|
||||
models.ManyToManyField(
|
||||
blank=True,
|
||||
help_text="Specific permissions for this user.",
|
||||
related_name="user_set",
|
||||
related_query_name="user",
|
||||
to="auth.permission",
|
||||
verbose_name="user permissions",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user',
|
||||
'verbose_name_plural': 'users',
|
||||
'abstract': False,
|
||||
"verbose_name": "user",
|
||||
"verbose_name_plural": "users",
|
||||
"abstract": False,
|
||||
},
|
||||
managers=[
|
||||
('objects', django.contrib.auth.models.UserManager()),
|
||||
("objects", django.contrib.auth.models.UserManager()),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -15,14 +15,16 @@ class CustomUser(AbstractUser):
|
|||
# is_admin inherited from base user class
|
||||
|
||||
avatar = ResizedImageField(
|
||||
null=True, force_format="WEBP", quality=100, upload_to='avatars/')
|
||||
null=True, force_format="WEBP", quality=100, upload_to="avatars/"
|
||||
)
|
||||
|
||||
# Used for onboarding processes
|
||||
# Set this to False later on once the user makes actions
|
||||
onboarding = models.BooleanField(default=True)
|
||||
|
||||
user_group = models.ForeignKey(
|
||||
'user_groups.UserGroup', on_delete=models.SET_NULL, null=True)
|
||||
"user_groups.UserGroup", on_delete=models.SET_NULL, null=True
|
||||
)
|
||||
|
||||
@property
|
||||
def group_member(self):
|
||||
|
@ -57,4 +59,4 @@ class CustomUser(AbstractUser):
|
|||
|
||||
@property
|
||||
def admin_url(self):
|
||||
return reverse('admin:users_customuser_change', args=(self.pk,))
|
||||
return reverse("admin:users_customuser_change", args=(self.pk,))
|
||||
|
|
|
@ -8,13 +8,14 @@ from django.core.cache import cache
|
|||
from django.core import exceptions as django_exceptions
|
||||
from rest_framework.settings import api_settings
|
||||
from django.contrib.auth.password_validation import validate_password
|
||||
|
||||
# There can be multiple subject instances with the same name, only differing in course, year level, and semester. We filter them here
|
||||
|
||||
|
||||
class SimpleCustomUserSerializer(ModelSerializer):
|
||||
class Meta(BaseUserSerializer.Meta):
|
||||
model = CustomUser
|
||||
fields = ('id', 'username', 'email', 'full_name')
|
||||
fields = ("id", "username", "email", "full_name")
|
||||
|
||||
|
||||
class CustomUserSerializer(BaseUserSerializer):
|
||||
|
@ -22,19 +23,36 @@ class CustomUserSerializer(BaseUserSerializer):
|
|||
|
||||
class Meta(BaseUserSerializer.Meta):
|
||||
model = CustomUser
|
||||
fields = ('id', 'username', 'email', 'avatar', 'first_name',
|
||||
'last_name', 'user_group', 'group_member', 'group_owner')
|
||||
read_only_fields = ('id', 'username', 'email', 'user_group',
|
||||
'group_member', 'group_owner')
|
||||
fields = (
|
||||
"id",
|
||||
"username",
|
||||
"email",
|
||||
"avatar",
|
||||
"first_name",
|
||||
"is_new",
|
||||
"last_name",
|
||||
"user_group",
|
||||
"group_member",
|
||||
"group_owner",
|
||||
)
|
||||
read_only_fields = (
|
||||
"id",
|
||||
"username",
|
||||
"email",
|
||||
"user_group",
|
||||
"group_member",
|
||||
"group_owner",
|
||||
)
|
||||
|
||||
def to_representation(self, instance):
|
||||
representation = super().to_representation(instance)
|
||||
representation['user_group'] = SimpleUserGroupSerializer(
|
||||
instance.user_group, many=False).data
|
||||
representation["user_group"] = SimpleUserGroupSerializer(
|
||||
instance.user_group, many=False
|
||||
).data
|
||||
return representation
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
cache.delete(f'user:{instance.id}')
|
||||
cache.delete(f"user:{instance.id}")
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
|
||||
|
@ -42,16 +60,18 @@ class UserRegistrationSerializer(serializers.ModelSerializer):
|
|||
email = serializers.EmailField(required=True)
|
||||
username = serializers.CharField(required=True)
|
||||
password = serializers.CharField(
|
||||
write_only=True, style={'input_type': 'password', 'placeholder': 'Password'})
|
||||
write_only=True, style={"input_type": "password", "placeholder": "Password"}
|
||||
)
|
||||
first_name = serializers.CharField(
|
||||
required=True, allow_blank=False, allow_null=False)
|
||||
required=True, allow_blank=False, allow_null=False
|
||||
)
|
||||
last_name = serializers.CharField(
|
||||
required=True, allow_blank=False, allow_null=False)
|
||||
required=True, allow_blank=False, allow_null=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = CustomUser
|
||||
fields = ['email', 'username', 'password',
|
||||
'first_name', 'last_name']
|
||||
fields = ["email", "username", "password", "first_name", "last_name"]
|
||||
|
||||
def validate(self, attrs):
|
||||
user_attrs = attrs.copy()
|
||||
|
@ -69,14 +89,15 @@ class UserRegistrationSerializer(serializers.ModelSerializer):
|
|||
raise serializers.ValidationError({"password": errors})
|
||||
if self.Meta.model.objects.filter(username=attrs.get("username")).exists():
|
||||
raise serializers.ValidationError(
|
||||
"A user with that username already exists.")
|
||||
"A user with that username already exists."
|
||||
)
|
||||
return super().validate(attrs)
|
||||
|
||||
def create(self, validated_data):
|
||||
user = self.Meta.model(**validated_data)
|
||||
user.username = validated_data['username']
|
||||
user.username = validated_data["username"]
|
||||
user.is_active = False
|
||||
user.set_password(validated_data['password'])
|
||||
user.set_password(validated_data["password"])
|
||||
user.save()
|
||||
|
||||
return user
|
||||
|
|
|
@ -12,38 +12,37 @@ import json
|
|||
@receiver(post_migrate)
|
||||
def create_users(sender, **kwargs):
|
||||
if sender.name == "accounts":
|
||||
with open(os.path.join(ROOT_DIR, 'seed_data.json'), "r") as f:
|
||||
with open(os.path.join(ROOT_DIR, "seed_data.json"), "r") as f:
|
||||
seed_data = json.loads(f.read())
|
||||
for user in seed_data['users']:
|
||||
USER = CustomUser.objects.filter(
|
||||
email=user['email']).first()
|
||||
for user in seed_data["users"]:
|
||||
USER = CustomUser.objects.filter(email=user["email"]).first()
|
||||
if not USER:
|
||||
if user['password'] == 'USE_REGULAR':
|
||||
password = get_secret('SEED_DATA_PASSWORD')
|
||||
elif user['password'] == 'USE_ADMIN':
|
||||
password = get_secret('SEED_DATA_ADMIN_PASSWORD')
|
||||
if user["password"] == "USE_REGULAR":
|
||||
password = get_secret("SEED_DATA_PASSWORD")
|
||||
elif user["password"] == "USE_ADMIN":
|
||||
password = get_secret("SEED_DATA_ADMIN_PASSWORD")
|
||||
else:
|
||||
password = user['password']
|
||||
if (user['is_superuser'] == True):
|
||||
password = user["password"]
|
||||
if user["is_superuser"] == True:
|
||||
# Admin users are created regardless of SEED_DATA value
|
||||
USER = CustomUser.objects.create_superuser(
|
||||
username=user['username'],
|
||||
email=user['email'],
|
||||
username=user["username"],
|
||||
email=user["email"],
|
||||
password=password,
|
||||
)
|
||||
print('Created Superuser:', user['email'])
|
||||
print("Created Superuser:", user["email"])
|
||||
else:
|
||||
# Only create non-admin users if SEED_DATA=True
|
||||
if SEED_DATA:
|
||||
USER = CustomUser.objects.create_user(
|
||||
username=user['email'],
|
||||
email=user['email'],
|
||||
username=user["email"],
|
||||
email=user["email"],
|
||||
password=password,
|
||||
)
|
||||
print('Created User:', user['email'])
|
||||
print("Created User:", user["email"])
|
||||
|
||||
USER.first_name = user['first_name']
|
||||
USER.last_name = user['last_name']
|
||||
USER.first_name = user["first_name"]
|
||||
USER.last_name = user["last_name"]
|
||||
USER.is_active = True
|
||||
USER.save()
|
||||
|
||||
|
@ -51,53 +50,57 @@ def create_users(sender, **kwargs):
|
|||
@receiver(post_migrate)
|
||||
def create_celery_beat_schedules(sender, **kwargs):
|
||||
if sender.name == "django_celery_beat":
|
||||
with open(os.path.join(ROOT_DIR, 'seed_data.json'), "r") as f:
|
||||
with open(os.path.join(ROOT_DIR, "seed_data.json"), "r") as f:
|
||||
seed_data = json.loads(f.read())
|
||||
# Creating Schedules
|
||||
for schedule in seed_data['schedules']:
|
||||
if schedule['type'] == 'crontab':
|
||||
for schedule in seed_data["schedules"]:
|
||||
if schedule["type"] == "crontab":
|
||||
# Check if Schedule already exists
|
||||
SCHEDULE = CrontabSchedule.objects.filter(minute=schedule['minute'],
|
||||
hour=schedule['hour'],
|
||||
day_of_week=schedule['day_of_week'],
|
||||
day_of_month=schedule['day_of_month'],
|
||||
month_of_year=schedule['month_of_year'],
|
||||
timezone=schedule['timezone']
|
||||
).first()
|
||||
SCHEDULE = CrontabSchedule.objects.filter(
|
||||
minute=schedule["minute"],
|
||||
hour=schedule["hour"],
|
||||
day_of_week=schedule["day_of_week"],
|
||||
day_of_month=schedule["day_of_month"],
|
||||
month_of_year=schedule["month_of_year"],
|
||||
timezone=schedule["timezone"],
|
||||
).first()
|
||||
# If it does not exist, create a new Schedule
|
||||
if not SCHEDULE:
|
||||
SCHEDULE = CrontabSchedule.objects.create(
|
||||
minute=schedule['minute'],
|
||||
hour=schedule['hour'],
|
||||
day_of_week=schedule['day_of_week'],
|
||||
day_of_month=schedule['day_of_month'],
|
||||
month_of_year=schedule['month_of_year'],
|
||||
timezone=schedule['timezone']
|
||||
minute=schedule["minute"],
|
||||
hour=schedule["hour"],
|
||||
day_of_week=schedule["day_of_week"],
|
||||
day_of_month=schedule["day_of_month"],
|
||||
month_of_year=schedule["month_of_year"],
|
||||
timezone=schedule["timezone"],
|
||||
)
|
||||
print(
|
||||
f'Created Crontab Schedule for Hour:{SCHEDULE.hour},Minute:{SCHEDULE.minute}')
|
||||
f"Created Crontab Schedule for Hour:{SCHEDULE.hour},Minute:{SCHEDULE.minute}"
|
||||
)
|
||||
else:
|
||||
print(
|
||||
f'Crontab Schedule for Hour:{SCHEDULE.hour},Minute:{SCHEDULE.minute} already exists')
|
||||
for task in seed_data['scheduled_tasks']:
|
||||
TASK = PeriodicTask.objects.filter(name=task['name']).first()
|
||||
f"Crontab Schedule for Hour:{SCHEDULE.hour},Minute:{SCHEDULE.minute} already exists"
|
||||
)
|
||||
for task in seed_data["scheduled_tasks"]:
|
||||
TASK = PeriodicTask.objects.filter(name=task["name"]).first()
|
||||
if not TASK:
|
||||
if task['schedule']['type'] == 'crontab':
|
||||
SCHEDULE = CrontabSchedule.objects.filter(minute=task['schedule']['minute'],
|
||||
hour=task['schedule']['hour'],
|
||||
day_of_week=task['schedule']['day_of_week'],
|
||||
day_of_month=task['schedule']['day_of_month'],
|
||||
month_of_year=task['schedule']['month_of_year'],
|
||||
timezone=task['schedule']['timezone']
|
||||
).first()
|
||||
if task["schedule"]["type"] == "crontab":
|
||||
SCHEDULE = CrontabSchedule.objects.filter(
|
||||
minute=task["schedule"]["minute"],
|
||||
hour=task["schedule"]["hour"],
|
||||
day_of_week=task["schedule"]["day_of_week"],
|
||||
day_of_month=task["schedule"]["day_of_month"],
|
||||
month_of_year=task["schedule"]["month_of_year"],
|
||||
timezone=task["schedule"]["timezone"],
|
||||
).first()
|
||||
TASK = PeriodicTask.objects.create(
|
||||
crontab=SCHEDULE,
|
||||
name=task['name'],
|
||||
task=task['task'],
|
||||
enabled=task['enabled']
|
||||
name=task["name"],
|
||||
task=task["task"],
|
||||
enabled=task["enabled"],
|
||||
)
|
||||
print(f'Created Periodic Task: {TASK.name}')
|
||||
print(f"Created Periodic Task: {TASK.name}")
|
||||
else:
|
||||
raise Exception('Schedule for Periodic Task not found')
|
||||
raise Exception("Schedule for Periodic Task not found")
|
||||
else:
|
||||
print(f'Periodic Task: {TASK.name} already exists')
|
||||
print(f"Periodic Task: {TASK.name} already exists")
|
||||
|
|
|
@ -4,20 +4,26 @@ from celery import shared_task
|
|||
@shared_task
|
||||
def get_paying_users():
|
||||
from subscriptions.models import UserSubscription
|
||||
|
||||
# Get a list of user subscriptions
|
||||
active_subscriptions = UserSubscription.objects.filter(
|
||||
valid=True).distinct('user')
|
||||
active_subscriptions = UserSubscription.objects.filter(valid=True).distinct("user")
|
||||
|
||||
# Get paying users
|
||||
active_users = []
|
||||
|
||||
# Paying regular users
|
||||
active_users += [
|
||||
subscription.user.id for subscription in active_subscriptions if subscription.user is not None and subscription.user.user_group is None]
|
||||
subscription.user.id
|
||||
for subscription in active_subscriptions
|
||||
if subscription.user is not None and subscription.user.user_group is None
|
||||
]
|
||||
|
||||
# Paying users within groups
|
||||
active_users += [
|
||||
subscription.user_group.members for subscription in active_subscriptions if subscription.user_group is not None and subscription.user is None]
|
||||
subscription.user_group.members
|
||||
for subscription in active_subscriptions
|
||||
if subscription.user_group is not None and subscription.user is None
|
||||
]
|
||||
|
||||
# Return paying users
|
||||
return active_users
|
||||
|
|
|
@ -3,10 +3,10 @@ from rest_framework.routers import DefaultRouter
|
|||
from accounts import views
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register(r'users', views.CustomUserViewSet, basename='users')
|
||||
router.register(r"users", views.CustomUserViewSet, basename="users")
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
path('', include('djoser.urls')),
|
||||
path('', include('djoser.urls.jwt')),
|
||||
path("", include(router.urls)),
|
||||
path("", include("djoser.urls")),
|
||||
path("", include("djoser.urls.jwt")),
|
||||
]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext as _
|
||||
import re
|
||||
|
@ -6,9 +5,10 @@ import re
|
|||
|
||||
class UppercaseValidator(object):
|
||||
def validate(self, password, user=None):
|
||||
if not re.findall('[A-Z]', password):
|
||||
if not re.findall("[A-Z]", password):
|
||||
raise ValidationError(
|
||||
_("The password must contain at least 1 uppercase letter (A-Z)."))
|
||||
_("The password must contain at least 1 uppercase letter (A-Z).")
|
||||
)
|
||||
|
||||
def get_help_text(self):
|
||||
return _("Your password must contain at least 1 uppercase letter (A-Z).")
|
||||
|
@ -16,9 +16,10 @@ class UppercaseValidator(object):
|
|||
|
||||
class LowercaseValidator(object):
|
||||
def validate(self, password, user=None):
|
||||
if not re.findall('[a-z]', password):
|
||||
if not re.findall("[a-z]", password):
|
||||
raise ValidationError(
|
||||
_("The password must contain at least 1 lowercase letter (a-z)."))
|
||||
_("The password must contain at least 1 lowercase letter (a-z).")
|
||||
)
|
||||
|
||||
def get_help_text(self):
|
||||
return _("Your password must contain at least 1 lowercase letter (a-z).")
|
||||
|
@ -26,19 +27,25 @@ class LowercaseValidator(object):
|
|||
|
||||
class SpecialCharacterValidator(object):
|
||||
def validate(self, password, user=None):
|
||||
if not re.findall('[@#$%^&*()_+/\<>;:!?]', password):
|
||||
if not re.findall("[@#$%^&*()_+/\<>;:!?]", password):
|
||||
raise ValidationError(
|
||||
_("The password must contain at least 1 special character (@, #, $, etc.)."))
|
||||
_(
|
||||
"The password must contain at least 1 special character (@, #, $, etc.)."
|
||||
)
|
||||
)
|
||||
|
||||
def get_help_text(self):
|
||||
return _("Your password must contain at least 1 special character (@, #, $, etc.).")
|
||||
return _(
|
||||
"Your password must contain at least 1 special character (@, #, $, etc.)."
|
||||
)
|
||||
|
||||
|
||||
class NumberValidator(object):
|
||||
def validate(self, password, user=None):
|
||||
if not any(char.isdigit() for char in password):
|
||||
raise ValidationError(
|
||||
_("The password must contain at least one numerical digit (0-9)."))
|
||||
_("The password must contain at least one numerical digit (0-9).")
|
||||
)
|
||||
|
||||
def get_help_text(self):
|
||||
return _("Your password must contain at least numerical digit (0-9).")
|
||||
|
|
|
@ -22,28 +22,27 @@ class CustomUserViewSet(DjoserUserViewSet):
|
|||
user = self.request.user
|
||||
# If user is admin, show all active users
|
||||
if user.is_superuser:
|
||||
key = 'users'
|
||||
key = "users"
|
||||
# Get cache
|
||||
queryset = cache.get(key)
|
||||
# Set cache if stale or does not exist
|
||||
if not queryset:
|
||||
queryset = CustomUser.objects.filter(is_active=True)
|
||||
cache.set(key, queryset, 60*60)
|
||||
cache.set(key, queryset, 60 * 60)
|
||||
return queryset
|
||||
elif not user.user_group:
|
||||
key = f'user:{user.id}'
|
||||
key = f"user:{user.id}"
|
||||
queryset = cache.get(key)
|
||||
if not queryset:
|
||||
queryset = CustomUser.objects.filter(is_active=True)
|
||||
cache.set(key, queryset, 60*60)
|
||||
cache.set(key, queryset, 60 * 60)
|
||||
return queryset
|
||||
elif user.user_group:
|
||||
key = f'usergroup_users:{user.user_group.id}'
|
||||
key = f"usergroup_users:{user.user_group.id}"
|
||||
queryset = cache.get(key)
|
||||
if not queryset:
|
||||
queryset = CustomUser.objects.filter(
|
||||
user_group=user.user_group)
|
||||
cache.set(key, queryset, 60*60)
|
||||
queryset = CustomUser.objects.filter(user_group=user.user_group)
|
||||
cache.set(key, queryset, 60 * 60)
|
||||
return queryset
|
||||
else:
|
||||
return CustomUser.objects.none()
|
||||
|
@ -52,10 +51,10 @@ class CustomUserViewSet(DjoserUserViewSet):
|
|||
user = self.request.user
|
||||
|
||||
# Clear cache
|
||||
cache.delete(f'users')
|
||||
cache.delete(f'user:{user.id}')
|
||||
cache.delete(f"users")
|
||||
cache.delete(f"user:{user.id}")
|
||||
if user.user_group:
|
||||
cache.delete(f'usergroup_users:{user.user_group.id}')
|
||||
cache.delete(f"usergroup_users:{user.user_group.id}")
|
||||
|
||||
super().perform_update(serializer, *args, **kwargs)
|
||||
user = serializer.instance
|
||||
|
@ -84,16 +83,18 @@ class CustomUserViewSet(DjoserUserViewSet):
|
|||
settings.EMAIL.confirmation(self.request, context).send(to)
|
||||
|
||||
# Clear cache
|
||||
cache.delete('users')
|
||||
cache.delete(f'user:{user.id}')
|
||||
cache.delete("users")
|
||||
cache.delete(f"user:{user.id}")
|
||||
if user.user_group:
|
||||
cache.delete(f'usergroup_users:{user.user_group.id}')
|
||||
cache.delete(f"usergroup_users:{user.user_group.id}")
|
||||
|
||||
except Exception as e:
|
||||
print('Warning: Unable to send email')
|
||||
print("Warning: Unable to send email")
|
||||
print(e)
|
||||
|
||||
@action(methods=['post'], detail=False, url_path='activation', url_name='activation')
|
||||
@action(
|
||||
methods=["post"], detail=False, url_path="activation", url_name="activation"
|
||||
)
|
||||
def activation(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
@ -103,16 +104,16 @@ class CustomUserViewSet(DjoserUserViewSet):
|
|||
|
||||
# Construct a response with user's first name, last name, and email
|
||||
user_data = {
|
||||
'first_name': user.first_name,
|
||||
'last_name': user.last_name,
|
||||
'email': user.email,
|
||||
'username': user.username
|
||||
"first_name": user.first_name,
|
||||
"last_name": user.last_name,
|
||||
"email": user.email,
|
||||
"username": user.username,
|
||||
}
|
||||
|
||||
# Clear cache
|
||||
cache.delete('users')
|
||||
cache.delete(f'user:{user.id}')
|
||||
cache.delete("users")
|
||||
cache.delete(f"user:{user.id}")
|
||||
if user.user_group:
|
||||
cache.delete(f'usergroup_users:{user.user_group.id}')
|
||||
cache.delete(f"usergroup_users:{user.user_group.id}")
|
||||
|
||||
return Response(user_data, status=status.HTTP_200_OK)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue