ifsg: can be confirmed and edited by admins
This commit is contained in:
parent
400edd9a19
commit
873803eb2d
|
@ -51,6 +51,15 @@ $route->addGroup(
|
|||
}
|
||||
);
|
||||
|
||||
// User admin settings
|
||||
$route->addGroup(
|
||||
'/users/{user_id:\d+}',
|
||||
function (RouteCollector $route): void {
|
||||
$route->get('/certificates', 'Admin\\UserSettingsController@certificate');
|
||||
$route->post('/certificates/ifsg', 'Admin\\UserSettingsController@saveIfsgCertificate');
|
||||
}
|
||||
);
|
||||
|
||||
// Password recovery
|
||||
$route->addGroup(
|
||||
'/password/reset',
|
||||
|
|
|
@ -24,6 +24,7 @@ class LicenseFactory extends Factory
|
|||
|
||||
$ifsg_certificate = $this->faker->boolean(0.1);
|
||||
$ifsg_certificate_light = $this->faker->boolean(0.5) && !$ifsg_certificate;
|
||||
$ifsg_confirmed = $this->faker->boolean(0.5) && ($ifsg_certificate || $ifsg_certificate_light);
|
||||
|
||||
return [
|
||||
'user_id' => User::factory(),
|
||||
|
@ -35,6 +36,7 @@ class LicenseFactory extends Factory
|
|||
'drive_12t' => $drive_12t,
|
||||
'ifsg_certificate' => $ifsg_certificate,
|
||||
'ifsg_certificate_light' => $ifsg_certificate_light,
|
||||
'ifsg_confirmed' => $ifsg_confirmed,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Migrations;
|
||||
|
||||
use Engelsystem\Database\Migration\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class AddIfsgConfirmedToUsersLicenses extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
$this->schema->table('users_licenses', function (Blueprint $table): void {
|
||||
$table->boolean('ifsg_confirmed')->default(false)->after('ifsg_certificate');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migration
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
$this->schema->table('users_licenses', function (Blueprint $table): void {
|
||||
$table->dropColumn('ifsg_confirmed');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Migrations;
|
||||
|
||||
use Engelsystem\Database\Migration\Migration;
|
||||
|
||||
class AddUserIfsgEditPermission extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
$db = $this->schema->getConnection();
|
||||
$db->table('privileges')
|
||||
->insert([
|
||||
'name' => 'user.ifsg.edit', 'description' => 'Edit IfSG Certificate',
|
||||
]);
|
||||
|
||||
$editIfsg = $db->table('privileges')
|
||||
->where('name', 'user.ifsg.edit')
|
||||
->get(['id'])
|
||||
->first();
|
||||
|
||||
$shico = 60;
|
||||
$team_coordinator = 65;
|
||||
$db->table('group_privileges')
|
||||
->insertOrIgnore([
|
||||
['group_id' => $shico, 'privilege_id' => $editIfsg->id],
|
||||
['group_id' => $team_coordinator, 'privilege_id' => $editIfsg->id],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migration
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
$db = $this->schema->getConnection();
|
||||
$db->table('privileges')
|
||||
->where('name', 'user.ifsg.edit')
|
||||
->delete();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Engelsystem\Database\Db;
|
||||
use Engelsystem\Models\AngelType;
|
||||
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||
use Engelsystem\Models\User\State;
|
||||
use Engelsystem\Models\User\User;
|
||||
|
@ -248,6 +249,12 @@ function user_controller()
|
|||
->with(['user', 'creator'])
|
||||
->get();
|
||||
|
||||
$is_ifsg_supporter = (bool) AngelType::whereRequiresIfsgCertificate(true)
|
||||
->leftJoin('user_angel_type', 'user_angel_type.angel_type_id', 'angel_types.id')
|
||||
->where('user_angel_type.user_id', $user->id)
|
||||
->where('user_angel_type.supporter', true)
|
||||
->count();
|
||||
|
||||
return [
|
||||
htmlspecialchars($user_source->displayName),
|
||||
User_view(
|
||||
|
@ -261,7 +268,8 @@ function user_controller()
|
|||
$tshirt_score,
|
||||
auth()->can('admin_active'),
|
||||
auth()->can('admin_user_worklog'),
|
||||
$worklogs
|
||||
$worklogs,
|
||||
auth()->can('user.ifsg.edit') || $is_ifsg_supporter,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -197,10 +197,10 @@ function AngelType_view_buttons(
|
|||
if ($angeltype->requires_driver_license) {
|
||||
$buttons[] = button(
|
||||
url('/settings/certificates'),
|
||||
icon('person-vcard') . __('my driving license')
|
||||
icon('person-vcard') . __('My driving license')
|
||||
);
|
||||
}
|
||||
if (config('isfg_enabled') && $angeltype->requires_ifsg_certificate) {
|
||||
if (config('ifsg_enabled') && $angeltype->requires_ifsg_certificate) {
|
||||
$buttons[] = button(
|
||||
url('/settings/certificates'),
|
||||
icon('card-checklist') . __('angeltype.ifsg.own')
|
||||
|
@ -294,14 +294,35 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
|
|||
$member['has_license_forklift'] = icon_bool($member->license->drive_forklift);
|
||||
}
|
||||
if ($angeltype->requires_ifsg_certificate && config('ifsg_enabled')) {
|
||||
$member['ifsg_certificate'] = icon_bool($member->license->ifsg_certificate);
|
||||
$ifsg_certificate = $member->license->ifsg_certificate;
|
||||
$member['ifsg_certificate'] = ($member->license->ifsg_confirmed && $ifsg_certificate)
|
||||
? icon('check2-all', 'text-success')
|
||||
: icon_bool($ifsg_certificate);
|
||||
if (config('ifsg_light_enabled')) {
|
||||
$member['ifsg_certificate_light'] = icon_bool($member->license->ifsg_certificate_light);
|
||||
$ifsg_certificate_light = $member->license->ifsg_certificate_light;
|
||||
$member['ifsg_certificate_light'] = ($member->license->ifsg_confirmed && $ifsg_certificate_light)
|
||||
? icon('check2-all', 'text-success')
|
||||
: icon_bool($ifsg_certificate_light);
|
||||
}
|
||||
}
|
||||
|
||||
$edit_certificates = '';
|
||||
if (
|
||||
($angeltype->requires_driver_license || $angeltype->requires_ifsg_certificate)
|
||||
&& ($admin_user_angeltypes || auth()->can('user.ifsg.edit'))
|
||||
) {
|
||||
$edit_certificates =
|
||||
button(
|
||||
url('/users/' . $member->id . '/certificates'),
|
||||
icon('card-checklist'),
|
||||
'btn-sm',
|
||||
'',
|
||||
__('Edit certificates'),
|
||||
);
|
||||
}
|
||||
if ($angeltype->restricted && empty($member->pivot->confirm_user_id)) {
|
||||
$member['actions'] = table_buttons([
|
||||
$edit_certificates,
|
||||
button(
|
||||
url(
|
||||
'/user-angeltypes',
|
||||
|
@ -323,6 +344,7 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
|
|||
} elseif ($member->pivot->supporter) {
|
||||
if ($admin_angeltypes || ($admin_user_angeltypes && config('supporters_can_promote'))) {
|
||||
$member['actions'] = table_buttons([
|
||||
$edit_certificates,
|
||||
button(
|
||||
url('/user-angeltypes', [
|
||||
'action' => 'update',
|
||||
|
@ -336,12 +358,15 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
|
|||
),
|
||||
]);
|
||||
} else {
|
||||
$member['actions'] = '';
|
||||
$member['actions'] = $edit_certificates
|
||||
? table_buttons([$edit_certificates,])
|
||||
: '';
|
||||
}
|
||||
$supporters[] = $member;
|
||||
} else {
|
||||
if ($admin_user_angeltypes) {
|
||||
$member['actions'] = table_buttons([
|
||||
$edit_certificates,
|
||||
($admin_angeltypes || config('supporters_can_promote')) ?
|
||||
button(
|
||||
url('/user-angeltypes', [
|
||||
|
@ -366,6 +391,10 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
|
|||
__('Remove'),
|
||||
),
|
||||
]);
|
||||
} elseif ($edit_certificates) {
|
||||
$member['actions'] = table_buttons([
|
||||
$edit_certificates,
|
||||
]);
|
||||
}
|
||||
$members_confirmed[] = $member;
|
||||
}
|
||||
|
@ -408,7 +437,10 @@ function AngelType_view_table_headers(AngelType $angeltype, $supporter, $admin_a
|
|||
]);
|
||||
}
|
||||
|
||||
if (config('ifsg_enabled') && $angeltype->requires_ifsg_certificate && ($supporter || $admin_angeltypes)) {
|
||||
if (
|
||||
config('ifsg_enabled') && $angeltype->requires_ifsg_certificate
|
||||
&& ($supporter || $admin_angeltypes || auth()->can('user.ifsg.edit'))
|
||||
) {
|
||||
if (config('ifsg_light_enabled')) {
|
||||
$headers['ifsg_certificate_light'] = __('ifsg.certificate_light');
|
||||
}
|
||||
|
|
|
@ -151,7 +151,9 @@ function UserAngelType_add_view(AngelType $angeltype, $users_source, $user_id)
|
|||
msg(),
|
||||
form([
|
||||
form_info(__('Angeltype'), htmlspecialchars($angeltype->name)),
|
||||
form_checkbox('auto_confirm_user', __('Confirm user'), true),
|
||||
$angeltype->restricted
|
||||
? form_checkbox('auto_confirm_user', __('Confirm user'), true)
|
||||
: '',
|
||||
form_select('user_id', __('general.user'), $users, $user_id),
|
||||
form_submit('submit', icon('plus-lg') . __('Add')),
|
||||
]),
|
||||
|
|
|
@ -532,6 +532,7 @@ function User_view_worklog(Worklog $worklog, $admin_user_worklog_privilege)
|
|||
* @param bool $tshirt_admin
|
||||
* @param bool $admin_user_worklog_privilege
|
||||
* @param Worklog[]|Collection $user_worklogs
|
||||
* @param bool $admin_ifsg
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -546,7 +547,8 @@ function User_view(
|
|||
$tshirt_score,
|
||||
$tshirt_admin,
|
||||
$admin_user_worklog_privilege,
|
||||
$user_worklogs
|
||||
$user_worklogs,
|
||||
$admin_ifsg
|
||||
) {
|
||||
$goodie = GoodieType::from(config('goodie_type'));
|
||||
$goodie_enabled = $goodie !== GoodieType::None;
|
||||
|
@ -629,6 +631,10 @@ function User_view(
|
|||
icon('valentine') . __('Vouchers')
|
||||
)
|
||||
: '',
|
||||
$admin_ifsg ? button(
|
||||
url('/users/' . $user_source->id . '/certificates'),
|
||||
icon('card-checklist') . __('settings.certificates')
|
||||
) : '',
|
||||
$admin_user_worklog_privilege ? button(
|
||||
url('/admin/user/' . $user_source->id . '/worklog'),
|
||||
icon('clock-history') . __('worklog.add')
|
||||
|
|
|
@ -368,6 +368,9 @@ msgstr "Du darfst diesen Benutzer nicht von diesem Engeltyp entfernen."
|
|||
msgid "User %s removed from %s."
|
||||
msgstr "Benutzer %s von %s entfernt."
|
||||
|
||||
msgid "Edit certificates"
|
||||
msgstr "Zertifikate bearbeiten"
|
||||
|
||||
msgid "Remove angeltype"
|
||||
msgstr "Engeltyp löschen"
|
||||
|
||||
|
@ -911,7 +914,7 @@ msgstr "Kontakt"
|
|||
msgid "Primary contact person/desk for user questions."
|
||||
msgstr "Ansprechpartner für Fragen."
|
||||
|
||||
msgid "my driving license"
|
||||
msgid "My driving license"
|
||||
msgstr "Meine Führerschein-Infos"
|
||||
|
||||
msgid ""
|
||||
|
@ -1736,11 +1739,28 @@ msgstr "Gabelstapler"
|
|||
msgid "settings.certificates.ifsg_light"
|
||||
msgstr "Ich wurde vor Ort nach IfSG §43 (Frikadellendiplom light) belehrt."
|
||||
|
||||
msgid "settings.certificates.ifsg_light_admin"
|
||||
msgstr "Wurde vor Ort nach IfSG §43 (Frikadellendiplom light) belehrt."
|
||||
|
||||
msgid "settings.certificates.ifsg"
|
||||
msgstr "Ich habe eine Belehrung nach §43 IfSG (Frikadellendiplom) bei meinem Gesundheitsamt "
|
||||
"erhalten und innerhalb von 3 Monaten die Zweitbelehrung durch uns oder meinen Arbeitgeber/Koch/Verein bekommen. "
|
||||
"Zusätzlich ist die Zweitbelehrung nicht älter als zwei Jahre."
|
||||
|
||||
msgid "settings.certificates.ifsg_admin"
|
||||
msgstr "Hat eine Belehrung nach §43 IfSG (Frikadellendiplom) vom Gesundheitsamt "
|
||||
"erhalten und innerhalb von 3 Monaten die Zweitbelehrung durch uns oder einen Arbeitgeber/Koch/Verein bekommen. "
|
||||
"Zusätzlich ist die Zweitbelehrung nicht älter als zwei Jahre."
|
||||
|
||||
msgid "settings.certificates.confirmed"
|
||||
msgstr "Zertifikat bestätigt"
|
||||
|
||||
msgid "settings.certificates.ifsg_confirmed.hint"
|
||||
msgstr "Deine Gesundheitsbelehrung wurde bestätigt, du kannst deine Angaben nicht mehr selber ändern."
|
||||
|
||||
msgid "settings.certificates.confirmation.info"
|
||||
msgstr "Du hast persönlich überprüft, dass die Zertifizierung / Bescheinigung den Anforderungen genügt."
|
||||
|
||||
msgid "settings.certificates.success"
|
||||
msgstr "Zertifikate wurden erfolgreich aktualisiert."
|
||||
|
||||
|
|
|
@ -437,11 +437,28 @@ msgstr "Forklift"
|
|||
msgid "settings.certificates.ifsg_light"
|
||||
msgstr "I was instructed about IfSG §43 (aka Frikadellendiplom light) on site."
|
||||
|
||||
msgid "settings.certificates.ifsg_light_admin"
|
||||
msgstr "Was instructed about IfSG §43 (aka Frikadellendiplom light) on site."
|
||||
|
||||
msgid "settings.certificates.ifsg"
|
||||
msgstr "I have gotten the instruction about §43 IfSG (aka Frikadellendiplom) from my Health Department "
|
||||
"and a second instruction from us or my employer/chef/assosiation within 3 months. "
|
||||
"and a second instruction from us or my employer/chef/association within 3 months. "
|
||||
"Additionally my second instruction is not older than 2 years."
|
||||
|
||||
msgid "settings.certificates.ifsg_admin"
|
||||
msgstr "Got the instruction about §43 IfSG (aka Frikadellendiplom) from a Health Department "
|
||||
"and a second instruction from us or his employer/chef/association within 3 months. "
|
||||
"Additionally the second instruction is not older than 2 years."
|
||||
|
||||
msgid "settings.certificates.confirmed"
|
||||
msgstr "Certificate confirmed"
|
||||
|
||||
msgid "settings.certificates.ifsg_confirmed.hint"
|
||||
msgstr "Your health instruction has been confirmed, you can no longer change it by yourself."
|
||||
|
||||
msgid "settings.certificates.confirmation.info"
|
||||
msgstr "You personally checked that the certificate / license meets the requirements."
|
||||
|
||||
msgid "settings.certificates.success"
|
||||
msgstr "Certificates were updated successfully."
|
||||
|
||||
|
@ -449,13 +466,13 @@ msgid "angeltype.ifsg.required"
|
|||
msgstr "Requires health instruction"
|
||||
|
||||
msgid "ifsg.certificate"
|
||||
msgstr "health instruction"
|
||||
msgstr "Health instruction"
|
||||
|
||||
msgid "ifsg.certificate_light"
|
||||
msgstr "health instruction on site"
|
||||
msgstr "Health instruction on site"
|
||||
|
||||
msgid "angeltype.ifsg.own"
|
||||
msgstr "my health instruction"
|
||||
msgstr "My health instruction"
|
||||
|
||||
msgid "angeltype.ifsg.required.info"
|
||||
msgstr "This angeltype requires a health instruction. Please enter your health instruction information!"
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
{% extends 'pages/settings/certificates.twig' %}
|
||||
{% import 'macros/form.twig' as f %}
|
||||
{% import 'macros/base.twig' as m %}
|
||||
|
||||
{% block row_content %}
|
||||
<div class="row">
|
||||
|
||||
{% if config('ifsg_enabled') %}
|
||||
<form
|
||||
action="{{ url('/users/' ~ admin_user.id ~ '/certificates/ifsg') }}"
|
||||
enctype="multipart/form-data" method="post"
|
||||
>
|
||||
{{ csrf() }}
|
||||
<div class="col-md-12 pb-3">
|
||||
<h3>{{ __('settings.certificates.title.ifsg') }}</h3>
|
||||
|
||||
{% if config('ifsg_light_enabled') %}
|
||||
{{ f.checkbox('ifsg_certificate_light', __('settings.certificates.ifsg_light_admin'), {
|
||||
'checked': certificates.ifsg_certificate_light,
|
||||
}) }}
|
||||
{% endif %}
|
||||
{{ f.checkbox('ifsg_certificate', __('settings.certificates.ifsg_admin'), {
|
||||
'checked': certificates.ifsg_certificate,
|
||||
}) }}
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
{{ f.submit(__('form.save'), {'icon_left': 'save'}) }}
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
{{ f.checkbox(
|
||||
'ifsg_confirmed',
|
||||
__('settings.certificates.confirmed') ~ f.info(__('settings.certificates.confirmation.info')),
|
||||
{'raw_label': true, 'checked': certificates.ifsg_confirmed}
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -7,20 +7,33 @@
|
|||
{% block row_content %}
|
||||
<div class="row">
|
||||
{% if config('ifsg_enabled') %}
|
||||
<form action="{{ url('/settings/certificates/ifsg') }}" enctype="multipart/form-data" method="post">
|
||||
<form
|
||||
action="{{ url('/settings/certificates/ifsg') }}"
|
||||
enctype="multipart/form-data" method="post"
|
||||
>
|
||||
{{ csrf() }}
|
||||
<div class="col-md-12 pb-3">
|
||||
<h3>{{ __('settings.certificates.title.ifsg') }}</h3>
|
||||
{{ m.info(__('settings.certificates.info')) }}
|
||||
{% if certificates.ifsg_confirmed %}
|
||||
<p class="text-success">{{ __('settings.certificates.ifsg_confirmed.hint') }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if config('ifsg_light_enabled') %}
|
||||
{{ f.checkbox('ifsg_certificate_light', __('settings.certificates.ifsg_light'), {
|
||||
'checked': certificates.ifsg_certificate_light,
|
||||
'disabled': certificates.ifsg_confirmed,
|
||||
}) }}
|
||||
{% endif %}
|
||||
|
||||
{{ f.checkbox('ifsg_certificate', __('settings.certificates.ifsg'), {
|
||||
'checked': certificates.ifsg_certificate,
|
||||
'disabled': certificates.ifsg_confirmed,
|
||||
}) }}
|
||||
|
||||
{% if not certificates.ifsg_confirmed %}
|
||||
{{ f.submit(__('form.save'), {'icon_left': 'save'}) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
|
|
@ -8,7 +8,12 @@
|
|||
{% block container_title %}
|
||||
<h1 id="settings-title">
|
||||
{{ __('settings.settings') }}
|
||||
<small class="text-muted">{{ block('title') }}</small>
|
||||
<small class="text-muted">
|
||||
{{ block('title') }}
|
||||
{% if is_admin|default(false) %}
|
||||
({{ admin_user.name }})
|
||||
{% endif %}
|
||||
</small>
|
||||
</h1>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -16,12 +21,14 @@
|
|||
<div class="col-md-3 settings-menu">
|
||||
<ul class="nav nav-pills flex-column mt-3 user-settings">
|
||||
{% for url,title in settings_menu %}
|
||||
<li class="nav-item{% if title.hidden ?? false and url != request.url() %} d-none{% endif %}">
|
||||
{% if not title.permission|default(false) or has_permission_to(title.permission) %}
|
||||
<li class="nav-item{% if title.hidden|default(false) and url != request.url() %} d-none{% endif %}">
|
||||
<a class="nav-link {% if url == request.url() %}active{% endif %}" href="{{ url }}">
|
||||
{{ m.icon(title.icon ?? 'gear-fill') }}
|
||||
{{ __(title.title ?? title) }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Controllers\Admin;
|
||||
|
||||
use Engelsystem\Config\Config;
|
||||
use Engelsystem\Controllers\BaseController;
|
||||
use Engelsystem\Controllers\HasUserNotifications;
|
||||
use Engelsystem\Http\Exceptions\HttpForbidden;
|
||||
use Engelsystem\Http\Exceptions\HttpNotFound;
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Http\Redirector;
|
||||
use Engelsystem\Http\Request;
|
||||
use Engelsystem\Helpers\Authenticator;
|
||||
use Engelsystem\Models\AngelType;
|
||||
use Engelsystem\Models\User\User;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class UserSettingsController extends BaseController
|
||||
{
|
||||
use HasUserNotifications;
|
||||
|
||||
public function __construct(
|
||||
protected Authenticator $auth,
|
||||
protected Config $config,
|
||||
protected LoggerInterface $log,
|
||||
protected Redirector $redirect,
|
||||
protected Response $response
|
||||
) {
|
||||
}
|
||||
|
||||
public function certificate(Request $request): Response
|
||||
{
|
||||
if (!config('ifsg_enabled')) {
|
||||
throw new HttpNotFound();
|
||||
}
|
||||
|
||||
$this->checkPermission('user.ifsg.edit', $this->isIfsgSupporter());
|
||||
$user = $this->getUser($request);
|
||||
|
||||
return $this->view(
|
||||
$user,
|
||||
'pages/settings/certificates-admin',
|
||||
[
|
||||
'certificates' => $user->license,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function saveIfsgCertificate(Request $request): Response
|
||||
{
|
||||
if (!config('ifsg_enabled')) {
|
||||
throw new HttpNotFound();
|
||||
}
|
||||
|
||||
$this->checkPermission('user.ifsg.edit', $this->isIfsgSupporter());
|
||||
$user = $this->getUser($request);
|
||||
|
||||
$data = $this->validate($request, [
|
||||
'ifsg_certificate_light' => 'optional|checked',
|
||||
'ifsg_certificate' => 'optional|checked',
|
||||
'ifsg_confirmed' => 'optional|checked',
|
||||
]);
|
||||
|
||||
if (config('ifsg_light_enabled')) {
|
||||
$user->license->ifsg_certificate_light = !$data['ifsg_certificate'] && $data['ifsg_certificate_light'];
|
||||
}
|
||||
$user->license->ifsg_certificate = (bool) $data['ifsg_certificate'];
|
||||
$user->license->ifsg_confirmed = $data['ifsg_confirmed']
|
||||
&& ($user->license->ifsg_certificate || $user->license->ifsg_certificate_light);
|
||||
|
||||
$user->license->save();
|
||||
$this->addNotification('settings.certificates.success');
|
||||
$this->log->info('Certificate "{certificate}" of user {user} ({id}) is {confirmation}.', [
|
||||
'certificate' => $user->license->ifsg_certificate_light
|
||||
? 'IfSG light'
|
||||
: ($user->license->ifsg_certificate
|
||||
? 'IfSG'
|
||||
: 'no IfSG'
|
||||
),
|
||||
'user' => $user->name,
|
||||
'id' => $user->id,
|
||||
'confirmation' => $user->license->ifsg_confirmed ? 'confirmed' : 'unconfirmed',
|
||||
]);
|
||||
|
||||
return $this->redirect->to('/users/' . $user->id . '/certificates');
|
||||
}
|
||||
|
||||
public function settingsMenu(User $user): array
|
||||
{
|
||||
$menu = [
|
||||
url('/users', ['action' => 'view', 'user_id' => $user->id]) => [
|
||||
'title' => 'general.back', 'icon' => 'chevron-left',
|
||||
],
|
||||
];
|
||||
|
||||
if (config('ifsg_enabled')) {
|
||||
$menu[url('/users/' . $user->id . '/certificates')] = [
|
||||
'title' => 'settings.certificates',
|
||||
'icon' => 'card-checklist',
|
||||
'permission' => $this->isIfsgSupporter() ? null : 'user.ifsg.edit',
|
||||
];
|
||||
}
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
protected function checkPermission(string | array $abilities, bool $overwrite = false): void
|
||||
{
|
||||
if (!$overwrite && !$this->auth->can($abilities)) {
|
||||
throw new HttpForbidden();
|
||||
}
|
||||
}
|
||||
|
||||
protected function view(User $user, string $view, array $data = []): Response
|
||||
{
|
||||
return $this->response->withView(
|
||||
$view,
|
||||
array_merge([
|
||||
'settings_menu' => $this->settingsMenu($user),
|
||||
'is_admin' => true,
|
||||
'admin_user' => $user,
|
||||
], $data)
|
||||
);
|
||||
}
|
||||
|
||||
protected function getUser(Request $request): User
|
||||
{
|
||||
$userId = $request->getAttribute('user_id');
|
||||
return User::findOrFail($userId);
|
||||
}
|
||||
|
||||
public function isIfsgSupporter(): bool
|
||||
{
|
||||
return (bool) AngelType::whereRequiresIfsgCertificate(true)
|
||||
->leftJoin('user_angel_type', 'user_angel_type.angel_type_id', 'angel_types.id')
|
||||
->where('user_angel_type.user_id', $this->auth->user()?->id)
|
||||
->where('user_angel_type.supporter', true)
|
||||
->count();
|
||||
}
|
||||
}
|
|
@ -242,12 +242,11 @@ class SettingsController extends BaseController
|
|||
|
||||
public function certificate(): Response
|
||||
{
|
||||
$user = $this->auth->user();
|
||||
|
||||
if (!config('ifsg_enabled') && !$this->checkDrivingLicense()) {
|
||||
throw new HttpNotFound();
|
||||
}
|
||||
|
||||
$user = $this->auth->user();
|
||||
return $this->response->withView(
|
||||
'pages/settings/certificates',
|
||||
[
|
||||
|
@ -260,11 +259,11 @@ class SettingsController extends BaseController
|
|||
|
||||
public function saveIfsgCertificate(Request $request): Response
|
||||
{
|
||||
if (!config('ifsg_enabled')) {
|
||||
$user = $this->auth->user();
|
||||
if (!config('ifsg_enabled') || $user->license->ifsg_confirmed) {
|
||||
throw new HttpNotFound();
|
||||
}
|
||||
|
||||
$user = $this->auth->user();
|
||||
$data = $this->validate($request, [
|
||||
'ifsg_certificate_light' => 'optional|checked',
|
||||
'ifsg_certificate' => 'optional|checked',
|
||||
|
@ -274,8 +273,8 @@ class SettingsController extends BaseController
|
|||
$user->license->ifsg_certificate_light = !$data['ifsg_certificate'] && $data['ifsg_certificate_light'];
|
||||
}
|
||||
$user->license->ifsg_certificate = (bool) $data['ifsg_certificate'];
|
||||
$user->license->save();
|
||||
|
||||
$user->license->save();
|
||||
$this->addNotification('settings.certificates.success');
|
||||
|
||||
return $this->redirect->to('/settings/certificates');
|
||||
|
|
|
@ -42,6 +42,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
|
|||
* @method static QueryBuilder|AngelType[] whereContactEmail($value)
|
||||
* @method static QueryBuilder|AngelType[] whereRestricted($value)
|
||||
* @method static QueryBuilder|AngelType[] whereRequiresDriverLicense($value)
|
||||
* @method static QueryBuilder|AngelType[] whereRequiresIfsgCertificate($value)
|
||||
* @method static QueryBuilder|AngelType[] whereNoSelfSignup($value)
|
||||
* @method static QueryBuilder|AngelType[] whereShowOnDashboard($value)
|
||||
* @method static QueryBuilder|AngelType[] whereHideRegister($value)
|
||||
|
|
|
@ -16,6 +16,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
|
|||
* @property bool $drive_12t
|
||||
* @property bool $ifsg_certificate_light
|
||||
* @property bool $ifsg_certificate
|
||||
* @property bool $ifsg_confirmed
|
||||
*
|
||||
* @method static QueryBuilder|License[] whereHasCar($value)
|
||||
* @method static QueryBuilder|License[] whereDriveForklift($value)
|
||||
|
@ -25,6 +26,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
|
|||
* @method static QueryBuilder|License[] whereDrive12T($value)
|
||||
* @method static QueryBuilder|License[] whereIfsgCertificateLight($value)
|
||||
* @method static QueryBuilder|License[] whereIfsgCertificate($value)
|
||||
* @method static QueryBuilder|License[] whereIfsgConfirmed($value)
|
||||
*/
|
||||
class License extends HasUserModel
|
||||
{
|
||||
|
@ -43,6 +45,7 @@ class License extends HasUserModel
|
|||
'drive_12t' => false,
|
||||
'ifsg_certificate_light' => false,
|
||||
'ifsg_certificate' => false,
|
||||
'ifsg_confirmed' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -60,6 +63,7 @@ class License extends HasUserModel
|
|||
'drive_12t',
|
||||
'ifsg_certificate_light',
|
||||
'ifsg_certificate',
|
||||
'ifsg_confirmed',
|
||||
];
|
||||
|
||||
/** @var array<string> */
|
||||
|
@ -72,6 +76,7 @@ class License extends HasUserModel
|
|||
'drive_12t' => 'boolean',
|
||||
'ifsg_certificate_light' => 'boolean',
|
||||
'ifsg_certificate' => 'boolean',
|
||||
'ifsg_confirmed' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Test\Unit\Controllers\Admin;
|
||||
|
||||
use Engelsystem\Controllers\Admin\UserSettingsController;
|
||||
use Engelsystem\Helpers\Authenticator;
|
||||
use Engelsystem\Http\Exceptions\HttpForbidden;
|
||||
use Engelsystem\Http\Exceptions\HttpNotFound;
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Http\UrlGenerator;
|
||||
use Engelsystem\Http\Validation\Validator;
|
||||
use Engelsystem\Models\AngelType;
|
||||
use Engelsystem\Models\User\License;
|
||||
use Engelsystem\Models\User\User;
|
||||
use Engelsystem\Test\Unit\Controllers\ControllerTest;
|
||||
use Engelsystem\Test\Unit\HasDatabase;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
class UserSettingsControllerTest extends ControllerTest
|
||||
{
|
||||
use HasDatabase;
|
||||
|
||||
protected Authenticator | MockObject $auth;
|
||||
|
||||
protected User $user;
|
||||
|
||||
protected User $userChanged;
|
||||
|
||||
protected UserSettingsController $controller;
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::certificate
|
||||
*/
|
||||
public function testCertificateDisabled(): void
|
||||
{
|
||||
config(['ifsg_enabled' => false]);
|
||||
|
||||
$this->expectException(HttpNotFound::class);
|
||||
$this->controller->certificate($this->request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::checkPermission
|
||||
*/
|
||||
public function testCertificateNotAllowed(): void
|
||||
{
|
||||
config(['ifsg_enabled' => true]);
|
||||
|
||||
$this->expectException(HttpForbidden::class);
|
||||
$this->controller->certificate($this->request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::__construct
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::certificate
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::checkPermission
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::getUser
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::view
|
||||
*/
|
||||
public function testCertificateByPermission(): void
|
||||
{
|
||||
config(['ifsg_enabled' => true]);
|
||||
$this->setExpects($this->auth, 'can', ['user.ifsg.edit'], true, $this->atLeastOnce());
|
||||
|
||||
$this->response->expects($this->once())
|
||||
->method('withView')
|
||||
->willReturnCallback(function (string $view, array $data): Response {
|
||||
$this->assertArrayHasKey('certificates', $data);
|
||||
$this->assertArrayHasKey('settings_menu', $data);
|
||||
$this->assertArrayHasKey('is_admin', $data);
|
||||
$this->assertTrue($data['is_admin']);
|
||||
$this->assertArrayHasKey('admin_user', $data);
|
||||
$this->assertEquals($this->userChanged->id, $data['admin_user']->id);
|
||||
return $this->response;
|
||||
});
|
||||
|
||||
$this->controller->certificate($this->request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::certificate
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::checkPermission
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::isIfsgSupporter
|
||||
*/
|
||||
public function testCertificateByAngelTypeSupporter(): void
|
||||
{
|
||||
config(['ifsg_enabled' => true]);
|
||||
$this->setExpects($this->response, 'withView', null, $this->response);
|
||||
|
||||
$angelType = AngelType::factory()->create(['requires_ifsg_certificate' => true]);
|
||||
$this->user->userAngelTypes()->attach($angelType, ['supporter' => true]);
|
||||
|
||||
$this->controller->certificate($this->request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::saveIfsgCertificate
|
||||
*/
|
||||
public function testSaveIfsgCertificateDisabled(): void
|
||||
{
|
||||
config(['ifsg_enabled' => false]);
|
||||
|
||||
$this->expectException(HttpNotFound::class);
|
||||
$this->controller->saveIfsgCertificate($this->request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::saveIfsgCertificate
|
||||
*/
|
||||
public function testSaveIfsgCertificateNotAllowed(): void
|
||||
{
|
||||
config(['ifsg_enabled' => true]);
|
||||
|
||||
$this->expectException(HttpForbidden::class);
|
||||
$this->controller->saveIfsgCertificate($this->request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::saveIfsgCertificate
|
||||
*/
|
||||
public function testSaveIfsgCertificateConfirmed(): void
|
||||
{
|
||||
config(['ifsg_enabled' => true]);
|
||||
$this->setExpects($this->auth, 'can', ['user.ifsg.edit'], true, $this->atLeastOnce());
|
||||
|
||||
$body = [
|
||||
'ifsg_certificate' => true,
|
||||
'ifsg_confirmed' => true,
|
||||
];
|
||||
$this->request = $this->request->withParsedBody($body);
|
||||
|
||||
$this->response->expects($this->once())
|
||||
->method('redirectTo')
|
||||
->with('http://localhost/users/' . $this->userChanged->id . '/certificates')
|
||||
->willReturn($this->response);
|
||||
|
||||
$this->controller->saveIfsgCertificate($this->request);
|
||||
$this->assertTrue($this->log->hasInfoThatContains('Certificate'));
|
||||
|
||||
$this->assertFalse($this->userChanged->license->ifsg_certificate_light);
|
||||
$this->assertTrue($this->userChanged->license->ifsg_certificate);
|
||||
$this->assertTrue($this->userChanged->license->ifsg_confirmed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::saveIfsgCertificate
|
||||
*/
|
||||
public function testSaveIfsgCertificate(): void
|
||||
{
|
||||
config(['ifsg_enabled' => true]);
|
||||
$this->setExpects($this->auth, 'can', ['user.ifsg.edit'], true, $this->atLeastOnce());
|
||||
|
||||
$body = [
|
||||
'ifsg_certificate' => true,
|
||||
];
|
||||
$this->request = $this->request->withParsedBody($body);
|
||||
|
||||
$this->response->expects($this->once())
|
||||
->method('redirectTo')
|
||||
->with('http://localhost/users/' . $this->userChanged->id . '/certificates')
|
||||
->willReturn($this->response);
|
||||
|
||||
$this->controller->saveIfsgCertificate($this->request);
|
||||
|
||||
$this->assertFalse($this->userChanged->license->ifsg_certificate_light);
|
||||
$this->assertTrue($this->userChanged->license->ifsg_certificate);
|
||||
$this->assertFalse($this->userChanged->license->ifsg_confirmed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::saveIfsgCertificate
|
||||
*/
|
||||
public function testSaveIfsgCertificateLite(): void
|
||||
{
|
||||
config(['ifsg_enabled' => true, 'ifsg_light_enabled' => true]);
|
||||
$this->setExpects($this->auth, 'can', ['user.ifsg.edit'], true, $this->atLeastOnce());
|
||||
|
||||
$body = [
|
||||
'ifsg_certificate_light' => true,
|
||||
];
|
||||
$this->request = $this->request->withParsedBody($body);
|
||||
|
||||
$this->response->expects($this->once())
|
||||
->method('redirectTo')
|
||||
->with('http://localhost/users/' . $this->userChanged->id . '/certificates')
|
||||
->willReturn($this->response);
|
||||
|
||||
$this->controller->saveIfsgCertificate($this->request);
|
||||
|
||||
$this->assertTrue($this->userChanged->license->ifsg_certificate_light);
|
||||
$this->assertFalse($this->userChanged->license->ifsg_certificate);
|
||||
$this->assertFalse($this->userChanged->license->ifsg_confirmed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Admin\UserSettingsController::settingsMenu
|
||||
*/
|
||||
public function testSettingsMenu(): void
|
||||
{
|
||||
$menu = $this->controller->settingsMenu($this->userChanged);
|
||||
$this->assertArrayHasKey('http://localhost/users?action=view&user_id=' . $this->userChanged->id, $menu);
|
||||
|
||||
config(['ifsg_enabled' => true]);
|
||||
$menu = $this->controller->settingsMenu($this->userChanged);
|
||||
$this->assertArrayHasKey('http://localhost/users/' . $this->userChanged->id . '/certificates', $menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup environment
|
||||
*/
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->app->bind('http.urlGenerator', UrlGenerator::class);
|
||||
|
||||
$this->user = User::factory()->create();
|
||||
|
||||
$this->userChanged = User::factory()
|
||||
->has(License::factory())
|
||||
->create();
|
||||
|
||||
$this->auth = $this->createMock(Authenticator::class);
|
||||
$this->app->instance(Authenticator::class, $this->auth);
|
||||
|
||||
$this->setExpects($this->auth, 'user', null, $this->user, $this->any());
|
||||
|
||||
$this->request = $this->request->withAttribute('user_id', $this->userChanged->id);
|
||||
|
||||
$this->controller = $this->app->make(UserSettingsController::class);
|
||||
$this->controller->setValidator(new Validator());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue