feat(models): Add a Profile model
This simplifies the management of the views data
This commit is contained in:
parent
8599992dd7
commit
7581bf59df
4 changed files with 82 additions and 32 deletions
37
src/dgsi/migrations/0001_initial.py
Normal file
37
src/dgsi/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# Generated by Django 4.2.12 on 2024-09-13 14:30
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Profile",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"user",
|
||||||
|
models.OneToOneField(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -1 +1,31 @@
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from functools import cached_property
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from asgiref.sync import async_to_sync
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.db import models
|
||||||
|
from kanidm.models.person import Person
|
||||||
|
|
||||||
|
from shared.kanidm import client
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class KanidmProfile:
|
||||||
|
person: Person
|
||||||
|
secret: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
|
class Profile(models.Model):
|
||||||
|
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def kanidm_profile(self):
|
||||||
|
person = async_to_sync(client.person_account_get)(self.user.username)
|
||||||
|
data = async_to_sync(client.get_radius_token)(self.user.username).data
|
||||||
|
|
||||||
|
secret = data.get("secret") if data is not None else None
|
||||||
|
|
||||||
|
return KanidmProfile(person, secret)
|
||||||
|
|
|
@ -1,35 +1,18 @@
|
||||||
# Create your views here.
|
|
||||||
import json
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from asgiref.sync import async_to_sync
|
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.db.models import QuerySet
|
from django.contrib.auth.models import User
|
||||||
from django.views.generic import DetailView
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
from shared.kanidm import client
|
|
||||||
|
|
||||||
User = get_user_model()
|
|
||||||
|
|
||||||
|
|
||||||
class ProfileView(LoginRequiredMixin, DetailView):
|
class ProfileView(LoginRequiredMixin, TemplateView):
|
||||||
model = User
|
model = User
|
||||||
template_name = "account/profile.html"
|
template_name = "account/profile.html"
|
||||||
|
|
||||||
def get_object(self, queryset: Optional[QuerySet] = None):
|
def get_context_data(self, **kwargs):
|
||||||
assert isinstance(self.request.user, User)
|
assert isinstance(self.request.user, User)
|
||||||
|
|
||||||
return self.request.user
|
return super().get_context_data(
|
||||||
|
# Pyright throws a fit as it doesn't detect the reverse relation
|
||||||
def get_context_data(self, **kwargs):
|
# giving a user its profile
|
||||||
ctx = super().get_context_data(**kwargs)
|
profile=self.request.user.profile.kanidm_profile, # pyright: ignore
|
||||||
|
**kwargs
|
||||||
username = self.request.user.get_username()
|
)
|
||||||
|
|
||||||
ctx["person"] = async_to_sync(client.person_account_get)(username)
|
|
||||||
|
|
||||||
content: str = async_to_sync(client.get_radius_token)(username).content
|
|
||||||
|
|
||||||
ctx["radius_secret"] = json.loads(content).get("secret")
|
|
||||||
return ctx
|
|
||||||
|
|
|
@ -2,24 +2,24 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2 class="subtitle">
|
<h2 class="subtitle">
|
||||||
<span>Profil de {{ person.displayname }}</span>
|
<span>Profil de {{ profile.person.displayname }}</span>
|
||||||
<span class="tag is-primary is-medium is-pulled-right">{{ person.name }}</span>
|
<span class="tag is-primary is-medium is-pulled-right">{{ profile.person.name }}</span>
|
||||||
</h2>
|
</h2>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<h3 class="has-text-weight-bold mb-3">Identifiant unique :</h3>
|
<h3 class="has-text-weight-bold mb-3">Identifiant unique :</h3>
|
||||||
|
|
||||||
<span class="button is-fullwidth">{{ person.uuid }}</span>
|
<span class="button is-fullwidth">{{ profile.person.uuid }}</span>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<h3 class="has-text-weight-bold mb-3">Token RADIUS :</h3>
|
<h3 class="has-text-weight-bold mb-3">Token RADIUS :</h3>
|
||||||
|
|
||||||
<span class="button is-fullwidth">{{ radius_secret }}</span>
|
<span class="button is-fullwidth">{{ profile.secret }}</span>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<h3 class="has-text-weight-bold mb-3">Membre des groupes suivants :</h3>
|
<h3 class="has-text-weight-bold mb-3">Membre des groupes suivants :</h3>
|
||||||
|
|
||||||
{% for group in person.memberof %}
|
{% for group in profile.person.memberof %}
|
||||||
<span class="button is-fullwidth">{{ group }}</span><br>
|
<span class="button is-fullwidth">{{ group }}</span><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue