feat: Allow to activate trusted accounts only

This commit is contained in:
aldrin 2021-08-03 11:41:58 +02:00
parent 0f1cd98a80
commit d656370aef
5 changed files with 40 additions and 44 deletions

View file

@ -12,7 +12,7 @@ async function api_request(
method: HTTPMethod,
endpoint: string,
successStatus: number,
data: any,
data?: any,
authToken?: string
) {
const init = {
@ -40,13 +40,15 @@ async function api_request(
}
export class User {
email: string | undefined;
pk: number | undefined;
password: string | undefined;
username: string | null = null;
isAuthenticated = false;
isTrusted = false;
private token = "";
/**
* Activate the corresponding LDAP account.
*/
async activate(): Promise<void> {
await api_request("POST", "users/activate", 204, {
password: this.password,
@ -74,21 +76,16 @@ export class User {
// successful logins are followed by a redirect
if (res.redirected && res.status === 200) {
this.isAuthenticated = true;
await this.retrieve();
} else {
throw new APIError("", "");
}
}
async save(): Promise<void> {
await api_request(
"PATCH",
"users/me",
200,
{
username: this.username,
},
this.token
);
async retrieve(): Promise<void> {
const data = await api_request("GET", "users/me", 200);
this.pk = data.pk;
this.isTrusted = data.trust_bridge.is_trusted;
}
async signup(): Promise<void> {

View file

@ -2,7 +2,7 @@
<div>
<b-notification type="is-info" aria-close-label="Close notification">
Dein Konto ist noch nicht aktiv.
<a @click="activate()">Jetzt aktivieren</a>
<a v-if="user.isTrusted" @click="activate()">Jetzt aktivieren</a>
</b-notification>
<table class="table is-fullwidth">
<tbody>

View file

@ -27,23 +27,9 @@ export default class Home extends mixins(NotifyMixin) {
private user = new User();
public async created(): Promise<void> {
if (this.$route.name === "confirm") {
await this.doConfirm();
} else if (!this.user.isAuthenticated && this.$route.name !== "login") {
if (!this.user.isAuthenticated && this.$route.name !== "login") {
this.$router.push({ name: "login" });
}
}
private async doConfirm() {
try {
await User.confirm(this.$route.params.uid, this.$route.params.token);
this.$router.push({ name: "login" });
this.showSuccess(
"Deine E-Mail-Adresse wurde bestätigt. Du kannst dich nun anmelden."
);
} catch {
this.showError();
}
}
}
</script>

View file

@ -1,25 +1,24 @@
from rest_framework import serializers
from userausfall.models import User
from userausfall.models import User, TrustBridge
class UserActivationSerializer(serializers.Serializer):
class TrustBridgeSerializer(serializers.ModelSerializer):
class Meta:
model = TrustBridge
fields = ["is_trusted"]
class ActivateUserSerializer(serializers.Serializer):
password = serializers.CharField()
class UserSerializer(serializers.ModelSerializer):
confidant_email = serializers.EmailField()
class RetrieveUserSerializer(serializers.ModelSerializer):
trust_bridge = TrustBridgeSerializer(required=False, read_only=True)
class Meta:
model = User
fields = ("pk", "email", "username", "confidant_email")
read_only_fields = ("email",)
def update(self, instance: User, validated_data):
confidant_email = validated_data.pop("confidant_email")
confidant, _ = User.objects.get_or_create(email=confidant_email)
instance.confidant_unconfirmed = confidant
return super().update(instance, validated_data)
fields = ["pk", "username", "trust_bridge"]
class CreateUserSerializer(serializers.ModelSerializer):

View file

@ -5,8 +5,11 @@ from rest_framework.response import Response
from djeveric import ConfirmationView
from userausfall.models import User, MissingUserAttribute, PasswordMismatch
from userausfall.confirmations import ConfidantConfirmation
from userausfall.rest_api.permissions import UserPermission
from userausfall.rest_api.serializers import UserSerializer, UserActivationSerializer, CreateUserSerializer
from userausfall.rest_api.serializers import (
ActivateUserSerializer,
CreateUserSerializer,
TrustBridgeSerializer, RetrieveUserSerializer,
)
class ConfidantConfirmationView(ConfirmationView):
@ -17,13 +20,24 @@ class UserViewSet(viewsets.ModelViewSet):
# permission_classes = [UserPermission]
queryset = User.objects.all()
@action(detail=False)
def me(self, request):
"""Retrieve user data for logged in user."""
user = request.user
serializer = RetrieveUserSerializer(user)
return Response(serializer.data)
@action(detail=False, methods=["post"])
def activate(self, request, pk=None):
"""Create the corresponding LDAP account."""
user: User = request.user # self.get_object()
serializer = UserActivationSerializer(data=request.data)
serializer = ActivateUserSerializer(data=request.data)
if serializer.is_valid():
try:
# We prevent untrusted user accounts from being activated via API.
# They might be activated via Admin or programmatically.
if not user.trust_bridge.is_trusted:
raise MissingUserAttribute("User has no trusted trust bridge.")
user.create_ldap_account(serializer.validated_data["password"])
except (MissingUserAttribute, PasswordMismatch) as e:
return Response({"message": str(e)}, status=status.HTTP_400_BAD_REQUEST)