Base user profile
This commit is contained in:
parent
c04d9410e9
commit
de34f1daf9
11 changed files with 130 additions and 4 deletions
|
@ -1,6 +1,7 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
from django.contrib import messages
|
||||||
|
|
||||||
from autosecretkey import AutoSecretKey
|
from autosecretkey import AutoSecretKey
|
||||||
from reportmonster.classes.config import MonsterConfig
|
from reportmonster.classes.config import MonsterConfig
|
||||||
|
@ -166,6 +167,8 @@ else:
|
||||||
# Login System
|
# Login System
|
||||||
|
|
||||||
LOGIN_URL = reverse_lazy("core:login")
|
LOGIN_URL = reverse_lazy("core:login")
|
||||||
|
LOGIN_REDIRECT_URL = reverse_lazy("core:dashboard")
|
||||||
|
LOGOUT_REDIRECT_URL = reverse_lazy("core:index")
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
|
|
||||||
|
@ -182,3 +185,13 @@ LOGGING = {
|
||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Messages
|
||||||
|
|
||||||
|
MESSAGE_TAGS = {
|
||||||
|
messages.DEBUG: 'alert-info',
|
||||||
|
messages.INFO: 'alert-info',
|
||||||
|
messages.SUCCESS: 'alert-success',
|
||||||
|
messages.WARNING: 'alert-warning',
|
||||||
|
messages.ERROR: 'alert-danger',
|
||||||
|
}
|
|
@ -7,6 +7,8 @@ from reportmonster.classes.vessel import Vessel
|
||||||
|
|
||||||
from bcrypt import checkpw
|
from bcrypt import checkpw
|
||||||
|
|
||||||
|
from ..models.auth import Profile
|
||||||
|
|
||||||
|
|
||||||
class ReportMonsterBackend(ModelBackend):
|
class ReportMonsterBackend(ModelBackend):
|
||||||
def authenticate(self, request, username: str = None, password: str = None):
|
def authenticate(self, request, username: str = None, password: str = None):
|
||||||
|
@ -17,9 +19,18 @@ class ReportMonsterBackend(ModelBackend):
|
||||||
filter(lambda x: x.name == settings.LOGIN_VESSEL, monster.vessels)
|
filter(lambda x: x.name == settings.LOGIN_VESSEL, monster.vessels)
|
||||||
)[0]
|
)[0]
|
||||||
|
|
||||||
|
try:
|
||||||
userdata = list(loginvessel.getUsers(username=username).values())[0]
|
userdata = list(loginvessel.getUsers(username=username).values())[0]
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
|
||||||
if checkpw(password.encode(), userdata["password"].encode()):
|
if checkpw(password.encode(), userdata["password"].encode()):
|
||||||
user, _ = get_user_model().objects.get_or_create(email=username)
|
user, _ = get_user_model().objects.get_or_create(email=username)
|
||||||
user.save()
|
user.save()
|
||||||
|
profile, _ = Profile.objects.get_or_create(user=user)
|
||||||
|
profile.first_name = userdata["firstname"]
|
||||||
|
profile.last_name = userdata["lastname"]
|
||||||
|
profile.save()
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
return
|
||||||
|
|
33
core/migrations/0003_vessel_profile.py
Normal file
33
core/migrations/0003_vessel_profile.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# Generated by Django 4.1.1 on 2022-09-16 15:22
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0002_alter_user_totp'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Vessel',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=64)),
|
||||||
|
('imo', models.IntegerField(blank=True, null=True)),
|
||||||
|
('mmsi', models.IntegerField(blank=True, null=True)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Profile',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('first_name', models.CharField(max_length=128)),
|
||||||
|
('last_name', models.CharField(max_length=128)),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
20
core/migrations/0004_alter_profile_user.py
Normal file
20
core/migrations/0004_alter_profile_user.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 4.1.1 on 2022-09-16 15:22
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0003_vessel_profile'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='user',
|
||||||
|
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 4.1.1 on 2022-09-16 15:33
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0004_alter_profile_user'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='first_name',
|
||||||
|
field=models.CharField(blank=True, max_length=128, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='last_name',
|
||||||
|
field=models.CharField(blank=True, max_length=128, null=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -27,6 +27,17 @@ class User(AbstractBaseUser, PermissionsMixin):
|
||||||
return self.email
|
return self.email
|
||||||
|
|
||||||
|
|
||||||
|
class Profile(models.Model):
|
||||||
|
user = models.OneToOneField(User, models.CASCADE)
|
||||||
|
first_name = models.CharField(max_length=128, null=True, blank=True)
|
||||||
|
last_name = models.CharField(max_length=128, null=True, blank=True)
|
||||||
|
|
||||||
|
def get_full_name(self):
|
||||||
|
return f"{self.first_name or ''} {self.last_name or ''}"
|
||||||
|
|
||||||
|
__str__ = get_full_name
|
||||||
|
|
||||||
|
|
||||||
class OTPSession(models.Model):
|
class OTPSession(models.Model):
|
||||||
uuid = models.UUIDField(default=uuid4)
|
uuid = models.UUIDField(default=uuid4)
|
||||||
user = models.ForeignKey(User, models.CASCADE)
|
user = models.ForeignKey(User, models.CASCADE)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
from django.contrib.auth.views import LogoutView
|
||||||
|
|
||||||
from ..views import LoginView, OTPView
|
from ..views import LoginView, OTPView
|
||||||
|
|
||||||
|
@ -6,4 +7,5 @@ from ..views import LoginView, OTPView
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("login/", LoginView.as_view(), name="login"),
|
path("login/", LoginView.as_view(), name="login"),
|
||||||
path("login/checkotp/", OTPView.as_view(), name="checkotp"),
|
path("login/checkotp/", OTPView.as_view(), name="checkotp"),
|
||||||
|
path("logout/", LogoutView.as_view(), name="logout"),
|
||||||
]
|
]
|
|
@ -6,5 +6,5 @@ from ..views.frontend import DashboardView, NotImplementedView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("dashboard/", DashboardView.as_view(), name="dashboard"),
|
path("dashboard/", DashboardView.as_view(), name="dashboard"),
|
||||||
path("", RedirectView.as_view(url=reverse_lazy("core:dashboard"))),
|
path("", RedirectView.as_view(url=reverse_lazy("core:dashboard")), name="index"),
|
||||||
]
|
]
|
|
@ -8,7 +8,7 @@ from django.core.exceptions import PermissionDenied
|
||||||
from django.http.response import HttpResponseRedirect
|
from django.http.response import HttpResponseRedirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from ..models.auth import OTPSession
|
from ..models.auth import OTPSession, Profile
|
||||||
from ..forms.auth import OTPForm
|
from ..forms.auth import OTPForm
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ class LoginView(DjangoLoginView):
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
if not (user := form.get_user()).totp:
|
if not (user := form.get_user()).totp:
|
||||||
login(self.request, user)
|
login(self.request, user)
|
||||||
|
profile, _ = Profile.objects.get_or_create(user=user)
|
||||||
|
profile.save()
|
||||||
return HttpResponseRedirect(self.get_success_url())
|
return HttpResponseRedirect(self.get_success_url())
|
||||||
|
|
||||||
session = OTPSession.objects.create(user=user)
|
session = OTPSession.objects.create(user=user)
|
||||||
|
@ -55,4 +57,6 @@ class OTPView(DjangoLoginView):
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
login(self.request, self.get_otpsession().user)
|
login(self.request, self.get_otpsession().user)
|
||||||
del request.session["OTPSession"]
|
del request.session["OTPSession"]
|
||||||
|
profile, _ = Profile.objects.get_or_create(user=user)
|
||||||
|
profile.save()
|
||||||
return HttpResponseRedirect(self.get_success_url())
|
return HttpResponseRedirect(self.get_success_url())
|
||||||
|
|
|
@ -20,6 +20,15 @@
|
||||||
<a href="/"><b>Acade</b>Mon</a>
|
<a href="/"><b>Acade</b>Mon</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% for message in messages %}
|
||||||
|
<div class="alert {{ message.tags }} alert-dismissible shadow fade show" role="alert">
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
{{ message | safe }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body login-card-body">
|
<div class="card-body login-card-body">
|
||||||
<p class="login-box-msg">Sign in using your Sea Chefs Academy credentials</p>
|
<p class="login-box-msg">Sign in using your Sea Chefs Academy credentials</p>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<img src="{% static "core/dist/images/noavatar.jpg" %}" class="img-circle elevation-2" alt="User Image">
|
<img src="{% static "core/dist/images/noavatar.jpg" %}" class="img-circle elevation-2" alt="User Image">
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<a href="#" class="d-block">{{ user.get_username }}</a>
|
<a href="#" class="d-block">{{ user.profile.get_full_name }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue