feat: Add trust bridge and user activation

This commit is contained in:
aldrin 2021-08-02 14:25:58 +02:00
parent 74afc805dc
commit 0f1cd98a80
8 changed files with 78 additions and 52 deletions

View File

@ -43,12 +43,14 @@ export class User {
email: string | undefined;
password: string | undefined;
username: string | null = null;
confidantEmail: string | null = null;
isAuthenticated = false;
isTrusted = false;
private token = "";
static async confirm(uid: string, token: string): Promise<void> {
await api_request("POST", "users/activation", 204, { uid, token });
async activate(): Promise<void> {
await api_request("POST", "users/activate", 204, {
password: this.password,
});
}
async login(): Promise<void> {
@ -84,7 +86,6 @@ export class User {
200,
{
username: this.username,
confidant_email: this.confidantEmail,
},
this.token
);

View File

@ -1,20 +1,8 @@
<template>
<div>
<b-notification
v-if="!user.username"
type="is-warning"
aria-close-label="Close notification"
>
Um dein Konto zu aktivieren, musst du einen
<strong>Benutzernamen</strong> festlegen.
</b-notification>
<b-notification
v-if="!user.confidant_email"
type="is-warning"
aria-close-label="Close notification"
>
Um dein Konto zu aktivieren, musst du eine
<strong>Vertrauensperson</strong> angeben.
<b-notification type="is-info" aria-close-label="Close notification">
Dein Konto ist noch nicht aktiv.
<a @click="activate()">Jetzt aktivieren</a>
</b-notification>
<table class="table is-fullwidth">
<tbody>
@ -34,10 +22,6 @@
<inline-editor v-model="user.confidantEmail" @input="user.save()" />
</td>
</tr>
<tr>
<td>E-Mail-Adresse</td>
<td>{{ user.email }} (bestätigt)</td>
</tr>
</tbody>
</table>
</div>
@ -53,5 +37,9 @@ import InlineEditor from "@/components/InlineEditor.vue";
})
export default class UserTable extends Vue {
@Prop() private user!: User;
async activate(): Promise<void> {
await this.user.activate();
}
}
</script>

View File

@ -1,5 +1,6 @@
from django.contrib import admin
from userausfall.models import User
from userausfall.models import User, TrustBridge
admin.site.register(TrustBridge)
admin.site.register(User)

View File

@ -0,0 +1,29 @@
# Generated by Django 2.2.20 on 2021-08-02 11:31
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('userausfall', '0009_auto_20210802_0745'),
]
operations = [
migrations.RemoveField(
model_name='user',
name='confidant',
),
migrations.RemoveField(
model_name='user',
name='confidant_unconfirmed',
),
migrations.RemoveField(
model_name='user',
name='email',
),
migrations.RemoveField(
model_name='user',
name='email_unconfirmed',
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 2.2.20 on 2021-08-02 11:41
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('userausfall', '0010_auto_20210802_1131'),
]
operations = [
migrations.CreateModel(
name='TrustBridge',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_trusted', models.BooleanField(default=False)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='trust_bridge', to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -66,28 +66,16 @@ class User(AbstractBaseUser, PermissionsMixin):
unique=True,
blank=True,
)
email = models.EmailField(_("email address"), blank=True)
email_unconfirmed = models.EmailField(_("email address"), blank=True)
is_staff = models.BooleanField(
_("staff status"),
default=False,
help_text=_("Designates whether the user can log into this admin site."),
)
date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
confidant = models.ForeignKey(
"User", on_delete=models.SET_NULL, null=True, blank=True, related_name="confidants"
)
confidant_unconfirmed = models.ForeignKey(
"User",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="unconfirmed_confidants",
)
objects = UserManager()
EMAIL_FIELD = "email"
# EMAIL_FIELD = "email"
USERNAME_FIELD = "username"
REQUIRED_FIELDS = []
@ -95,13 +83,6 @@ class User(AbstractBaseUser, PermissionsMixin):
verbose_name = _("user")
verbose_name_plural = _("users")
@property
def confidant_email(self):
if self.confidant is not None:
return self.confidant.email
else:
return None
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
@ -114,10 +95,13 @@ class User(AbstractBaseUser, PermissionsMixin):
"""Create the LDAP account which corresponds to this user."""
if not self.username:
raise MissingUserAttribute("User is missing a username.")
if not self.confidant:
raise MissingUserAttribute("User is missing a confirmed confidant.")
if not self.check_password(raw_password):
raise PasswordMismatch(
"The given password does not match the user's password."
)
return ldap.create_account(self.username, raw_password)
class TrustBridge(models.Model):
user = models.OneToOneField("User", on_delete=models.CASCADE, related_name="trust_bridge")
is_trusted = models.BooleanField(default=False)

View File

@ -14,13 +14,13 @@ class ConfidantConfirmationView(ConfirmationView):
class UserViewSet(viewsets.ModelViewSet):
permission_classes = [UserPermission]
# permission_classes = [UserPermission]
queryset = User.objects.all()
@action(detail=True, methods=["post"])
@action(detail=False, methods=["post"])
def activate(self, request, pk=None):
"""Create the corresponding LDAP account."""
user: User = self.get_object()
user: User = request.user # self.get_object()
serializer = UserActivationSerializer(data=request.data)
if serializer.is_valid():
try:

View File

@ -2,10 +2,10 @@ from django.db.models.signals import post_save
from django.dispatch import receiver
from userausfall.models import User
from userausfall.confirmations import ConfidantConfirmation
@receiver(post_save, sender=User)
def user_saved(sender, instance: User, **kwargs):
if instance.confidant_unconfirmed is not None:
ConfidantConfirmation(instance.confidant_unconfirmed, instance).send_request()
# if instance.confidant_unconfirmed is not None:
# ConfidantConfirmation(instance.confidant_unconfirmed, instance).send_request()
pass