Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Django Admin #130

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,6 @@ jobs:
docker stop null_jobs_backend || true
docker rm null_jobs_backend || true
docker run -d --network null_jobs --env-file /home/dev@null/projects/nulljobs/backend/.env null_jobs_backend:latest python manage.py migrate
docker run -d --network null_jobs --env-file /home/dev@null/projects/nulljobs/backend/.env null_jobs_backend:latest python manage.py create_superuser
docker run -d --name null_jobs_backend --network null_jobs --restart always --env-file /home/dev@null/projects/nulljobs/backend/.env null_jobs_backend:latest python manage.py runserver 0.0.0.0:8000
rm -r /tmp/null_job_backend_latest.tar
Empty file.
18 changes: 18 additions & 0 deletions apps/accounts/management/commands/create_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model


class Command(BaseCommand):
help = 'Create an initial admin User'

def handle(self, *args, **kwargs):
User = get_user_model()
if not User.objects.filter(email='', user_type="Moderator").exists():
User.objects.create_superuser(
email='',
name='',
password=''
)
self.stdout.write(self.style.SUCCESS('Successfully created the admin user'))
else:
self.stdout.write(self.style.WARNING('Admin user already exists'))
60 changes: 59 additions & 1 deletion apps/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# from Jobapp.models import User as JobUser
# Create your models here.

USER_TYPE = (("Job Seeker", "User/Employee"), ("Employer", "HR/Employer"))
USER_TYPE = (("Job Seeker", "User/Employee"), ("Employer", "HR/Employer"), ("Moderator", "Admin/Moderator"))


class UserManager(BaseUserManager):
Expand All @@ -33,12 +33,35 @@ def create_superuser(self, email, name, password=None):
email,
password=password,
name=name,
user_type="Moderator" # keep it as it is
)
user.is_admin = True
user.is_staff = True
user.is_moderator = True
user.is_verified = True
user.save(using=self._db)
return user

# todo: to have it when we have moderator dashboard
def create_moderator(self, email, name, password=None):
"""
Creates and saves a superuser with the given email, name, tc and password.
"""
user = self.create_user(
email,
password=password,
name=name,
user_type="Moderator" # as it moderator
)
#
user.is_admin = False # false
user.is_staff = True
user.is_moderator = True
user.save(using=self._db)
return user



class User(AbstractBaseUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

Expand All @@ -51,6 +74,8 @@ class User(AbstractBaseUser):
is_admin = models.BooleanField(default=False, editable=False)
is_moderator = models.BooleanField(default=False, null=True, editable=False)

is_staff = models.BooleanField(default=False)

created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

Expand All @@ -72,3 +97,36 @@ class User(AbstractBaseUser):

class Meta:
db_table = "tbl_user_auth"


def get_full_name(self):
# The user is identified by their email address
return self.email

def get_short_name(self):
# The user is identified by their email address
return self.email

def __str__(self):
return self.email

def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True

def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True

@property
def is_staff_member(self):
"Is the user a member of staff?"
return self.is_staff

@property
def is_admin_member(self):
"Is the user a admin member?"
return self.is_admin

24 changes: 24 additions & 0 deletions apps/accounts/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,27 @@ def validate(self, attrs):

def create(self, validate_data):
return User.objects.create_user(**validate_data)

from django.contrib.auth import get_user_model

User = get_user_model()

class AdminUserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)

class Meta:
model = User
fields = ['email', 'name', 'password']

def create(self, validated_data):
user = User(
email=validated_data['email'],
name=validated_data['name'],
)
user.set_password(validated_data['password'])
user.is_staff = True
user.is_superuser = True # for time being lets keep it this only
user.user_type = "Moderator"
user.is_verified = True
user.save()
return user
3 changes: 2 additions & 1 deletion apps/accounts/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
UserLogOutView,
UserPasswordResetView,
UserProfileView,
UserRegistrationView,
UserRegistrationView, CreateAdminUserView,
)

app_name = "apps.accounts"
Expand Down Expand Up @@ -52,4 +52,5 @@
# google oauth endpoints
path("google/login/", GoogleHandle.as_view(), name="google"),
path("google/login/callback/", CallbackHandleView.as_view(), name="callback"),
path('create-admin', CreateAdminUserView.as_view(), name='create-admin'),
]
34 changes: 32 additions & 2 deletions apps/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.conf import settings
from django.contrib.auth import authenticate
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework import status
from rest_framework import status, generics
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
Expand All @@ -28,10 +28,11 @@
UserPasswordResetSerializer,
UserRegistrationResponseSerializer,
UserRegistrationSerializer,
UserSerializer,
UserSerializer, AdminUserSerializer,
)
from apps.accounts.utils import *
from apps.userprofile.models import UserProfile
import logging

# from django.shortcuts import render

Expand Down Expand Up @@ -473,3 +474,32 @@ def get(self, request):
{"msg": "There was an error authenticating the user"},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)




class IsSuperuserOrStaff(IsAuthenticated):
def has_permission(self, request, view):
return super().has_permission(request, view) and (request.user.is_admin or request.user.is_staff)


class CreateAdminUserView(generics.CreateAPIView):
serializer_class = AdminUserSerializer
permission_classes = [IsSuperuserOrStaff]

def create(self, request, *args, **kwargs):
# Check if the current user email matches the one in the environment variable
admin_email_env = os.getenv('DJANGO_ADMIN_EMAIL')
admin_password_env = os.getenv('DJANGO_ADMIN_PASSWORD')
if not (admin_email_env or admin_password_env):
return Response({'error': 'Admin email is not set in environment variables'},
status=status.HTTP_400_BAD_REQUEST)

if request.user.email != admin_email_env and request.user.password != admin_password_env:
return Response({'error': 'You are not authorized to create a new superuser'},
status=status.HTTP_403_FORBIDDEN)

response = super().create(request, *args, **kwargs)
if response.status_code == status.HTTP_201_CREATED:
logger.info(f"Admin user created: {response.data['email']} by {request.user.email}")
return response
2 changes: 2 additions & 0 deletions apps/applicants/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from django.contrib import admin
from .models import Applicants

admin.site.register(Applicants)
# Register your models here.
6 changes: 5 additions & 1 deletion apps/jobs/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from django.contrib import admin

from .models import Job, ContactMessage, Company
# Register your models here.

admin.site.register(Job)
admin.site.register(ContactMessage)
admin.site.register(Company)
2 changes: 1 addition & 1 deletion apps/jobs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class Meta:
updated_at = models.DateTimeField(auto_now=True) # update timestamp on every save()

# flags are un explained here
is_active = models.BooleanField(default=False, null=False, editable=False)
is_active = models.BooleanField(default=False, null=False)
is_created = models.BooleanField(default=False, null=True, editable=False)
is_deleted = models.BooleanField(default=False, null=True, editable=False)
is_featured = models.BooleanField(default=False, null=True)
Expand Down
5 changes: 4 additions & 1 deletion apps/userprofile/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from django.contrib import admin

from .models import UserProfile, FavoriteProfiles
# Register your models here.

admin.site.register(UserProfile)
admin.site.register(FavoriteProfiles)
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ services:
condition: service_healthy
volumes:
- .:/workspace
command: bash -c "python manage.py loaddata utils/seed/accounts/userauth.json && python manage.py loaddata utils/seed/jobs/company.json && python manage.py loaddata utils/seed/jobs/userprofile.json && python manage.py loaddata utils/seed/jobs/job.json"
# command: bash -c "python manage.py loaddata utils/seed/accounts/userauth.json && python manage.py loaddata utils/seed/jobs/company.json && python manage.py loaddata utils/seed/jobs/job.json && python manage.py loaddata utils/seed/jobs/drf-spectacular.json"
env_file:
- .env

Expand Down
5 changes: 5 additions & 0 deletions null_jobs_backend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@
"PASSWORD": os.getenv("DB_PWD"),
"HOST": os.getenv("DB_HOST"),
"PORT": os.getenv("DB_PORT"),
},
'local': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'mydatabase', # This is where you put the name of the db file.
# If one doesn't exist, it will be created at migration time.
}
}

Expand Down
Loading