From 11108bdfcc3302079fea89c5c005950f485f0f17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=BCnther?=
Date: Thu, 5 Feb 2026 00:46:22 +0100
Subject: [PATCH] Basic user management
---
app/Domains/Invoice/Views/CreateInvoice.vue | 29 +++
.../SendMessage/SendMessageCommand.php | 45 +++++
.../SendMessage/SendMessageRequest.php | 30 ++++
.../SendMessage/SendMessageResponse.php | 7 +
.../GenerateActivationTokenCommand.php | 49 ++++++
.../GenerateActivationTokenRequest.php | 16 ++
.../GenerateActivationTokenResponse.php | 7 +
.../UserActivation/UserActivationCommand.php | 20 +++
.../UserActivation/UserActivationRequest.php | 14 ++
.../UserActivation/UserActivationResponse.php | 11 ++
.../UserChangePasswordCommand.php | 23 +++
.../UserChangePasswordRequest.php | 15 ++
.../UserChangePasswordResponse.php | 11 ++
.../UserDeactivationCommand.php | 21 +++
.../UserDeactivationRequest.php | 14 ++
.../UserDeactivationResponse.php | 11 ++
.../UserRegistrationCommand.php | 60 +++++++
.../UserRegistrationRequest.php | 25 +++
.../UserRegistrationResponse.php | 15 ++
.../EmailVerificationController.php | 80 +++++++++
.../Controllers/LoginController.php | 9 +-
.../Controllers/RegistrationController.php | 73 ++++++++
.../Controllers/ResetPasswordController.php | 39 ++++
app/Domains/UserManagement/Routes/api.php | 17 ++
app/Domains/UserManagement/Routes/web.php | 31 ++++
app/Domains/UserManagement/Views/Login.vue | 5 +
.../UserManagement/Views/Registration.vue | 166 ++++++++++++++++++
.../UserManagement/Views/ResetPassword.vue | 102 +++++++++++
.../UserManagement/Views/VerifyEmail.vue | 152 ++++++++++++++++
app/Enumerations/MessageType.php | 8 +
app/Installer/DevelopmentDataSeeder.php | 8 +-
app/Installer/ProductionDataSeeder.php | 2 +-
app/MessageTemplates/MessageTemplate.php | 37 ++++
.../InformAdminAboutNewUserTemplate.php | 59 +++++++
.../activationCodeTemplate.php | 23 +++
app/Models/Tenant.php | 2 +-
app/Models/User.php | 49 +++++-
app/Providers/AuthCheckProvider.php | 11 +-
app/Providers/InertiaProvider.php | 4 +-
app/Providers/TenantUserProvider.php | 8 +-
app/Repositories/UserRepository.php | 20 +++
app/Scopes/CommonController.php | 7 +
app/ValueObjects/EmailAddress.php | 26 +++
app/ValueObjects/MessageRecipient.php | 50 ++++++
app/Views/Components/ErrorText.vue | 10 ++
config/app.php | 2 +-
.../2026_01_30_140001_create_tenants.php | 2 +-
.../2026_01_30_140002_create_users_table.php | 12 +-
docker-compose.dev | 9 +-
public/css/app.css | 1 +
public/css/elements.css | 23 ++-
resources/js/components/ajaxHandler.js | 80 +++++++++
resources/views/app.blade.php | 4 +-
routes/api.php | 14 +-
routes/web.php | 10 +-
55 files changed, 1524 insertions(+), 54 deletions(-)
create mode 100644 app/Domains/Invoice/Views/CreateInvoice.vue
create mode 100644 app/Domains/MessageSystem/Actions/SendMessage/SendMessageCommand.php
create mode 100644 app/Domains/MessageSystem/Actions/SendMessage/SendMessageRequest.php
create mode 100644 app/Domains/MessageSystem/Actions/SendMessage/SendMessageResponse.php
create mode 100644 app/Domains/UserManagement/Actions/GenerateActivationToken/GenerateActivationTokenCommand.php
create mode 100644 app/Domains/UserManagement/Actions/GenerateActivationToken/GenerateActivationTokenRequest.php
create mode 100644 app/Domains/UserManagement/Actions/GenerateActivationToken/GenerateActivationTokenResponse.php
create mode 100644 app/Domains/UserManagement/Actions/UserActivation/UserActivationCommand.php
create mode 100644 app/Domains/UserManagement/Actions/UserActivation/UserActivationRequest.php
create mode 100644 app/Domains/UserManagement/Actions/UserActivation/UserActivationResponse.php
create mode 100644 app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordCommand.php
create mode 100644 app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordRequest.php
create mode 100644 app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordResponse.php
create mode 100644 app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationCommand.php
create mode 100644 app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationRequest.php
create mode 100644 app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationResponse.php
create mode 100644 app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationCommand.php
create mode 100644 app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationRequest.php
create mode 100644 app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationResponse.php
create mode 100644 app/Domains/UserManagement/Controllers/EmailVerificationController.php
create mode 100644 app/Domains/UserManagement/Controllers/RegistrationController.php
create mode 100644 app/Domains/UserManagement/Controllers/ResetPasswordController.php
create mode 100644 app/Domains/UserManagement/Routes/api.php
create mode 100644 app/Domains/UserManagement/Routes/web.php
create mode 100644 app/Domains/UserManagement/Views/Registration.vue
create mode 100644 app/Domains/UserManagement/Views/ResetPassword.vue
create mode 100644 app/Domains/UserManagement/Views/VerifyEmail.vue
create mode 100644 app/Enumerations/MessageType.php
create mode 100644 app/MessageTemplates/MessageTemplate.php
create mode 100644 app/MessageTemplates/Registration/InformAdminAboutNewUserTemplate.php
create mode 100644 app/MessageTemplates/activationCodeTemplate.php
create mode 100644 app/Repositories/UserRepository.php
create mode 100644 app/ValueObjects/EmailAddress.php
create mode 100644 app/ValueObjects/MessageRecipient.php
create mode 100644 app/Views/Components/ErrorText.vue
create mode 100644 resources/js/components/ajaxHandler.js
diff --git a/app/Domains/Invoice/Views/CreateInvoice.vue b/app/Domains/Invoice/Views/CreateInvoice.vue
new file mode 100644
index 0000000..01f0f5f
--- /dev/null
+++ b/app/Domains/Invoice/Views/CreateInvoice.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+ Dashboard Content
+ Test 1!
+ Hier wird mal eine Rechnung erstellt.
+ Wenn es geht oder auch nicht
+ {{props.tenant}}
+
+
+
+
+
+
+
+
diff --git a/app/Domains/MessageSystem/Actions/SendMessage/SendMessageCommand.php b/app/Domains/MessageSystem/Actions/SendMessage/SendMessageCommand.php
new file mode 100644
index 0000000..64c76c2
--- /dev/null
+++ b/app/Domains/MessageSystem/Actions/SendMessage/SendMessageCommand.php
@@ -0,0 +1,45 @@
+request = $request;
+ }
+
+ public function send() : SendMessageResponse {
+ $response = new SendMessageResponse();
+
+ foreach ($this->request->messageTypes as $messageType) {
+ switch (true) {
+ case $messageType->value === MessageType::EMAIL->value:
+ $this->sendAsEmail();
+ break;
+
+ case $messageType->value === MessageType::INTERNAL->value:
+ $this->sendAsInternalMessage();
+ break;
+ }
+ }
+
+ return $response;
+ }
+
+ private function sendAsEmail() {
+ foreach ($this->request->recipient->getEmailAddresses() as $emailAddress) {
+ Mail::html($this->request->message, function ($message) use ($emailAddress) {
+ $message
+ ->to($emailAddress->getValue(), $this->request->recipient->getName())
+ ->subject($this->request->subject);
+ });
+ }
+ }
+
+ private function sendAsInternalMessage() {
+ }
+}
diff --git a/app/Domains/MessageSystem/Actions/SendMessage/SendMessageRequest.php b/app/Domains/MessageSystem/Actions/SendMessage/SendMessageRequest.php
new file mode 100644
index 0000000..dc4ae4d
--- /dev/null
+++ b/app/Domains/MessageSystem/Actions/SendMessage/SendMessageRequest.php
@@ -0,0 +1,30 @@
+message = $message;
+ $this->recipient = $recipient;
+ $this->subject = $subject;
+ $this->messageTypes = $messageTypes;
+ }
+}
diff --git a/app/Domains/MessageSystem/Actions/SendMessage/SendMessageResponse.php b/app/Domains/MessageSystem/Actions/SendMessage/SendMessageResponse.php
new file mode 100644
index 0000000..98e2dae
--- /dev/null
+++ b/app/Domains/MessageSystem/Actions/SendMessage/SendMessageResponse.php
@@ -0,0 +1,7 @@
+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;
+
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/GenerateActivationToken/GenerateActivationTokenRequest.php b/app/Domains/UserManagement/Actions/GenerateActivationToken/GenerateActivationTokenRequest.php
new file mode 100644
index 0000000..58220c5
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/GenerateActivationToken/GenerateActivationTokenRequest.php
@@ -0,0 +1,16 @@
+user = $user;
+ $this->expirationDate = $expirationDate;
+
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/GenerateActivationToken/GenerateActivationTokenResponse.php b/app/Domains/UserManagement/Actions/GenerateActivationToken/GenerateActivationTokenResponse.php
new file mode 100644
index 0000000..a24b291
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/GenerateActivationToken/GenerateActivationTokenResponse.php
@@ -0,0 +1,7 @@
+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;
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserActivation/UserActivationRequest.php b/app/Domains/UserManagement/Actions/UserActivation/UserActivationRequest.php
new file mode 100644
index 0000000..f68cfee
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserActivation/UserActivationRequest.php
@@ -0,0 +1,14 @@
+user = $user;
+
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserActivation/UserActivationResponse.php b/app/Domains/UserManagement/Actions/UserActivation/UserActivationResponse.php
new file mode 100644
index 0000000..859aaa8
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserActivation/UserActivationResponse.php
@@ -0,0 +1,11 @@
+success = false;
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordCommand.php b/app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordCommand.php
new file mode 100644
index 0000000..ca3eed0
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordCommand.php
@@ -0,0 +1,23 @@
+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;
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordRequest.php b/app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordRequest.php
new file mode 100644
index 0000000..e5c6767
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordRequest.php
@@ -0,0 +1,15 @@
+user = $user;
+ $this->newPassword = $newPassword;
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordResponse.php b/app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordResponse.php
new file mode 100644
index 0000000..7f196e2
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserChangePassword/UserChangePasswordResponse.php
@@ -0,0 +1,11 @@
+success = false;
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationCommand.php b/app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationCommand.php
new file mode 100644
index 0000000..791ccff
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationCommand.php
@@ -0,0 +1,21 @@
+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;
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationRequest.php b/app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationRequest.php
new file mode 100644
index 0000000..0907a26
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationRequest.php
@@ -0,0 +1,14 @@
+user = $user;
+
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationResponse.php b/app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationResponse.php
new file mode 100644
index 0000000..5573662
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserDeactivation/UserDeactivationResponse.php
@@ -0,0 +1,11 @@
+success = false;
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationCommand.php b/app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationCommand.php
new file mode 100644
index 0000000..b7df941
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationCommand.php
@@ -0,0 +1,60 @@
+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;
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationRequest.php b/app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationRequest.php
new file mode 100644
index 0000000..b3697fa
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationRequest.php
@@ -0,0 +1,25 @@
+firstname = $firstname;
+ $this->lastname = $lastname;
+ $this->nickname = $nickname;
+ $this->email = $email;
+ $this->userRoleMain = $userRoleMain;
+ $this->userRoleLocalGroup = $userRoleLocalGroup;
+ $this->localGroup = $localGroup;
+ }
+}
diff --git a/app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationResponse.php b/app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationResponse.php
new file mode 100644
index 0000000..4c3202b
--- /dev/null
+++ b/app/Domains/UserManagement/Actions/UserRegistration/UserRegistrationResponse.php
@@ -0,0 +1,15 @@
+user = null;
+ $this->success = false;
+ }
+}
diff --git a/app/Domains/UserManagement/Controllers/EmailVerificationController.php b/app/Domains/UserManagement/Controllers/EmailVerificationController.php
new file mode 100644
index 0000000..91c4009
--- /dev/null
+++ b/app/Domains/UserManagement/Controllers/EmailVerificationController.php
@@ -0,0 +1,80 @@
+ 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.'
+ ]);
+ }
+}
diff --git a/app/Domains/UserManagement/Controllers/LoginController.php b/app/Domains/UserManagement/Controllers/LoginController.php
index 640cbde..d7270d6 100644
--- a/app/Domains/UserManagement/Controllers/LoginController.php
+++ b/app/Domains/UserManagement/Controllers/LoginController.php
@@ -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)) {
diff --git a/app/Domains/UserManagement/Controllers/RegistrationController.php b/app/Domains/UserManagement/Controllers/RegistrationController.php
new file mode 100644
index 0000000..986a72b
--- /dev/null
+++ b/app/Domains/UserManagement/Controllers/RegistrationController.php
@@ -0,0 +1,73 @@
+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'
+ ]);
+ }
+}
diff --git a/app/Domains/UserManagement/Controllers/ResetPasswordController.php b/app/Domains/UserManagement/Controllers/ResetPasswordController.php
new file mode 100644
index 0000000..2c5cead
--- /dev/null
+++ b/app/Domains/UserManagement/Controllers/ResetPasswordController.php
@@ -0,0 +1,39 @@
+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.'
+ ]);
+
+ }
+}
diff --git a/app/Domains/UserManagement/Routes/api.php b/app/Domains/UserManagement/Routes/api.php
new file mode 100644
index 0000000..ed20b73
--- /dev/null
+++ b/app/Domains/UserManagement/Routes/api.php
@@ -0,0 +1,17 @@
+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']);
+ });
+ });
diff --git a/app/Domains/UserManagement/Routes/web.php b/app/Domains/UserManagement/Routes/web.php
new file mode 100644
index 0000000..a5dea9c
--- /dev/null
+++ b/app/Domains/UserManagement/Routes/web.php
@@ -0,0 +1,31 @@
+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']);
+
+ });
+});
+
+
+
diff --git a/app/Domains/UserManagement/Views/Login.vue b/app/Domains/UserManagement/Views/Login.vue
index 0616102..ef5d6d2 100644
--- a/app/Domains/UserManagement/Views/Login.vue
+++ b/app/Domains/UserManagement/Views/Login.vue
@@ -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';
+ }
@@ -48,6 +52,7 @@ const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute
|
+
|
diff --git a/app/Domains/UserManagement/Views/Registration.vue b/app/Domains/UserManagement/Views/Registration.vue
new file mode 100644
index 0000000..b00b885
--- /dev/null
+++ b/app/Domains/UserManagement/Views/Registration.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/Domains/UserManagement/Views/ResetPassword.vue b/app/Domains/UserManagement/Views/ResetPassword.vue
new file mode 100644
index 0000000..34a95cb
--- /dev/null
+++ b/app/Domains/UserManagement/Views/ResetPassword.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/Domains/UserManagement/Views/VerifyEmail.vue b/app/Domains/UserManagement/Views/VerifyEmail.vue
new file mode 100644
index 0000000..f719d8e
--- /dev/null
+++ b/app/Domains/UserManagement/Views/VerifyEmail.vue
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/Enumerations/MessageType.php b/app/Enumerations/MessageType.php
new file mode 100644
index 0000000..b4ba22f
--- /dev/null
+++ b/app/Enumerations/MessageType.php
@@ -0,0 +1,8 @@
+ 'wilde-moehre',
- 'local_group_name' => 'Stamm Wilde Möhre',
+ 'name' => 'Stamm Wilde Möhre',
'url' => 'wilde-moehre.mareike.local',
'account_iban' => 'DE12345678901234567890',
'email' => 'test@example1.com',
@@ -32,11 +32,11 @@ class DevelopmentDataSeeder {
User::create([
'firstname' => 'Development',
'lastname' => 'User',
- 'user_role' => UserRole::USER_ROLE_ADMIN,
- 'tenant' => 'lv',
+ 'user_role_main' => UserRole::USER_ROLE_ADMIN,
+ 'user_role_local_group' => UserRole::USER_ROLE_GROUP_LEADER,
+ 'local_group' => 'wilde-moehre',
'email' => 'th.guenther@saale-mail.de',
'password' => bcrypt('development'),
- 'local_group_id' => 1,
'username' => 'development',
]);
}
diff --git a/app/Installer/ProductionDataSeeder.php b/app/Installer/ProductionDataSeeder.php
index dcebdd5..21797a8 100644
--- a/app/Installer/ProductionDataSeeder.php
+++ b/app/Installer/ProductionDataSeeder.php
@@ -58,7 +58,7 @@ class ProductionDataSeeder {
private function installTenants() {
Tenant::create([
'slug' => 'lv',
- 'local_group_name' => 'Landesunmittelbare Mitglieder',
+ 'name' => 'Landesunmittelbare Mitglieder',
'url' => 'mareike.local',
'account_iban' => 'DE12345678901234567890',
'email' => 'test@example.com',
diff --git a/app/MessageTemplates/MessageTemplate.php b/app/MessageTemplates/MessageTemplate.php
new file mode 100644
index 0000000..8ba81ba
--- /dev/null
+++ b/app/MessageTemplates/MessageTemplate.php
@@ -0,0 +1,37 @@
+subject;
+ }
+
+ public function setSubject(string $subject): void
+ {
+ $this->subject = $subject;
+ }
+
+ public function getMessage(): string
+ {
+ return $this->message;
+ }
+
+ public function setMessage(string $message): void
+ {
+ $this->message = $message;
+ }
+
+
+
+}
diff --git a/app/MessageTemplates/Registration/InformAdminAboutNewUserTemplate.php b/app/MessageTemplates/Registration/InformAdminAboutNewUserTemplate.php
new file mode 100644
index 0000000..5c8affd
--- /dev/null
+++ b/app/MessageTemplates/Registration/InformAdminAboutNewUserTemplate.php
@@ -0,0 +1,59 @@
+composeMessage($user);
+ return $template;
+ }
+
+ public function __construct() {
+ $this->subject = "Eine Person hat sich auf mareike registriert";
+ }
+
+ public function composeMessage(User $user): void {
+ $this->message =
+ <<Eine Person hat sich auf mareike angemeldet
+Soeben hat sich eine neue Person auf mareike angemeldet:
+
+
+ | Name: |
+ %1\$s |
+
+
+ | Email: |
+ %2\$s |
+
+
+ | Stamm: |
+ %3\$s |
+
+
+ | Freischaltcode: |
+ %4\$s |
+
+
+
+
+Sollte die Person unberechtigt angemeldet sein, lösche den Account.
+
+HTML;
+
+ $this->message = sprintf($this->message,
+ $user->getFullname(),
+ $user->email,
+ $user->local_group,
+ $user->activation_token
+ );
+ }
+}
diff --git a/app/MessageTemplates/activationCodeTemplate.php b/app/MessageTemplates/activationCodeTemplate.php
new file mode 100644
index 0000000..fe27f2a
--- /dev/null
+++ b/app/MessageTemplates/activationCodeTemplate.php
@@ -0,0 +1,23 @@
+composeMessage($emailAddress, $activationCode);
+ return $template;
+ }
+
+ public function __construct() {
+ $this->subject = "Dein Aktivierungscode";
+ }
+
+ public function composeMessage(EmailAddress $emailAddress, string $activationCode): void {
+ $this->message = "Dein Aktivierungscode lautet: {$activationCode}" . PHP_EOL .
+ "Gib diesen zusammen mit der Mailadresse {$emailAddress->getValue()} ein.";
+ }
+}
diff --git a/app/Models/Tenant.php b/app/Models/Tenant.php
index 35bed28..b46ff1f 100644
--- a/app/Models/Tenant.php
+++ b/app/Models/Tenant.php
@@ -24,7 +24,7 @@ class Tenant extends CommonModel
protected $fillable = [
'slug',
- 'local_group_name',
+ 'name',
'email',
'url',
'account_iban',
diff --git a/app/Models/User.php b/app/Models/User.php
index f93e9d6..e17b389 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -5,6 +5,34 @@ namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
+/**
+ * @property string $username
+ * @property string $local_group
+ * @property string $firstname
+ * @property string $nickname
+ * @property string $lastname
+ * @property string $membership_id
+ * @property string $address_1
+ * @property string $address_2
+ * @property string $postcode
+ * @property string $city
+ * @property string $email
+ * @property string $phone
+ * @property string $birthday
+ * @property string $medications
+ * @property string $allergies
+ * @property string $intolerances
+ * @property string $eating_habits
+ * @property string $swimming_permission
+ * @property string $first_aid_permission
+ * @property string $bank_account_iban
+ * @property string $password
+ * @property boolean $active
+ * @property string $user_role_main
+ * @property string $user_role_local_group
+ * @property string $activation_token
+ * @property string $activation_token_expires_at
+ */
class User extends Authenticatable
{
use Notifiable;
@@ -15,13 +43,15 @@ class User extends Authenticatable
* @var list
*/
protected $fillable = [
- 'tenant_id',
- 'user_role',
+ 'user_role_main',
+ 'user_role_local_group',
+ 'activation_token',
+ 'activation_token_expires_at',
'username',
+ 'local_group',
'firstname',
'nickname',
'lastname',
- 'local_group_id',
'membership_id',
'address_1',
'address_2',
@@ -58,8 +88,19 @@ class User extends Authenticatable
protected function casts(): array
{
return [
- 'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
+
+ public function getFullname() : string {
+ return sprintf('%1$1s %2$s %3$s',
+ $this->firstname,
+ $this->nickname !== '' ? '(' . $this->nickname . ')' : '',
+ $this->lastname
+ );
+ }
+
+ public function getNicename() : string {
+ return $this->nickname !== '' ? $this->nickname : $this->firstname;
+ }
}
diff --git a/app/Providers/AuthCheckProvider.php b/app/Providers/AuthCheckProvider.php
index c93b018..4cb38a7 100644
--- a/app/Providers/AuthCheckProvider.php
+++ b/app/Providers/AuthCheckProvider.php
@@ -10,6 +10,11 @@ class AuthCheckProvider {
$user = auth()->user();
$tenant = app('tenant');
+ if ($tenant->slug === 'lv') {
+ return $user->active;
+ }
+
+
return $user->active && $tenant->slug === $user->tenant;
}
@@ -18,6 +23,10 @@ class AuthCheckProvider {
return null;
}
- return auth()->user()->user_role;
+ if (app('tenant')->slug === 'lv') {
+ return auth()->user()->user_role_main;
+ }
+
+ return auth()->user()->user_role_local_group;
}
}
diff --git a/app/Providers/InertiaProvider.php b/app/Providers/InertiaProvider.php
index 49be165..ea8b422 100644
--- a/app/Providers/InertiaProvider.php
+++ b/app/Providers/InertiaProvider.php
@@ -2,6 +2,7 @@
namespace App\Providers;
+use App\Models\Tenant;
use App\Models\User;
use Inertia\Inertia;
use Inertia\Response;
@@ -21,9 +22,10 @@ final class InertiaProvider
public function render() : Response {
$this->props['navbar'] = $this->generateNavbar();
- $this->props['tenant'] = app('tenant')->local_group_name;
+ $this->props['tenant'] = app('tenant');
$this->props['user'] = $this->user;
$this->props['currentPath'] = request()->path();
+ $this->props['availableLocalGroups'] = Tenant::where(['is_active_local_group' => true])->get();
return Inertia::render(
str_replace('/', '/Views/', $this->vueFile),
diff --git a/app/Providers/TenantUserProvider.php b/app/Providers/TenantUserProvider.php
index c15b9cc..909769c 100644
--- a/app/Providers/TenantUserProvider.php
+++ b/app/Providers/TenantUserProvider.php
@@ -8,6 +8,8 @@ class TenantUserProvider extends EloquentUserProvider
{
public function retrieveByCredentials(array $credentials)
{
+ $credentials['active'] = true;
+
$query = $this->createModel()->newQuery();
foreach ($credentials as $key => $value) {
@@ -16,8 +18,12 @@ class TenantUserProvider extends EloquentUserProvider
}
}
+ if (app('tenant')->slug === 'lv') {
+ return $query->first();
+ }
+
$query->where([
- 'tenant' => app('tenant')->slug,
+ 'local_group' => app('tenant')->slug,
'active' => true
]);
diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php
new file mode 100644
index 0000000..a96bfb6
--- /dev/null
+++ b/app/Repositories/UserRepository.php
@@ -0,0 +1,20 @@
+ $username])->first();
+ }
+
+ public function checkVerificationToken(User $user, string $token) : bool {
+ if (new DateTime() > DateTime::createFromFormat('Y-m-d H:i:s', $user->activation_token_expires_at)) {
+ return false;
+ }
+
+ return $token === $user->activation_token;
+ }
+}
diff --git a/app/Scopes/CommonController.php b/app/Scopes/CommonController.php
index 18f4c94..ee0e119 100644
--- a/app/Scopes/CommonController.php
+++ b/app/Scopes/CommonController.php
@@ -3,8 +3,15 @@
namespace App\Scopes;
use App\Providers\AuthCheckProvider;
+use App\Repositories\UserRepository;
abstract class CommonController {
+ protected UserRepository $users;
+
+ public function __construct() {
+ $this->users = new UserRepository();
+ }
+
protected function checkAuth() {
$authCheckProvider = new AuthCheckProvider;
return $authCheckProvider->checkLoggedIn();
diff --git a/app/ValueObjects/EmailAddress.php b/app/ValueObjects/EmailAddress.php
new file mode 100644
index 0000000..7309928
--- /dev/null
+++ b/app/ValueObjects/EmailAddress.php
@@ -0,0 +1,26 @@
+setValue($value);
+ return $emailAddress;
+ }
+
+ public function getValue(): string
+ {
+ return $this->value;
+ }
+
+ public function setValue(string $value): void
+ {
+ $this->value = $value;
+ }
+}
diff --git a/app/ValueObjects/MessageRecipient.php b/app/ValueObjects/MessageRecipient.php
new file mode 100644
index 0000000..ade85dc
--- /dev/null
+++ b/app/ValueObjects/MessageRecipient.php
@@ -0,0 +1,50 @@
+user = null;
+ $this->emailAddresses = [];
+ $this->name = "";
+ }
+
+ public function getUser(): ?User
+ {
+ return $this->user;
+ }
+
+ public function setUser(?User $user): void
+ {
+ $this->user = $user;
+ }
+
+ public function getEmailAddresses(): array
+ {
+ return $this->emailAddresses;
+ }
+
+ public function addEmailAddress(EmailAddress $emailAddresses): void
+ {
+ $this->emailAddresses[] = $emailAddresses;
+ }
+
+ public function getName(): string
+ {
+ return $this->name;
+ }
+
+ public function setName(string $name): void
+ {
+ $this->name = $name;
+ }
+
+
+}
diff --git a/app/Views/Components/ErrorText.vue b/app/Views/Components/ErrorText.vue
new file mode 100644
index 0000000..2e53b14
--- /dev/null
+++ b/app/Views/Components/ErrorText.vue
@@ -0,0 +1,10 @@
+
+
+
+ {{ props.message }}
+
+
diff --git a/config/app.php b/config/app.php
index 423eed5..6fad0ed 100644
--- a/config/app.php
+++ b/config/app.php
@@ -65,7 +65,7 @@ return [
|
*/
- 'timezone' => 'UTC',
+ 'timezone' => 'Europe/Berlin',
/*
|--------------------------------------------------------------------------
diff --git a/database/migrations/2026_01_30_140001_create_tenants.php b/database/migrations/2026_01_30_140001_create_tenants.php
index ddd4f7e..10982f2 100644
--- a/database/migrations/2026_01_30_140001_create_tenants.php
+++ b/database/migrations/2026_01_30_140001_create_tenants.php
@@ -9,7 +9,7 @@ return new class extends Migration {
Schema::create('tenants', function (Blueprint $table) {
$table->id();
$table->string('slug')->unique();
- $table->string('local_group_name');
+ $table->string('name');
$table->string('email');
$table->string('url');
$table->string('account_iban');
diff --git a/database/migrations/2026_01_30_140002_create_users_table.php b/database/migrations/2026_01_30_140002_create_users_table.php
index b745d24..0a9c1ce 100644
--- a/database/migrations/2026_01_30_140002_create_users_table.php
+++ b/database/migrations/2026_01_30_140002_create_users_table.php
@@ -38,14 +38,14 @@ return new class extends Migration
Schema::create('users', function (Blueprint $table) {
$table->id();
- $table->string('tenant');
- $table->string('user_role');
+ $table->string('user_role_main');
+ $table->string('user_role_local_group');
$table->string('username')->unique();
$table->string('password')->nullable();
+ $table->string('local_group');
$table->string('firstname');
$table->string('nickname')->nullable();
$table->string('lastname');
- $table->foreignId('local_group_id')->references('id')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate();
$table->string('membership_id')->nullable();
$table->string('address_1')->nullable();
$table->string('address_2')->nullable();
@@ -62,10 +62,12 @@ return new class extends Migration
$table->string('first_aid_permission')->nullable();
$table->string('bank_account_iban')->nullable();
$table->string('activation_token')->nullable();
+ $table->dateTime('activation_token_expires_at')->nullable()->default(date('Y-m-d H:i:s', strtotime('+3 days')));
$table->boolean('active')->default(false);
- $table->foreign('tenant')->references('slug')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate();
- $table->foreign('user_role')->references('slug')->on('user_roles')->cascadeOnDelete()->cascadeOnUpdate();
+ $table->foreign('local_group')->references('slug')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate();
+ $table->foreign('user_role_main')->references('slug')->on('user_roles')->cascadeOnDelete()->cascadeOnUpdate();
+ $table->foreign('user_role_local_group')->references('slug')->on('user_roles')->cascadeOnDelete()->cascadeOnUpdate();
$table->foreign('swimming_permission')->references('slug')->on('swimming_permissions')->cascadeOnDelete()->cascadeOnUpdate();
$table->foreign('eating_habits')->references('slug')->on('eating_habits')->cascadeOnDelete()->cascadeOnUpdate();
$table->foreign('first_aid_permission')->references('slug')->on('first_aid_permissions')->cascadeOnDelete()->cascadeOnUpdate();
diff --git a/docker-compose.dev b/docker-compose.dev
index ea842a7..338256a 100644
--- a/docker-compose.dev
+++ b/docker-compose.dev
@@ -18,7 +18,7 @@ services:
labels:
- "traefik.enable=true"
- - "traefik.http.routers.mareike.rule=Host(`mareike.local`) || Host(`admin.mareike.local`) || Host(`wilde-moehre.mareike.local`)"
+ - "traefik.http.routers.mareike.rule=Host(`mareike.local`) || Host(`admin.mareike.local`) || Host(`wilde-moehre.mareike.local`) || Host(`fennek.mareike.local`)"
- "traefik.http.routers.mareike.entrypoints=websecure"
- "traefik.http.routers.mareike.tls=true"
- "traefik.http.services.mareike.loadbalancer.server.port=80"
@@ -46,13 +46,6 @@ services:
- ./:/var/www/html
command: >
sh -c "
- npm install &&
- npm install vue3-toastify && npm install @inertiajs/progress && npm install @inertiajs/progress &&
- npm install @fortawesome/fontawesome-svg-core &&
- npm install @fortawesome/free-solid-svg-icons &&
- npm install @fortawesome/vue-fontawesome@latest &&
-
-
while true; do
npm run build
echo 'Vite Dev-Server beendet. Neustart in 3 Sekunden...'
diff --git a/public/css/app.css b/public/css/app.css
index fc27ddc..27dced7 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -118,6 +118,7 @@ html {
th {
text-align: left;
padding-right: 1em;
+ vertical-align: top;
}
th:after {
diff --git a/public/css/elements.css b/public/css/elements.css
index 56e0e27..3edacfb 100644
--- a/public/css/elements.css
+++ b/public/css/elements.css
@@ -12,20 +12,28 @@
input[type="text"],
input[type="email"],
-input[type="password"] {
+input[type="password"],
+select {
width: 100%;
font-size: 13pt;
padding: 5px;
border: 1px solid #ccc;
border-radius: 5px;
color: #656363;
+ background-color: #ffffff;
+}
+
+select {
+ width: calc(100% + 10px);
}
input[type="text"]:focus,
input[type="email"]:focus,
-input[type="password"]:focus {
+input[type="password"]:focus,
+select:focus {
outline: none;
border-color: #1d4899;
+ color: #1d4899;
}
@@ -33,7 +41,8 @@ table {
width: 100%;
}
-button, input[type="submit"] {
+input[type="button"],
+input[type="submit"] {
cursor: pointer;
background-color: #ffffff;
border: 1px solid #809dd5 !important;
@@ -41,7 +50,13 @@ button, input[type="submit"] {
font-weight: bold;
}
-button:hover, input[type="submit"]:hover {
+input[type="button"]:hover,
+input[type="submit"]:hover {
background-color: #1d4899;
color: #ffffff;
}
+
+.error_text {
+ color: red;
+ display: block;
+}
diff --git a/resources/js/components/ajaxHandler.js b/resources/js/components/ajaxHandler.js
new file mode 100644
index 0000000..6f208cb
--- /dev/null
+++ b/resources/js/components/ajaxHandler.js
@@ -0,0 +1,80 @@
+import { ref } from "vue"
+
+export function useAjax() {
+ const loading = ref(false)
+ const error = ref(null)
+ const data = ref(null)
+
+ async function request(url, options = {}) {
+ loading.value = true
+ error.value = null
+ data.value = null
+
+ try {
+ const response = await fetch(url, {
+ method: options.method || "GET",
+ headers: {
+ "Content-Type": "application/json",
+ ...(options.headers || {}),
+ },
+ body: options.body ? JSON.stringify(options.body) : null,
+ })
+
+ if (!response.ok) throw new Error(`HTTP ${response.status}`)
+ const result = await response.json()
+ data.value = result
+ return result
+ } catch (err) {
+ error.value = err
+ console.error("AJAX Error:", err)
+ return null
+ } finally {
+ loading.value = false
+ }
+ }
+
+ async function download(url, options = {}) {
+ loading.value = true
+ error.value = null
+
+ try {
+ const response = await fetch(url, {
+ method: options.method || "GET",
+ headers: {
+ ...(options.headers || {}),
+ },
+ body: options.body ? JSON.stringify(options.body) : null,
+ })
+
+ if (!response.ok) throw new Error(`HTTP ${response.status}`)
+
+ const blob = await response.blob()
+ const filename =
+ options.filename ||
+ response.headers
+ .get("Content-Disposition")
+ ?.split("filename=")[1]
+ ?.replace(/["']/g, "") ||
+ "download.bin"
+
+ const downloadUrl = window.URL.createObjectURL(blob)
+ const a = document.createElement("a")
+ a.href = downloadUrl
+ a.download = filename
+ document.body.appendChild(a)
+ a.click()
+ a.remove()
+ window.URL.revokeObjectURL(downloadUrl)
+
+ return true
+ } catch (err) {
+ error.value = err
+ console.error("Download Error:", err)
+ return false
+ } finally {
+ loading.value = false
+ }
+ }
+
+ return {data, loading, error, request, download}
+}
diff --git a/resources/views/app.blade.php b/resources/views/app.blade.php
index d63bb32..90c776a 100644
--- a/resources/views/app.blade.php
+++ b/resources/views/app.blade.php
@@ -1,8 +1,8 @@
-
-
+
+
diff --git a/routes/api.php b/routes/api.php
index 1b1d16a..3877b9c 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -1,15 +1,3 @@
config('app.name'),
- ]);
-});
+require __DIR__.'/../app/Domains/UserManagement/Routes/api.php';
diff --git a/routes/web.php b/routes/web.php
index c85a4b6..6510d5b 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -1,23 +1,24 @@
group(function () {
Route::get('/', DashboardController::class);
-
-
Route::middleware(['auth'])->group(function () {
Route::get('/messages', fn () => inertia('Messages'));
- Route::post('/logout', [LogoutController::class, 'logout']);
});
@@ -27,9 +28,6 @@ Route::middleware(IdentifyTenant::class)->group(function () {
- route::get('/logout', LogOutController::class);
- route::post('/login', [LoginController::class, 'doLogin']);
- route::get('/login', [LoginController::class, 'loginForm']);
Route::get('/messages', [TestRenderInertiaProvider::class, 'index']);