diff --git a/core/forms/profiles.py b/core/forms/profiles.py new file mode 100644 index 0000000..e477b8a --- /dev/null +++ b/core/forms/profiles.py @@ -0,0 +1,15 @@ +from django.forms import ModelForm, CharField, EmailField +from django.contrib.auth import get_user_model +from django.utils.translation import gettext_lazy as _ + +from core.models import AdminProfile + +class AdminEditForm(ModelForm): + #fields from User model that you want to edit + first_name = CharField(required=True, label=_('First Name')) + last_name = CharField(required=True, label=_('Last Name')) + email = EmailField(required=True, labels=_("Email Address")) + + class Meta: + model = AdminProfile + fields = ('first_name', 'last_name', "email", 'mobile', "role", "image") \ No newline at end of file diff --git a/core/models/files.py b/core/models/files.py index 03fab66..eaa4cb0 100644 --- a/core/models/files.py +++ b/core/models/files.py @@ -1,13 +1,31 @@ -from django.db.models import Model, CharField, ImageField, FileField +from django.db.models import Model, CharField, ImageField, FileField, ManyToManyField, ForeignKey, BooleanField, CASCADE +from django.contrib.auth import get_user_model + +from polymorphic.models import PolymorphicModel from core.helpers.files import generate_storage_filename +from core.models.profiles import Profile # Create your models here. -class ImageFile(Model): +class BaseFile(PolymorphicModel): filename = CharField(max_length=255) - file = ImageField(upload_to=generate_storage_filename) -class File(Model): - filename = CharField(max_length=255) - file = FileField(upload_to=generate_storage_filename) \ No newline at end of file +class ImageFile(BaseFile): + rawfile = ImageField(upload_to=generate_storage_filename) + + @property + def get_file(self): + return self.image + +class File(BaseFile): + rawfile = FileField(upload_to=generate_storage_filename) + + @property + def get_file(self): + return self.file + +class FileAssociation(Model): + file = ForeignKey(BaseFile, CASCADE) + user = ForeignKey(get_user_model(), CASCADE) + visible = BooleanField() \ No newline at end of file diff --git a/core/modules/urls.py b/core/modules/urls.py index 00a6a84..69654b5 100644 --- a/core/modules/urls.py +++ b/core/modules/urls.py @@ -3,16 +3,52 @@ import importlib from django.conf import settings from django.urls import path -from core.views import DashboardView, LoginView, OTPSelectorView, LogoutView, OTPValidatorView, BackendNotImplementedView +from core.views import ( + DashboardView, + LoginView, + OTPSelectorView, + LogoutView, + OTPValidatorView, + BackendNotImplementedView, + AdminListView, + AdminDeleteView, + AdminEditView, + AdminCreateView, + DBSettingsListView, + DBSettingsEditView, + DBSettingsDeleteView, + DBSettingsCreateView, +) -URLPATTERNS = [ - path('login/', LoginView.as_view(), name="login"), - path('login/otp/select/', OTPSelectorView.as_view(), name="otpselector"), - path('login/otp/validate/', OTPValidatorView.as_view(), name="otpvalidator"), - path('logout/', LogoutView.as_view(), name="logout"), - path('admin/', DashboardView.as_view(), name="dashboard"), - path('admin/oops/', BackendNotImplementedView.as_view(), name="backendni") -] +URLPATTERNS = [] + +# Auth URLs + +URLPATTERNS.append(path('login/', LoginView.as_view(), name="login")) +URLPATTERNS.append(path('login/otp/select/', OTPSelectorView.as_view(), name="otpselector")) +URLPATTERNS.append(path('login/otp/validate/', OTPValidatorView.as_view(), name="otpvalidator")) +URLPATTERNS.append(path('logout/', LogoutView.as_view(), name="logout")) + +# Base Backend URLs + +URLPATTERNS.append(path('admin/', DashboardView.as_view(), name="dashboard")) +URLPATTERNS.append(path('admin/oops/', BackendNotImplementedView.as_view(), name="backendni")) + +# Backend Database Settings URLs + +URLPATTERNS.append(path("admin/dbsettings/", DBSettingsListView.as_view(), name="dbsettings")) +URLPATTERNS.append(path("admin/dbsettings//delete/", DBSettingsDeleteView.as_view(), name="dbsettings_delete")) +URLPATTERNS.append(path("admin/dbsettings//edit/", DBSettingsEditView.as_view(), name="dbsettings_edit")) +URLPATTERNS.append(path("admin/dbsettings/create/", DBSettingsCreateView.as_view(), name="dbsettings_create")) + +# Backend User Administration URLs + +URLPATTERNS.append(path('admin/profiles/', AdminListView.as_view(), name="admins")) +URLPATTERNS.append(path("admin/profiles//delete/", AdminDeleteView.as_view(), name="admins_delete")) +URLPATTERNS.append(path("admin/profiles//edit/", AdminEditView.as_view(), name="admins_edit")) +URLPATTERNS.append(path("admin/profiles/create/", AdminCreateView.as_view(), name="admins_create")) + +# External Module URLs for module in settings.EXPEPHALON_MODULES: try: @@ -21,12 +57,3 @@ for module in settings.EXPEPHALON_MODULES: URLPATTERNS.append(path(f'admin/modules/{module}/{url}', action, name=f"{module}_{name}")) except (AttributeError, ModuleNotFoundError): pass - -try: - from core.views import DBSettingsListView, DBSettingsEditView, DBSettingsDeleteView, DBSettingsCreateView - URLPATTERNS.append(path("admin/dbsettings/", DBSettingsListView.as_view(), name="dbsettings")) - URLPATTERNS.append(path("admin/dbsettings//delete/", DBSettingsDeleteView.as_view(), name="dbsettings_delete")) - URLPATTERNS.append(path("admin/dbsettings//edit/", DBSettingsEditView.as_view(), name="dbsettings_edit")) - URLPATTERNS.append(path("admin/dbsettings/create/", DBSettingsCreateView.as_view(), name="dbsettings_create")) -except: - pass \ No newline at end of file diff --git a/core/receivers/__init__.py b/core/receivers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/receivers/profiles.py b/core/receivers/profiles.py new file mode 100644 index 0000000..bf5fed7 --- /dev/null +++ b/core/receivers/profiles.py @@ -0,0 +1,7 @@ +from django.db.models.signals import post_delete + +from core.models.profiles import AdminProfile + +@receiver(post_delete, sender=AdminProfile) +def delete_user(sender, instance, *args, **kwargs): + instance.user.delete() \ No newline at end of file diff --git a/core/views/__init__.py b/core/views/__init__.py index 3452b12..e07a4f4 100644 --- a/core/views/__init__.py +++ b/core/views/__init__.py @@ -4,6 +4,7 @@ from django.conf import settings from core.views.dbsettings import * from core.views.auth import * +from core.views.profiles import * # Create your views here. diff --git a/core/views/dbsettings.py b/core/views/dbsettings.py index 244a82b..6e1b7a8 100644 --- a/core/views/dbsettings.py +++ b/core/views/dbsettings.py @@ -2,49 +2,45 @@ from django.conf import settings from django.views.generic import ListView, UpdateView, DeleteView, CreateView from django.urls import reverse_lazy -try: - from dbsettings.models import Setting +from dbsettings.models import Setting - class DBSettingsListView(ListView): - template_name = f"{settings.EXPEPHALON_BACKEND}/dbsettings/index.html" - model = Setting +class DBSettingsListView(ListView): + template_name = f"{settings.EXPEPHALON_BACKEND}/dbsettings/index.html" + model = Setting - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context["title"] = "Database Settings" - return context + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Database Settings" + return context - class DBSettingsEditView(UpdateView): - template_name = f"{settings.EXPEPHALON_BACKEND}/dbsettings/update.html" - model = Setting - success_url = reverse_lazy("dbsettings") - fields = ["key", "value"] +class DBSettingsEditView(UpdateView): + template_name = f"{settings.EXPEPHALON_BACKEND}/dbsettings/update.html" + model = Setting + success_url = reverse_lazy("dbsettings") + fields = ["key", "value"] - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context["title"] = "Edit Setting" - return context + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Edit Setting" + return context - class DBSettingsDeleteView(DeleteView): - template_name = f"{settings.EXPEPHALON_BACKEND}/dbsettings/delete.html" - model = Setting - success_url = reverse_lazy("dbsettings") +class DBSettingsDeleteView(DeleteView): + template_name = f"{settings.EXPEPHALON_BACKEND}/dbsettings/delete.html" + model = Setting + success_url = reverse_lazy("dbsettings") - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context["title"] = "Delete Setting" - return context + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Delete Setting" + return context - class DBSettingsCreateView(CreateView): - template_name = f"{settings.EXPEPHALON_BACKEND}/dbsettings/create.html" - model = Setting - success_url = reverse_lazy("dbsettings") - fields = ["key", "value"] +class DBSettingsCreateView(CreateView): + template_name = f"{settings.EXPEPHALON_BACKEND}/dbsettings/create.html" + model = Setting + success_url = reverse_lazy("dbsettings") + fields = ["key", "value"] - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context["title"] = "Create Setting" - return context - -except ModuleNotFoundError: - pass + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Create Setting" + return context diff --git a/core/views/profiles.py b/core/views/profiles.py new file mode 100644 index 0000000..b704246 --- /dev/null +++ b/core/views/profiles.py @@ -0,0 +1,47 @@ +from django.conf import settings +from django.views.generic import FormView, ListView, DeleteView +from django.urls import reverse_lazy +from django.contrib.auth import get_user_model + +from core.models import AdminProfile + +class AdminListView(ListView): + template_name = f"{settings.EXPEPHALON_BACKEND}/profiles/index.html" + model = AdminProfile + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Administrator Users" + return context + +class AdminEditView(FormView): + template_name = f"{settings.EXPEPHALON_BACKEND}/profiles/update.html" + model = get_user_model() + success_url = reverse_lazy("dbsettings") + fields = ["key", "value"] + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Edit Setting" + return context + +class AdminDeleteView(DeleteView): + template_name = f"{settings.EXPEPHALON_BACKEND}/profiles/delete.html" + model = get_user_model() + success_url = reverse_lazy("dbsettings") + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Delete Administrator" + return context + +class AdminCreateView(FormView): + template_name = f"{settings.EXPEPHALON_BACKEND}/profiles/create.html" + model = get_user_model() + success_url = reverse_lazy("dbsettings") + fields = ["key", "value"] + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Create Setting" + return context diff --git a/templates/backend/profiles/create.html b/templates/backend/profiles/create.html new file mode 100644 index 0000000..dcd49dd --- /dev/null +++ b/templates/backend/profiles/create.html @@ -0,0 +1,57 @@ +{% extends "backend/base.html" %} +{% load bootstrap4 %} +{% block content %} +
+
+
+
+ + +
+
Administrator Users - Create User +
Create a new administrator +
+
+
+
+ + +
+
+
+
+
+
+
+
+ + Create Administrator +
+
+
+
+
+
+ {% csrf_token %} + {% bootstrap_form form %} + {% buttons %} + + + Cancel + + {% endbuttons %} +
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/backend/profiles/delete.html b/templates/backend/profiles/delete.html new file mode 100644 index 0000000..1329afe --- /dev/null +++ b/templates/backend/profiles/delete.html @@ -0,0 +1,57 @@ +{% extends "backend/base.html" %} +{% load bootstrap4 %} +{% block content %} +
+
+
+
+ + +
+
Administrator Users - Delete User +
Delete an administrator from the system +
+
+
+
+ + +
+
+
+
+
+
+
+
+ + Deleting {{ object.user.username }} +
+
+
+
+
+
+ {% csrf_token %} + Are you sure you wish to delete {{ object.user.username }}? This will irrevocably delete their account and any associated information. You can also disable the user without deleting their data! + {% buttons %} + + + Cancel + + {% endbuttons %} +
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/backend/profiles/index.html b/templates/backend/profiles/index.html new file mode 100644 index 0000000..90d7d11 --- /dev/null +++ b/templates/backend/profiles/index.html @@ -0,0 +1,67 @@ +{% extends "backend/base.html" %} +{% block content %} +
+
+
+
+ + +
+
Administrator Users +
Create, edit and delete users with backend access +
+
+
+ +
+
+
+
+
+
+
+ + Active Users +
+
+
+
+
+
+ + + + + + + + + + + + + {% for admin in object_list %} + + + + + + + + + {% endfor %} + +
First NameLast NameRoleEmailMobileOptions
{{ admin.user.first_name }}{{ admin.user.last_name }}{{ admin.role }}{{ admin.user.username }}{{ admin.mobile }}
+
+
+
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/backend/profiles/update.html b/templates/backend/profiles/update.html new file mode 100644 index 0000000..9822e91 --- /dev/null +++ b/templates/backend/profiles/update.html @@ -0,0 +1,57 @@ +{% extends "backend/base.html" %} +{% load bootstrap4 %} +{% block content %} +
+
+
+
+ + +
+
Administrator Users - Edit User +
Edit adminstrator user properties +
+
+
+
+ + +
+
+
+
+
+
+
+
+ + Editing {{ form.email.value }} +
+
+
+
+
+
+ {% csrf_token %} + {% bootstrap_form form %} + {% buttons %} + + + Cancel + + {% endbuttons %} +
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file