Compare commits

..

70 Commits

Author SHA1 Message Date
philipp lang 667fc4b731 Cleanup
continuous-integration/drone/push Build is failing Details
2024-12-08 23:50:47 +01:00
philipp lang 50a5d6216b Add Password Reset email page 2024-12-08 23:38:03 +01:00
philipp lang cc1c12d9f1 Add Login module 2024-12-07 14:56:33 +01:00
philipp lang 5653489fa6 Move DPSG Icon 2024-12-07 14:06:32 +01:00
philipp lang dbdadde542 Add title and menu to Page component 2024-12-06 16:54:32 +01:00
philipp lang e664255d7c Add head component for html page head tag 2024-12-06 16:38:43 +01:00
philipp lang 612b782c9b Fix error handling for mailgateway forms 2024-12-05 15:10:57 +01:00
philipp lang e5b2e1799f Add error handling via tooltip 2024-12-05 15:10:57 +01:00
philipp lang 110ad9d978 Fix: Add id to select field 2024-12-05 15:10:57 +01:00
philipp lang 0cb6f9111e Add Vite facade 2024-12-05 15:10:57 +01:00
philipp lang aceb2b0a73 Add Danger theme for tippy 2024-12-05 15:10:57 +01:00
philipp lang 36412a7e90 Add vite spritemap 2024-12-05 15:10:57 +01:00
philipp lang 5c8a597fef Update sprite component 2024-12-05 15:10:57 +01:00
philipp lang becd5881c3 Add validation attributes to nami field 2024-12-05 15:10:57 +01:00
philipp lang de508aa8ce Add SettingIntro component 2024-12-05 15:10:57 +01:00
philipp lang bafdb86f95 Add Nami Settings 2024-12-05 15:10:57 +01:00
philipp lang 31d9b38814 Move test files 2024-12-05 15:10:57 +01:00
philipp lang 1e5bd6127c Add page title 2024-12-05 15:10:57 +01:00
philipp lang c52995aeb7 Add active menu entry for setting 2024-12-05 15:10:57 +01:00
philipp lang 98f567b6cd Set active title for setting 2024-12-05 15:10:56 +01:00
philipp lang 0d04d9ee99 Update arch tests 2024-12-05 15:10:56 +01:00
philipp lang 4877b59f46 Lint 2024-12-05 15:10:56 +01:00
philipp lang 5263c2c976 Move types 2024-12-05 15:10:56 +01:00
philipp lang 494fc30d21 Move modules 2024-12-05 15:10:56 +01:00
philipp lang 3199a2d5fb Add Badge component 2024-12-05 15:10:56 +01:00
philipp lang bc55d19ed0 Add data type cast for Mailgateway 2024-12-05 15:10:56 +01:00
philipp lang 9333b1e562 Allow MailmanTypeRequest to cast to data 2024-12-05 15:10:56 +01:00
philipp lang 019f421c9b Mod setArray macro for nested values 2024-12-05 15:10:56 +01:00
philipp lang a0091ec995 Simplify form 2024-12-05 15:10:56 +01:00
philipp lang 969406313d Update update hook 2024-12-05 15:10:56 +01:00
philipp lang 43e1fd4080 Add test for events 2024-12-05 15:10:56 +01:00
philipp lang a51258bef9 Lint 2024-12-05 15:10:56 +01:00
philipp lang 5b52d94390 Update refresh page 2024-12-05 15:10:56 +01:00
philipp lang 99f32d49f8 Add mailgateway 2024-12-05 15:10:56 +01:00
philipp lang e5916c65df Fix layout 2024-12-05 15:10:56 +01:00
philipp lang 17beda5524 Remove old MailgatewayRequestFactory 2024-12-05 15:10:56 +01:00
philipp lang 45ccc16979 Lint 2024-12-05 15:10:56 +01:00
philipp lang 818a72e133 Add HTTP Check to MailmanTypeRequest 2024-12-05 15:10:56 +01:00
philipp lang 01512705e3 Delete old mailgateway tests 2024-12-05 15:10:56 +01:00
philipp lang 004a3b7a0f Mark MailgatewayResource as deprecated 2024-12-05 15:10:56 +01:00
philipp lang 5518f54f0c Mark old mailgateway settings as deprecated 2024-12-05 15:10:56 +01:00
philipp lang 4351dab663 Add BooleanDisplay component 2024-12-05 15:10:56 +01:00
philipp lang c27bf43b4a Make right slot optional in SettingLayout 2024-12-05 15:10:56 +01:00
philipp lang 582d252e36 fixup! Add modal component 2024-12-05 15:10:56 +01:00
philipp lang e197c236d6 Add testable macro for setArray 2024-12-05 15:10:56 +01:00
philipp lang 4da1e01296 Add modal component 2024-12-05 15:10:56 +01:00
philipp lang 689614ee93 Throw exception when variant not found 2024-12-05 15:10:56 +01:00
philipp lang 9d5122b13f Lint 2024-12-05 15:10:56 +01:00
philipp lang 66561ad43e Merge attributes for hint 2024-12-05 15:10:56 +01:00
philipp lang 867cf99a44 Lint 2024-12-05 15:10:56 +01:00
philipp lang b0a8cf5d1b Fix Tooltip attribute of Table action 2024-12-05 15:10:56 +01:00
philipp lang 5c925dd92b Register MailgatewayServiceProvider 2024-12-05 15:10:56 +01:00
philipp lang 963f8c02a9 Add select field 2024-12-05 15:10:56 +01:00
philipp lang 5c4c9f130b Disable autocomplete for password fields 2024-12-05 15:10:56 +01:00
philipp lang a76da98d61 Fix label required 2024-12-05 15:10:56 +01:00
philipp lang 04addccde5 Add Table action button 2024-12-05 15:10:56 +01:00
philipp lang e4d1df6a28 Add table component 2024-12-05 15:10:56 +01:00
philipp lang 17f3aff307 Mod Component Test 2024-12-05 15:10:56 +01:00
philipp lang 3a0ebb2483 Move Dashboard registrations 2024-12-05 15:10:56 +01:00
philipp lang 4b89bbfda4 Add Settings for Bill 2024-12-05 15:10:56 +01:00
philipp lang 4188f0733c Add Toast and tooltip 2024-12-05 15:10:56 +01:00
philipp lang f93a0efed2 Remove Base tests from Composer 2024-12-05 15:10:56 +01:00
philipp lang 6b40951b9e Add Component Resolver for Modules 2024-12-05 15:10:56 +01:00
philipp lang ddaa1a5027 Add Dashboard 2024-12-05 15:10:56 +01:00
philipp lang f3a3f3cd22 Add Service Provider 2024-12-05 15:10:56 +01:00
philipp lang 22740f8aff Add livewire components 2024-12-05 15:10:56 +01:00
philipp lang 751ef3891b Add config file 2024-12-05 15:10:56 +01:00
philipp lang 645825765d Install Livewire Package 2024-12-05 15:10:56 +01:00
philipp lang 75dc0d9769 Update CHANGELOG
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-11-20 11:11:26 +01:00
philipp lang 9fc8548504 Fix: Dont remember past events
continuous-integration/drone/push Build is passing Details
2024-11-20 11:10:24 +01:00
29 changed files with 394 additions and 287 deletions

View File

@ -1,5 +1,9 @@
# Letzte Änderungen
### 1.11.4
- Fix: Nicht an Präventions-Unterlagen für vergangene Veranstaltungen erinnern
### 1.11.1
- Es kann nun auch das Feld "Datenweiterverwendung" über Adrema gepflegt werden.

View File

@ -17,7 +17,12 @@ class PreventionRememberAction
public function handle(): void
{
$query = Participant::whereHas('form', fn ($form) => $form->where('needs_prevention', true))
$query = Participant::whereHas(
'form',
fn ($form) => $form
->where('needs_prevention', true)
->where('from', '>=', now())
)
->where(
fn ($q) => $q
->where('last_remembered_at', '<=', now()->subWeeks(2))

View File

@ -1,60 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Inertia\Response;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function showLoginForm(): Response
{
session()->put('title', 'Anmelden');
return \Inertia::render('authentication/VLogin');
}
/**
* Validate the user login request.
*/
protected function validateLogin(Request $request): void
{
$request->validate([
$this->username() => 'required|max:255|string|email',
'password' => 'required|string',
]);
}
}

View File

@ -1,71 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* @return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}

View File

@ -2,11 +2,11 @@
namespace App;
use App\Auth\ResetPassword;
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Modules\Auth\Mails\ResetPassword;
class User extends Authenticatable
{

32
app/View/Page/Full.php Normal file
View File

@ -0,0 +1,32 @@
<?php
namespace App\View\Page;
use Illuminate\View\Component;
class Full extends Component
{
public function __construct(public string $title = '', public ?string $heading = null)
{
session()->put('title', $title);
}
public function render()
{
return <<<'HTML'
<div class="min-w-[16rem] sm:min-w-[18rem] md:min-w-[24rem] bg-gray-800 rounded-xl overflow-hidden shadow-lg @if($heading === null) p-6 md:p-10 @endif">
@if ($heading)
<div class="h-24 p-6 md:px-10 bg-primary-800 flex justify-between items-center w-full">
<span class="text-primary-500 text-xl">{{$heading}}</span>
<img src="{{asset('img/dpsg.gif')}}" class="w-24" />
</div>
@endif
<div @if($heading !== null) class="p-6 md:p-10" @endif>
{{ $slot }}
</div>
</div>
HTML;
}
}

View File

@ -7,9 +7,10 @@ use Illuminate\View\Component;
class Layout extends Component
{
public function __construct(public string $pageClass = '', public string $title = '')
public function __construct(public string $pageClass = '', public string $title = '', public string $menu = '')
{
session()->put('title', $title);
session()->put('menu', $menu);
}
public function userName(): string

View File

@ -18,13 +18,12 @@ class SettingLayout extends Component
'is_active' => get_class($setting) === $active,
'title' => $setting->title(),
])->toArray();
session()->put('menu', 'setting');
}
public function render()
{
return <<<'HTML'
<x-page::layout :title="$active::title()">
<x-page::layout :title="$active::title()" menu="setting">
<x-slot:right>
{{ $right ?? '' }}
</x-slot:right>

22
app/View/Ui/Button.php Normal file
View File

@ -0,0 +1,22 @@
<?php
namespace App\View\Ui;
use Illuminate\View\Component;
class Button extends Component
{
public function __construct(public string $type = 'button')
{
}
public function render()
{
return <<<'HTML'
<button type="{{$type}}" class="px-3 py-2 uppercase no-underline text-sm items-center justify-center bg-primary-700 rounded text-primary-300">
{{$slot}}
</button>
HTML;
}
}

View File

@ -183,6 +183,7 @@ return [
Modules\Invoice\InvoiceServiceProvider::class,
Modules\Mailgateway\MailgatewayServiceProvider::class,
Modules\Nami\NamiServiceProvider::class,
Modules\Auth\AuthServiceProvider::class,
],
/*

View File

@ -27,4 +27,9 @@ class UserFactory extends Factory
'lastname' => $this->faker->lastName,
];
}
public function loginData(string $email, string $password): self
{
return $this->state(['email' => $email, 'password' => Hash::make($password)]);
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Modules\Auth;
use Illuminate\Routing\Router;
use Illuminate\Support\ServiceProvider;
use Modules\Auth\Components\LoginForm;
use Modules\Auth\Components\PasswordReset;
class AuthServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
app(Router::class)->middleware(['web', 'guest'])->group(function ($router) {
$router->get('/login', LoginForm::class)->name('login');
$router->get('/password/reset', PasswordReset::class)->name('password.request');
$router->get('/password/reseta', PasswordReset::class)->name('password.reset');
});
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace Modules\Auth\Components;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\Layout;
use Livewire\Component;
class LoginForm extends Component
{
use AuthenticatesUsers;
use ThrottlesLogins;
public string $email = '';
public string $password = '';
public function validateLogin(Request $request)
{
$this->validate([
'email' => 'required|max:255|string|email',
'password' => 'required|string',
]);
}
protected function credentials(Request $request)
{
return ['email' => $this->email, 'password' => $this->password];
}
protected function sendLoginResponse(Request $request)
{
return redirect()->intended('/');
}
public function submit()
{
return $this->login(request());
}
#[Layout('components.layouts.full')]
public function render(): string
{
return <<<'HTML'
<x-page::full heading="Login" title="Login">
<form wire:submit="submit">
<div class="grid gap-5">
<x-form::text name="email" wire:model="email" label="E-Mail-Adresse"></x-form::text>
<x-form::text name="password" wire:model="password" type="password" label="Passwort"></x-form::text>
<x-ui::button type="submit">Login</x-ui::button>
<div class="flex justify-center">
<a href="{{route('password.request')}}" class="text-gray-500 text-sm hover:text-gray-300">Passwort vergessen?</a>
</div>
</div>
</form>
</x-page::full>
HTML;
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace Modules\Auth\Components;
use App\User;
use Illuminate\Auth\Events\Lockout;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Livewire\Livewire;
uses(TestCase::class);
uses(DatabaseTransactions::class);
it('redirects to login', function () {
test()->get('/')->assertRedirect('/login');
});
it('displays component', function () {
test()->get('/login')->assertSeeLivewire(LoginForm::class)->assertDontSee('Dashboard');
});
it('displays form', function () {
Livewire::test(LoginForm::class)
->assertSee('Login')
->assertSee('Passwort vergessen')
->assertSee(route('password.request'));
});
it('loggs in', function () {
User::factory()->loginData('admin@example.com', 'secret')->create();
Livewire::test(LoginForm::class)
->set('email', 'admin@example.com')
->set('password', 'secret')
->call('submit')
->assertRedirect('/');
$this->assertEquals('admin@example.com', auth()->user()->email);
});
it('displays failed login response', function () {
Livewire::test(LoginForm::class)
->set('email', 'admin@example.com')
->set('password', 'secret')
->call('submit')
->assertHasErrors(['email' => 'Login fehlgeschlagen.']);
});
it('increments login attempts', function () {
Event::fake([Lockout::class]);
Livewire::test(LoginForm::class)
->set('email', 'admin@example.com')
->set('password', 'secret')
->call('submit')
->call('submit')
->call('submit')
->call('submit')
->call('submit')
->call('submit');
Event::assertDispatchedTimes(Lockout::class);
});
it('requires email and password', function () {
User::factory()->loginData('admin@example.com', 'secret')->create();
Livewire::test(LoginForm::class)
->set('email', '')
->set('password', '')
->call('submit')
->assertHasErrors(['email', 'password']);
});

View File

@ -0,0 +1,66 @@
<?php
namespace Modules\Auth\Components;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\Layout;
use Livewire\Component;
class PasswordReset extends Component
{
use SendsPasswordResetEmails;
public string $email = '';
protected function validateEmail(Request $request)
{
$this->validate([
'email' => 'required|max:255|string|email',
]);
}
protected function sendResetLinkFailedResponse(Request $request, $response)
{
throw ValidationException::withMessages([
'email' => [trans($response)],
]);
}
protected function credentials(Request $request)
{
return ['email' => $this->email];
}
public function submit()
{
$this->sendResetLinkEmail(request());
$this->dispatch('success', 'Du hast weitere Instruktionen per E-Mail erhalten.');
}
#[Layout('components.layouts.full')]
public function render(): string
{
return <<<'HTML'
<x-page::full heading="Passwort vergessen" title="Passwort vergessen">
<form wire:submit.prevent="submit">
<div class="grid gap-5">
<span class="text-gray-500 text-sm"
>Hier kannst du dein Passwort zurücksetzen.<br />
Gebe dafür die E-Mail-Adresse deines Benutzerkontos ein.<br />
Anschließend bekommst du eine E-Mail<br />
mit weiteren Anweisungen.</span
>
<x-form::text name="email" wire:model="email" label="E-Mail-Adresse"></x-form::text>
<x-ui::button type="submit">Passwort zurücksetzen</x-ui::button>
<div class="flex justify-center">
<a href="/login" class="text-gray-500 text-sm hover:text-gray-300">Zurück zum Login</a>
</div>
</div>
</form>
</x-page::full>
HTML;
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace Modules\Auth\Components;
use Modules\Auth\Mails\ResetPassword;
use App\User;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Notification;
use Livewire\Livewire;
uses(TestCase::class);
uses(DatabaseTransactions::class);
it('displays component', function () {
test()->get(route('password.request'))->assertSeeLivewire(PasswordReset::class)->assertDontSee('Dashboard');
});
it('shows intro', function () {
Livewire::test(PasswordReset::class)->assertSee('Hier kannst du dein Passwort zurücksetzen.');
});
it('it needs email address', function (string $email, string $error) {
Livewire::test(PasswordReset::class)
->set('email', $email)
->call('submit')
->assertHasErrors(['email' => $error]);
})
->with([
['', 'E-Mail Adresse ist erforderlich.'],
['aaa', 'E-Mail Adresse muss eine gültige E-Mail-Adresse sein.'],
]);
it('displays error when user doesnt exsst', function () {
Livewire::test(PasswordReset::class)
->set('email', 'nowhere@example.com')
->call('submit')
->assertHasErrors(['email' => 'Es konnte leider kein Nutzer mit dieser E-Mail-Adresse gefunden werden.']);
});
it('requests link', function () {
Notification::fake();
$user = User::factory()->loginData('admin@example.com', 'secret')->create();
Livewire::test(PasswordReset::class)
->set('email', 'admin@example.com')
->call('submit')
->assertDispatched('success', 'Du hast weitere Instruktionen per E-Mail erhalten.');
Notification::assertSentTo($user, ResetPassword::class);
});

View File

@ -1,6 +1,6 @@
<?php
namespace App\Auth;
namespace Modules\Auth\Mails;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Lang;
@ -17,7 +17,7 @@ class ResetPassword extends BaseResetPassword
protected function buildMailMessage($url)
{
return (new MailMessage)
->subject(Lang::get('Passwort zurücksetzen | Adrema'))
->subject(Lang::get('Passwort zurücksetzen | ' . config('app.name')))
->line(Lang::get('Du erhälst diese E-Mail, weil du eine Anfrage zum zurücksetzen deines Account-Passworts gestellt hast.'))
->action(Lang::get('Passwort zurücksetzen'), $url)
->line(Lang::get('Dieser Link wird in :count Minuten ablaufen.', ['count' => config('auth.passwords.' . config('auth.defaults.passwords') . '.expire')]))

View File

@ -12,16 +12,13 @@ class DashboardComponent extends Component
public function mount(DashboardFactory $factory): void
{
session()->put('menu', 'dashboard');
session()->put('title', 'Dashboard');
$this->blocks = $factory->load();
}
public function render(): string
{
return <<<'HTML'
<x-page::layout>
<x-page::layout title="Dashboard" menu="dashboard">
<div class="gap-6 md:grid-cols-2 xl:grid-cols-4 grid p-6">
@foreach($this->blocks as $block)
<x-ui::box title="{{$block->title()}}" :second="true">

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -1,10 +0,0 @@
<template>
<div class="h-24 p-6 md:px-10 bg-primary-800 flex justify-between items-center w-full">
<span class="text-primary-500 text-xl"><slot></slot></span>
<img src="../../../img/dpsg.gif" class="w-24" />
</div>
</template>
<script>
export default {};
</script>

View File

@ -1,36 +0,0 @@
<template>
<page-full-layout banner>
<template #heading>
<page-full-heading-banner>Login</page-full-heading-banner>
</template>
<form @submit.prevent="submit">
<div class="grid gap-5">
<f-text id="email" v-model="values.email" label="E-Mail-Adresse"></f-text>
<f-text id="password" v-model="values.password" type="password" label="Passwort"></f-text>
<button type="submit" class="btn btn-primary">Login</button>
</div>
</form>
</page-full-layout>
</template>
<script>
import FullLayout from '../layouts/FullLayout.vue';
export default {
layout: FullLayout,
data: function () {
return {
values: {
email: '',
password: '',
},
};
},
methods: {
submit() {
this.$inertia.post('/login', this.values);
},
},
};
</script>

View File

@ -1,39 +0,0 @@
<template>
<page-full-layout banner>
<template #heading>
<page-full-heading-banner>Login</page-full-heading-banner>
</template>
<form @submit.prevent="submit">
<div class="grid gap-5">
<f-text id="email" v-model="values.email" label="E-Mail-Adresse"></f-text>
<f-text id="password" v-model="values.password" type="password" label="Passwort"></f-text>
<button type="submit" class="btn btn-primary">Login</button>
<div class="flex justify-center">
<button type="button" class="text-gray-500 text-sm hover:text-gray-300" @click.prevent="$inertia.visit('/password/reset')">Passwort vergessen?</button>
</div>
</div>
</form>
</page-full-layout>
</template>
<script>
import FullLayout from '../../layouts/FullLayout.vue';
export default {
layout: FullLayout,
data: function () {
return {
values: {
email: '',
password: '',
},
};
},
methods: {
submit() {
this.$inertia.post('/login', this.values);
},
},
};
</script>

View File

@ -12,6 +12,6 @@ return [
|
*/
'failed' => 'Diese Kombination aus Zugangsdaten wurde nicht in unserer Datenbank gefunden.',
'failed' => 'Login fehlgeschlagen.',
'throttle' => 'Zu viele Loginversuche. Versuchen Sie es bitte in :seconds Sekunden nochmal.',
];

View File

@ -0,0 +1,12 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<title>{{ session()->get('title') }} | {{ config('app.name') }}</title>
<meta name="socketport" content="{{env('SOCKET_PORT')}}" />
<meta name="adrema_base_url" content="/">
@if(auth()->id())
<meta name="meilisearch_key" content="{{config('scout.meilisearch.key')}}" />
@endif
@vite('resources/livewire-js/app.js')
</head>

View File

@ -1,17 +1,6 @@
<!DOCTYPE html>
<html class="h-full" lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<title>{{ session()->get('title') }} | {{ config('app.name') }}</title>
<meta name="socketport" content="{{env('SOCKET_PORT')}}" />
<meta name="adrema_base_url" content="/">
@if(auth()->id())
<meta name="meilisearch_key" content="{{config('scout.meilisearch.key')}}" />
@endif
@vite('resources/livewire-js/app.js')
</head>
<x-head></x-head>
<body class="min-h-full flex flex-col">
<livewire:page.sidebar />
{{ $slot }}

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html class="h-full" lang="de">
<x-head></x-head>
<body class="min-h-full flex justify-center items-center bg-gray-900">
{{ $slot }}
@livewireScriptConfig
</body>
</html>

View File

@ -76,9 +76,7 @@ use App\Membership\Actions\MembershipStoreAction;
use App\Membership\Actions\MembershipUpdateAction;
use App\Payment\SubscriptionController;
Route::group(['namespace' => 'App\\Http\\Controllers'], function (): void {
Auth::routes(['register' => false]);
});
Route::group(['middleware' => 'auth:web'], function (): void {
Route::post('/nami/login-check', NamiLoginCheckAction::class)->name('nami.login-check');

View File

@ -1,44 +0,0 @@
<?php
namespace Tests\Feature\Authentication;
use App\Auth\ResetPassword;
use App\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class ForgotPasswordTest extends TestCase
{
use DatabaseTransactions;
public function testItShowsResetForm(): void
{
$this->withoutExceptionHandling();
$this->get('/password/reset')->assertComponent('authentication/PasswordReset');
}
public function testItRequiresAnEmailAddress(): void
{
$this->postJson('/password/email')->assertJsonValidationErrors(['email' => 'E-Mail Adresse ist erforderlich.']);
}
public function testItNeedsAnActiveUser(): void
{
$this->postJson('/password/email', [
'email' => 'test@aa.de',
])->assertJsonValidationErrors(['email' => 'Es konnte leider kein Nutzer mit dieser E-Mail-Adresse gefunden werden.']);
}
public function testItSendsPasswordResetLink(): void
{
Notification::fake();
$user = User::factory()->create(['email' => 'test@aa.de']);
$this->postJson('/password/email', [
'email' => 'test@aa.de',
])->assertOk();
Notification::assertSentTo($user, ResetPassword::class);
}
}

View File

@ -39,6 +39,18 @@ class PreventionTest extends TestCase
$this->assertEquals(now()->format('Y-m-d'), $participant->fresh()->last_remembered_at->format('Y-m-d'));
}
public function testItDoesntRememberPastEvents(): void
{
Mail::fake();
$form = $this->createForm();
$participant = $this->createParticipant($form);
$form->update(['from' => now()->subDay()]);
PreventionRememberAction::run();
$this->assertNull($participant->fresh()->last_remembered_at);
}
public function testItDoesntRememberWhenConditionDoesntMatch(): void
{
Mail::fake();