Basic user management

This commit is contained in:
2026-02-05 00:46:22 +01:00
parent e280fcfba8
commit 11108bdfcc
55 changed files with 1524 additions and 54 deletions

View File

@@ -0,0 +1,49 @@
<?php
namespace App\Domains\UserManagement\Actions\GenerateActivationToken;
use App\Domains\MessageSystem\Actions\SendMessage\SendMessageCommand;
use App\Domains\MessageSystem\Actions\SendMessage\SendMessageRequest;
use App\Enumerations\MessageType;
use App\MessageTemplates\activationCodeTemplate;
use App\ValueObjects\EmailAddress;
use App\ValueObjects\MessageRecipient;
use Illuminate\Support\Str;
class GenerateActivationTokenCommand {
private GenerateActivationTokenRequest $request;
public function __construct(GenerateActivationTokenRequest $request) {
$this->request = $request;
}
public function execute() : GenerateActivationTokenResponse {
$response = new GenerateActivationTokenResponse;
$activationCode = Str::password(24,true,true,false,false);
$this->request->user->activation_token = $activationCode;
if (null !== $this->request->expirationDate) {
$this->request->user->activation_token_expires_at = $this->request->expirationDate;
}
$this->request->user->save();
$response->activationCode = $activationCode;
$activationMessage = new activationCodeTemplate();
$activationMessage->composeMessage(EmailAddress::fromString($this->request->user->email), $activationCode);
$recipient = new MessageRecipient();
$recipient->addEmailAddress(EmailAddress::fromString($this->request->user->email));
$recipient->setName($this->request->user->getFullname());
$message = activationCodeTemplate::createForUser(EmailAddress::fromString($this->request->user->email), $activationCode);
$userMessageRequests = new SendMessageRequest($message->getMessage(), $message->getSubject(), $recipient, [MessageType::EMAIL]);
$userMessageCommand = new SendMessageCommand($userMessageRequests);
$userMessageCommand->send();
return $response;
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Domains\UserManagement\Actions\GenerateActivationToken;
use App\Models\User;
class GenerateActivationTokenRequest {
public User $user;
public ?\DateTime $expirationDate;
public function __construct(User $user, ?\DateTime $expirationDate = null) {
$this->user = $user;
$this->expirationDate = $expirationDate;
}
}

View File

@@ -0,0 +1,7 @@
<?php
namespace App\Domains\UserManagement\Actions\GenerateActivationToken;
class GenerateActivationTokenResponse {
public string $activationCode;
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Domains\UserManagement\Actions\UserActivation;
class UserActivationCommand {
private UserActivationRequest $request;
public function __construct(UserActivationRequest $request) {
$this->request = $request;
}
public function execute() : UserActivationResponse {
$response = new UserActivationResponse();
$this->request->user->active = true;
$this->request->user->activation_token = null;
$this->request->user->activation_token_expires_at = null;
$this->request->user->save();
$response->success = true;
return $response;
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace App\Domains\UserManagement\Actions\UserActivation;
use App\Models\User;
class UserActivationRequest {
public User $user;
public function __construct(User $user) {
$this->user = $user;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Domains\UserManagement\Actions\UserActivation;
class UserActivationResponse {
public bool $success;
public function __construct() {
$this->success = false;
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Domains\UserManagement\Actions\UserChangePassword;
class UserChangePasswordCommand {
private UserChangePasswordRequest $request;
public function __construct(UserChangePasswordRequest $request)
{
$this->request = $request;
}
public function execute() : UserChangePasswordResponse {
$response = new UserChangePasswordResponse();
$this->request->user->password = $this->request->newPassword;
$this->request->user->save();
$response->success = true;
return $response;
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Domains\UserManagement\Actions\UserChangePassword;
use App\Models\User;
class UserChangePasswordRequest {
public User $user;
public string $newPassword;
public function __construct(User $user, string $newPassword) {
$this->user = $user;
$this->newPassword = $newPassword;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Domains\UserManagement\Actions\UserChangePassword;
class UserChangePasswordResponse {
public bool $success;
public function __construct() {
$this->success = false;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Domains\UserManagement\Actions\UserActivation;
class UserDeactivationCommand {
private UserDeactivationRequest $request;
public function __construct(UserDeactivationRequest $request) {
$this->request = $request;
}
public function execute() : UserDeactivationResponse {
$response = new UserDeactivationResponse();
$this->request->user->active = false;
$this->request->user->password = NULL;
$this->request->user->username = 'deleted-' . $this->request->user->username;
$this->request->user->email = 'null@example.com';
$this->request->user->save();
$response->success = true;
return $response;
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace App\Domains\UserManagement\Actions\UserActivation;
use App\Models\User;
class UserDeactivationRequest {
public User $user;
public function __construct(User $user) {
$this->user = $user;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Domains\UserManagement\Actions\UserActivation;
class UserDeactivationResponse {
public bool $success;
public function __construct() {
$this->success = false;
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Domains\UserManagement\Actions\UserRegistration;
use App\Domains\MessageSystem\Actions\SendMessage\SendMessageCommand;
use App\Domains\MessageSystem\Actions\SendMessage\SendMessageRequest;
use App\Domains\UserManagement\Actions\GenerateActivationToken\GenerateActivationTokenCommand;
use App\Domains\UserManagement\Actions\GenerateActivationToken\GenerateActivationTokenRequest;
use App\Enumerations\MessageType;
use App\MessageTemplates\Registration\InformAdminAboutNewUserTemplate;
use App\Models\User;
use App\ValueObjects\EmailAddress;
use App\ValueObjects\MessageRecipient;
class UserRegistrationCommand {
private UserRegistrationRequest $request;
public function __construct(UserRegistrationRequest $request) {
$this->request = $request;
}
public function execute() : UserRegistrationResponse {
$response = new UserRegistrationResponse;
$user = User::create([
'user_role_main' => $this->request->userRoleMain,
'user_role_local_group' => $this->request->userRoleLocalGroup,
'username' => $this->request->email->getValue(),
'local_group' => $this->request->localGroup,
'firstname' => $this->request->firstname,
'lastname' => $this->request->lastname,
'nickname' => $this->request->nickname !== '' ? $this->request->nickname : null,
'email' => $this->request->email->getValue(),
]);
if ($user === null) {
return $response;
}
$generateActivationCoedeRequest = new GenerateActivationTokenRequest($user);
$generateActivationCoedeDommand = new GenerateActivationTokenCommand($generateActivationCoedeRequest);
$result = $generateActivationCoedeDommand->execute();
$user->activation_token = $result->activationCode;
$siteAdmin = new MessageRecipient();
$siteAdmin->addEmailAddress(EmailAddress::fromString(env('APP_ADMIN_MAIL')));
$siteAdmin->setName(env('APP_ADMIN_NAME'));
$registrationMessage = InformAdminAboutNewUserTemplate::createNew($user);
$registrationMessageRequest = new SendMessageRequest($registrationMessage->getMessage(), $registrationMessage->getSubject(), $siteAdmin, [MessageType::EMAIL]);
$registrationMessageCommand = new SendMessageCommand($registrationMessageRequest);
$registrationMessageCommand->send();
$response->user = $user;
$response->success = true;
return $response;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Domains\UserManagement\Actions\UserRegistration;
use App\ValueObjects\EmailAddress;
class UserRegistrationRequest {
public string $firstname;
public string $lastname;
public EmailAddress $email;
public string $nickname;
public string $userRoleMain;
public string $userRoleLocalGroup;
public string $localGroup;
public function __construct(string $firstname, string $lastname, string $nickname, EmailAddress $email, string $userRoleMain, string $userRoleLocalGroup, string $localGroup) {
$this->firstname = $firstname;
$this->lastname = $lastname;
$this->nickname = $nickname;
$this->email = $email;
$this->userRoleMain = $userRoleMain;
$this->userRoleLocalGroup = $userRoleLocalGroup;
$this->localGroup = $localGroup;
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Domains\UserManagement\Actions\UserRegistration;
use App\Models\User;
class UserRegistrationResponse {
public ?User $user;
public bool $success;
public function __construct() {
$this->user = null;
$this->success = false;
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace App\Domains\UserManagement\Controllers;
use App\Domains\UserManagement\Actions\UserActivation\UserActivationCommand;
use App\Domains\UserManagement\Actions\UserActivation\UserActivationRequest;
use App\Domains\UserManagement\Actions\UserActivation\UserDeactivationCommand;
use App\Domains\UserManagement\Actions\UserActivation\UserDeactivationRequest;
use App\Domains\UserManagement\Actions\UserChangePassword\UserChangePasswordCommand;
use App\Domains\UserManagement\Actions\UserChangePassword\UserChangePasswordRequest;
use App\Domains\UserManagement\Actions\UserRegistration\UserRegistrationCommand;
use App\Domains\UserManagement\Actions\UserRegistration\UserRegistrationRequest;
use App\Enumerations\UserRole;
use App\Models\User;
use App\Providers\InertiaProvider;
use App\Scopes\CommonController;
use App\ValueObjects\EmailAddress;
use Carbon\Traits\Date;
use DateTime;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class EmailVerificationController extends CommonController
{
public function verifyEmailForm(Request $request) {
$inertiaProvider = new InertiaProvider('UserManagement/VerifyEmail', ['appName' => app('tenant')->name]);
return $inertiaProvider->render();
}
public function doVerification(Request $request) : JsonResponse
{
$user = $this->users->findByUsername($request->get('email'));
if ($user === null) {
return response()->json([
'error_types' => [
'email' => 'Die E-Mail-Adresse konnte nicht zugeordnet werden.',
],
]);
}
if (new DateTime() > DateTime::createFromFormat('Y-m-d H:i:s', $user->activation_token_expires_at)) {
return response()->json([
'error_types' => [
'verificationToken' => 'Der Sicherheitsschlüssel ist abgelaufen.',
],
]);
}
if (!$this->users->checkVerificationToken($user, $request->get('verificationToken'))) {
return response()->json([
'error_types' => [
'verificationToken' => 'Der Sicherheitsschlüssel ist nicht korrekt',
],
]);
}
$userActivationRequest = new UserActivationRequest($user);
$userActivationCommand = new UserActivationCommand($userActivationRequest);
$activationResult = $userActivationCommand->execute();
if (!$activationResult->success) {
return response()->json([
'error_types' => [
'verificationToken' => 'Ein allgemeiner Fehler ist aufgetreten. Bitte versuche es später noch einmal.',
],
]);
}
$userPasswordResetRequest = new UserChangePasswordRequest($user, $request->get('password'));
$userPasswordResetCommand = new UserChangePasswordCommand($userPasswordResetRequest);
$userPasswordResetCommand->execute();
return response()->json([
'status' => 'success',
'message' => 'Dein Account wurde aktiviert.Du kannst dich nun mit deinem neuen Passwort einloggen.'
]);
}
}

View File

@@ -3,10 +3,11 @@
namespace App\Domains\UserManagement\Controllers;
use App\Providers\InertiaProvider;
use App\Scopes\CommonController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController {
class LoginController extends CommonController {
public function loginForm(Request $request) {
$errors = [];
@@ -32,6 +33,12 @@ class LoginController {
'password.required' => 'Bitte gib dein Passwort ein.',
]);
$user = $this->users->findByUsername($request->get('username'));
if ($user !== null && $user->password === null) {
return redirect()->intended('/register/verifyEmail');
}
#$credentials = ['username' => 'development', 'password' => 'development'];
if (!Auth::attempt($credentials)) {

View File

@@ -0,0 +1,73 @@
<?php
namespace App\Domains\UserManagement\Controllers;
use App\Domains\MessageSystem\Actions\SendMessage\SendMessageCommand;
use App\Domains\MessageSystem\Actions\SendMessage\SendMessageRequest;
use App\Domains\UserManagement\Actions\UserRegistration\UserRegistrationCommand;
use App\Domains\UserManagement\Actions\UserRegistration\UserRegistrationRequest;
use App\Enumerations\MessageType;
use App\Enumerations\UserRole;
use App\Providers\InertiaProvider;
use App\Scopes\CommonController;
use App\ValueObjects\EmailAddress;
use App\ValueObjects\MessageRecipient;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class RegistrationController extends CommonController {
public function loginForm(Request $request) {
$errors = [];
if ($request->session()->has('errors')) {
$errors = $request->session()->get('errors')->getBag('default')->getMessages();
}
$inertiaProvider = new InertiaProvider('UserManagement/Registration', ['errors' => $errors, 'appName' => app('tenant')->name]);
return $inertiaProvider->render();
}
public function doRegistration(Request $request) : JsonResponse {
$user = $this->users->findByUsername($request->get('email'));
if ($user !== null) {
return response()->json([
'status' => 'error',
'message' => 'Dieser Account existiert bereits.'
]);
}
$email = EmailAddress::fromString($request->get('email'));
$userRoleMain = UserRole::USER_ROLE_USER;
$userRoleLocalGroup = UserRole::USER_ROLE_USER;
$localGroup = app('tenant')->slug === 'lv' ? $request->get('localGroup') : app('tenant')->slug;
$registrationRequest = new UserRegistrationRequest(
$request->get('firstname'),
$request->get('lastname'),
$request->get('nickname'),
$email,
$userRoleMain,
$userRoleLocalGroup,
$localGroup
);
$registrationCommand = new UserRegistrationCommand($registrationRequest);
$result = $registrationCommand->execute();
if (!$result->success) {
return response()->json([
'status' => 'error',
'message' => 'Beim Erstellen des Accounts ist ein Fehler aufgetreten.'
]);
}
return response()->json([
'status' => 'success',
'message' => 'Registrierung erfolgreich! Bitte prüfe nun dein E-Mail-Postfach'
]);
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace App\Domains\UserManagement\Controllers;
use App\Domains\UserManagement\Actions\GenerateActivationToken\GenerateActivationTokenCommand;
use App\Domains\UserManagement\Actions\GenerateActivationToken\GenerateActivationTokenRequest;
use App\Domains\UserManagement\Actions\GenerateActivationToken\GenerateActivationTokenResponse;
use App\Domains\UserManagement\Actions\UserActivation\UserActivationCommand;
use App\Domains\UserManagement\Actions\UserActivation\UserActivationRequest;
use App\Providers\InertiaProvider;
use App\Scopes\CommonController;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ResetPasswordController extends CommonController {
public function resetPasswordForm() {
$inertiaProvider = new InertiaProvider('UserManagement/ResetPassword', []);
return $inertiaProvider->render();
}
public function doResetPassword(Request $request) : JsonResponse {
$user = $this->users->findByUsername($request->get('email'));
if (null !== $user) {
$expirationDate = new \DateTime()->modify('+15 Minutes');
$resetAccountRequest = new GenerateActivationTokenRequest($user, $expirationDate);
$resetAccountCommand = new GenerateActivationTokenCommand($resetAccountRequest);
$resetAccountCommand->execute();
}
return response()->json([
'status' => 'success',
'message' => 'Falls deine E-Mail-Adresse gefunden wurde, erhältst du nun eine E-Mail mit weiteren Schritten zum Zurücksetzen deines Passwortes.'
]);
}
}

View File

@@ -0,0 +1,17 @@
<?php
use App\Domains\UserManagement\Controllers\EmailVerificationController;
use App\Domains\UserManagement\Controllers\RegistrationController;
use App\Domains\UserManagement\Controllers\ResetPasswordController;
use App\Middleware\IdentifyTenant;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::prefix('v1')
->group(function () {
Route::middleware(IdentifyTenant::class)->group(function () {
Route::post('/register', [RegistrationController::class, 'doRegistration']);
Route::post('/register/confirmEmail', [EmailVerificationController::class, 'doVerification']);
Route::post('/reset-password', [ResetPasswordController::class, 'doResetPassword']);
});
});

View File

@@ -0,0 +1,31 @@
<?php
use App\Domains\Dashboard\Controllers\DashboardController;
use App\Domains\UserManagement\Controllers\EmailVerificationController;
use App\Domains\UserManagement\Controllers\LoginController;
use App\Domains\UserManagement\Controllers\LogOutController;
use App\Domains\UserManagement\Controllers\RegistrationController;
use App\Domains\UserManagement\Controllers\ResetPasswordController;
use App\Http\Controllers\TestRenderInertiaProvider;
use App\Middleware\IdentifyTenant;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::middleware(IdentifyTenant::class)->group(function () {
Route::get('/register', [RegistrationController::class, 'loginForm']);
Route::get('/register/verifyEmail', [EmailVerificationController::class, 'verifyEmailForm']);
Route::get('/reset-password', [ResetPasswordController::class, 'resetPasswordForm']);
route::get('/logout', LogOutController::class);
route::post('/login', [LoginController::class, 'doLogin']);
route::get('/login', [LoginController::class, 'loginForm']);
Route::middleware(['auth'])->group(function () {
Route::post('/logout', [LogoutController::class, 'logout']);
});
});

View File

@@ -25,6 +25,10 @@ const username = ref('')
const password = ref('')
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
function resetPassword() {
window.location.href = '/reset-password';
}
</script>
<template>
@@ -48,6 +52,7 @@ const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute
<tr>
<td colspan="2">
<input type="submit" value="Anmelden" style="margin-top: 20px;" />
<input type="button" @click="resetPassword" style="margin-top: 20px; margin-left: 20px;" value="Passwort vergessen" />
</td>
</tr>
</table>

View File

@@ -0,0 +1,166 @@
<script setup>
import AppLayout from '../../../../resources/js/layouts/AppLayout.vue'
import {computed, onMounted, reactive, ref} from 'vue'
import { toast } from 'vue3-toastify'
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
import {useAjax} from "../../../../resources/js/components/ajaxHandler.js";
import ErrorText from "../../../Views/Components/ErrorText.vue";
const props = defineProps({
navbar: Object,
tenant: String,
user: Object,
currentPath: String,
errors: Object,
availableLocalGroups: Array,
})
onMounted(() => {
if (undefined !== props.errors && undefined !== props.errors.username) {
toast.error(props.errors.username[0])
}
})
//console.log(props.errors.password[0])
const username = ref('')
const password = ref('')
const form = reactive({
firstname: '',
lastname: '',
nickname: '',
email: '',
localGroup: '',
password: '',
password_confirmation: ''
})
const errors = reactive({})
const { request } = useAjax()
const isValid = computed(() => {
errors.firstname = ''
errors.lastname = ''
errors.localGroup = ''
errors.email = ''
if (!form.firstname) {
errors.firstname = 'Bitte gib deinen Vornamen ein'
}
if (!form.lastname) {
errors.lastname = 'Bitte gib deinen Nachnamen ein'
}
if (!form.localGroup) {
errors.localGroup = 'Bitte gib deinen Stamm an'
}
if (!form.email) {
errors.email = 'Bitte gib deine E-Mail-Adresse ein'
} else if (!/^\S+@\S+\.\S+$/.test(form.email)) {
errors.email = 'Ungültige E-Mail'
}
return !errors.password && !errors.firstname && !errors.lastname && !errors.localGroup
})
async function submit() {
if (!isValid.value) return false
const data = await request("/api/v1/register", {
method: "POST",
body: {
"firstname": form.firstname,
"lastname": form.lastname,
'nickname': form.nickname,
"email": form.email,
"localGroup": form.localGroup,
}
});
if (data.status === 'error') {
toast.error(data.message);
} else {
toast.success(data.message)
window.location.href = '/register/verifyEmail';
}
return;
}
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
</script>
<template>
<AppLayout title='Registrieren' :user="props.user" :navbar="props.navbar" :tenant="props.tenant" :currentPath="props.currentPath">
<form method="POST" action="/register" @submit.prevent="submit">
<input type="hidden" name="_token" :value="csrfToken" />
<shadowed-box style="width: 75%; margin: 150px auto; padding: 20px;">
<table>
<tr>
<th>Vorname</th>
<td>
<input type="text" name="firstname" id="firstname" v-model="form.firstname" />
<ErrorText :message="errors.firstname" />
</td>
</tr>
<tr>
<th>Nachname</th>
<td>
<input type="text" name="lastname" id="lastname" v-model="form.lastname" />
<ErrorText :message="errors.lastname" />
</td>
</tr>
<tr>
<th>
Pfadi-Name*<br />
<small>*Falls vorhanden</small>
</th>
<td>
<input type="text" name="nickname" id="nickname" v-model="form.nickname" />
</td>
</tr>
<tr>
<th>E-Mail-Adresse</th>
<td>
<input type="email" name="email" id="email" v-model="form.email" />
<ErrorText :message="errors.email" />
</td>
</tr>
<tr v-if="props.tenant.slug === 'lv'">
<th>Stamm</th>
<td>
<select name="localgroup" v-model="form.localGroup">
<option v-for="localGroup in props.availableLocalGroups" :value="localGroup.slug">{{localGroup.name}}</option>
</select>
<ErrorText :message="errors.localGroup" />
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Registrieren" style="margin-top: 20px;" />
</td>
</tr>
</table>
</shadowed-box>
</form>
</AppLayout>
</template>
<style>
th {
width: 150px;
}
</style>

View File

@@ -0,0 +1,102 @@
<script setup>
import AppLayout from '../../../../resources/js/layouts/AppLayout.vue'
import {computed, onMounted, reactive, ref} from 'vue'
import { toast } from 'vue3-toastify'
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
import {useAjax} from "../../../../resources/js/components/ajaxHandler.js";
import ErrorText from "../../../Views/Components/ErrorText.vue";
const props = defineProps({
navbar: Object,
tenant: String,
user: Object,
currentPath: String,
errors: Object,
availableLocalGroups: Array,
})
onMounted(() => {
if (undefined !== props.errors && undefined !== props.errors.username) {
toast.error(props.errors.username[0])
}
})
const form = reactive({
email: '',
verificationToken: '',
})
const errors = reactive({})
const { request } = useAjax()
const isValid = computed(() => {
errors.email = ''
if (!form.email) {
errors.email = 'Bitte gib deine E-Mail-Adresse ein'
}
return !errors.email
})
async function submit() {
if (!isValid.value) return false
const data = await request("/api/v1/reset-password", {
method: "POST",
body: {
"email": form.email,
}
});
if (data.error_types) {
Object.keys(data.error_types).forEach((key) => {
if (key in errors) {
errors[key] = data.error_types[key]
}
});
} else {
window.location.href = '/register/verifyEmail';
toast.success(data.message)
}
return;
}
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
</script>
<template>
<AppLayout title='Passwort zurücksetzen' :user="props.user" :navbar="props.navbar" :tenant="props.tenant" :currentPath="props.currentPath">
<form method="POST" action="/reset-password" @submit.prevent="submit">
<input type="hidden" name="_token" :value="csrfToken" />
<shadowed-box style="width: 75%; margin: 150px auto; padding: 20px;">
<table>
<tr>
<th>E-Mail-Adresse</th>
<td>
<input type="email" name="email" id="email" v-model="form.email" />
<ErrorText :message="errors.email" />
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Verifizierung starten" style="margin-top: 20px;" />
</td>
</tr>
</table>
</shadowed-box>
</form>
</AppLayout>
</template>
<style>
th {
width: 150px;
}
</style>

View File

@@ -0,0 +1,152 @@
<script setup>
import AppLayout from '../../../../resources/js/layouts/AppLayout.vue'
import {computed, onMounted, reactive, ref} from 'vue'
import { toast } from 'vue3-toastify'
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
import {useAjax} from "../../../../resources/js/components/ajaxHandler.js";
import ErrorText from "../../../Views/Components/ErrorText.vue";
const props = defineProps({
navbar: Object,
tenant: String,
user: Object,
currentPath: String,
errors: Object,
availableLocalGroups: Array,
})
onMounted(() => {
if (undefined !== props.errors && undefined !== props.errors.username) {
toast.error(props.errors.username[0])
}
})
const form = reactive({
email: '',
verificationToken: '',
password: '',
})
const errors = reactive({})
const { request } = useAjax()
const isValid = computed(() => {
errors.email = '';
errors.verificationToken = '';
errors.password = '';
if (!form.email) {
errors.email = 'Bitte gib deine E-Mail-Adresse ein'
} else if (!/^\S+@\S+\.\S+$/.test(form.email)) {
errors.email = 'Ungültige E-Mail'
}
if (!form.verificationToken) {
errors.verificationToken = 'Bitte gib den Sicherheitsschlüssel, den du per E-Mail erhalten hast, ein'
}
if (!form.password) {
errors.password = 'Bitte gib ein Passwort ein'
} else if (form.password.length < 2) {
errors.password = 'Das Passwort muss mindestens 12 Zeichen lang sein'
}
if (form.password !== form.password_confirmation) {
errors.password = 'Das Passwort und die Wiederholung stimmen nicht überein'
}
return !errors.password && !errors.email && !errors.verificationToken
})
async function submit() {
if (!isValid.value) return false
const data = await request("/api/v1/register/confirmEmail", {
method: "POST",
body: {
"email": form.email,
"verificationToken": form.verificationToken,
"password": form.password,
}
});
if (data.error_types) {
Object.keys(data.error_types).forEach((key) => {
if (key in errors) {
errors[key] = data.error_types[key]
}
});
} else {
toast.success(data.message)
window.location.href = '/login';
}
return;
}
function resetPassword() {
window.location.href = '/reset-password';
}
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
</script>
<template>
<AppLayout title='E-Mail bestätigen' :user="props.user" :navbar="props.navbar" :tenant="props.tenant" :currentPath="props.currentPath">
<form method="POST" action="/register" @submit.prevent="submit">
<input type="hidden" name="_token" :value="csrfToken" />
<shadowed-box style="width: 75%; margin: 150px auto; padding: 20px;">
<p>
Bitte prüfe dein E-Mail-Postfach.<br />
Solltest du keinen Aktivierungsschlüssel erhalten haben, kontaktiere bitte einen Administrator.
</p>
<table>
<tr>
<th>E-Mail-Adresse</th>
<td>
<input type="email" name="email" id="email" v-model="form.email" />
<ErrorText :message="errors.email" />
</td>
</tr>
<tr>
<th>Sicherheitsschlüssel</th>
<td>
<input type="text" name="verificationToken" id="verificationToken" v-model="form.verificationToken" />
<ErrorText :message="errors.verificationToken" />
</td>
</tr>
<tr>
<th>Dein neues Passwort</th>
<td><input type="password" name="password" id="password" v-model="form.password" /></td>
</tr>
<tr>
<th>Passwort (wiederholen)</th>
<td>
<input type="password" name="password_retype" id="password_retype" v-model="form.password_confirmation" />
<ErrorText :message="errors.password" />
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="E-Mail validieren" style="margin-top: 20px;" />
<input type="button" @click="resetPassword" style="margin-top: 20px; margin-left: 20px;" value="Validierungscode neu zusenden" />
</td>
</tr>
</table>
</shadowed-box>
</form>
</AppLayout>
</template>
<style>
th {
width: 150px;
}
</style>