Added UserAngelType model

This commit is contained in:
Igor Scheller 2022-12-03 00:57:04 +01:00 committed by Michael Weimann
parent 99e7a088b0
commit 7f78f59840
27 changed files with 686 additions and 533 deletions

View File

@ -0,0 +1,27 @@
<?php
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserAngelTypeFactory extends Factory
{
/** @var string */
protected $model = UserAngelType::class;
/**
* @return array
*/
public function definition(): array
{
return [
'user_id' => User::factory(),
'angel_type_id' => AngelType::factory(),
'confirm_user_id' => $this->faker->optional()->passthrough(User::factory()),
'supporter' => $this->faker->boolean(),
];
}
}

View File

@ -0,0 +1,101 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateUserAngelTypesTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('user_angel_type', function (Blueprint $table) {
$table->increments('id');
$this->referencesUser($table);
$this->references($table, 'angel_types')->index();
$this->references($table, 'users', 'confirm_user_id')->nullable()->default(null)->index();
$table->boolean('supporter')->default(false)->index();
$table->index(['user_id', 'angel_type_id', 'confirm_user_id']);
$table->unique(['user_id', 'angel_type_id']);
});
if (!$this->schema->hasTable('UserAngelTypes')) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('UserAngelTypes')
->get();
foreach ($records as $record) {
$connection->table('user_angel_type')->insert([
'id' => $record->id,
'user_id' => $record->user_id,
'angel_type_id' => $record->angeltype_id,
'confirm_user_id' => $record->confirm_user_id ?: null,
'supporter' => (bool)$record->supporter,
]);
}
$this->changeReferences(
'UserAngelTypes',
'id',
'user_angel_type',
'id'
);
$this->schema->drop('UserAngelTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('UserAngelTypes', function (Blueprint $table) {
$table->increments('id');
$this->referencesUser($table);
$this->references($table, 'angel_types', 'angeltype_id')->index('angeltype_id');
$this->references($table, 'users', 'confirm_user_id')->nullable()->index('confirm_user_id');
$table->boolean('supporter')->nullable()->index('coordinator');
$table->index(['user_id', 'angeltype_id', 'confirm_user_id'], 'user_id');
});
/** @var stdClass[] $records */
$records = $connection
->table('user_angel_type')
->get();
foreach ($records as $record) {
$connection->table('UserAngelTypes')->insert([
'id' => $record->id,
'user_id' => $record->user_id,
'angeltype_id' => $record->angel_type_id,
'confirm_user_id' => $record->confirm_user_id ?: null,
'supporter' => (bool)$record->supporter,
]);
}
$this->changeReferences(
'user_angel_type',
'id',
'UserAngelTypes',
'id',
'integer'
);
$this->schema->drop('user_angel_type');
}
}

View File

@ -1,6 +1,7 @@
<?php
use Engelsystem\Models\AngelType;
use Engelsystem\Models\UserAngelType;
use Engelsystem\ShiftsFilter;
use Engelsystem\ShiftsFilterRenderer;
use Engelsystem\ValidationResult;
@ -116,7 +117,7 @@ function angeltype_edit_controller()
// Edit existing angeltype
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
if (!User_is_AngelType_supporter(auth()->user(), $angeltype)) {
if (!auth()->user()->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
throw_redirect(page_link_to('angeltypes'));
}
} else {
@ -193,8 +194,9 @@ function angeltype_controller()
}
$angeltype = AngelType::findOrFail(request()->input('angeltype_id'));
$user_angeltype = UserAngelType_by_User_and_AngelType($user->id, $angeltype);
$members = Users_by_angeltype($angeltype);
/** @var UserAngelType $user_angeltype */
$user_angeltype = UserAngelType::whereUserId($user->id)->where('angel_type_id', $angeltype->id)->first();
$members = $angeltype->userAngelTypes->sortBy('name');
$days = angeltype_controller_shiftsFilterDays($angeltype);
$shiftsFilter = angeltype_controller_shiftsFilter($angeltype, $days);
@ -210,7 +212,7 @@ function angeltype_controller()
$tab = 1;
}
$isSupporter = !is_null($user_angeltype) && $user_angeltype['supporter'];
$isSupporter = !is_null($user_angeltype) && $user_angeltype->supporter;
return [
sprintf(__('Team %s'), $angeltype->name),
AngelType_view(
@ -291,7 +293,6 @@ function angeltypes_list_controller()
}
$angeltypes = AngelTypes_with_user($user->id);
foreach ($angeltypes as $angeltype) {
$actions = [
button(
@ -315,11 +316,11 @@ function angeltypes_list_controller()
}
$angeltype->membership = AngelType_render_membership($angeltype);
if (!empty($angeltype->user_angeltype_id)) {
if (!empty($angeltype->user_angel_type_id)) {
$actions[] = button(
page_link_to(
'user_angeltypes',
['action' => 'delete', 'user_angeltype_id' => $angeltype->user_angeltype_id]
['action' => 'delete', 'user_angeltype_id' => $angeltype->user_angel_type_id]
),
icon('box-arrow-right') . __('leave'),
'btn-sm'
@ -387,13 +388,13 @@ function AngelTypes_with_user($userId): Collection
return AngelType::query()
->select([
'angel_types.*',
'UserAngelTypes.id AS user_angeltype_id',
'UserAngelTypes.confirm_user_id',
'UserAngelTypes.supporter',
'user_angel_type.id AS user_angel_type_id',
'user_angel_type.confirm_user_id',
'user_angel_type.supporter',
])
->leftJoin('UserAngelTypes', function (JoinClause $join) use ($userId) {
$join->on('angel_types.id', 'UserAngelTypes.angeltype_id');
$join->where('UserAngelTypes.user_id', $userId);
->leftJoin('user_angel_type', function (JoinClause $join) use ($userId) {
$join->on('angel_types.id', 'user_angel_type.angel_type_id');
$join->where('user_angel_type.user_id', $userId);
})
->get();
}

View File

@ -3,6 +3,7 @@
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Engelsystem\ShiftSignupState;
use Illuminate\Database\Eloquent\Collection;
@ -62,7 +63,7 @@ function shift_entry_create_controller(): array
throw_redirect(user_link($user->id));
}
if (User_is_AngelType_supporter($user, $angeltype)) {
if ($user->isAngelTypeSupporter($angeltype) || auth()->can('admin_user_angeltypes')) {
return shift_entry_create_controller_supporter($shift, $angeltype);
}
@ -145,7 +146,8 @@ function shift_entry_create_controller_supporter($shift, AngelType $angeltype):
if ($request->has('user_id')) {
$signup_user = User::find($request->input('user_id'));
}
if (!UserAngelType_exists($signup_user->id, $angeltype)) {
if (!$signup_user->userAngelTypes()->wherePivot('angel_type_id', $angeltype->id)->exists()) {
error(__('User is not in angeltype.'));
throw_redirect(shift_link($shift));
}
@ -164,7 +166,7 @@ function shift_entry_create_controller_supporter($shift, AngelType $angeltype):
throw_redirect(shift_link($shift));
}
$users = Users_by_angeltype($angeltype);
$users = $angeltype->userAngelTypes->sortBy('name');
$users_select = [];
foreach ($users as $u) {
$users_select[$u->id] = $u->name;
@ -242,8 +244,14 @@ function shift_entry_create_controller_user($shift, AngelType $angeltype): array
'freeload_comment' => ''
]);
if (!$angeltype->restricted && !UserAngelType_exists($signup_user->id, $angeltype)) {
UserAngelType_create($signup_user->id, $angeltype);
if (
!$angeltype->restricted
&& !$angeltype->userAngelTypes()->wherePivot('user_id', $signup_user->id)->exists()
) {
$userAngelType = new UserAngelType();
$userAngelType->user()->associate($signup_user);
$userAngelType->angelType()->associate($angeltype);
$userAngelType->save();
}
success(__('You are subscribed. Thank you!'));

View File

@ -3,6 +3,8 @@
use Engelsystem\Mail\EngelsystemMailer;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Illuminate\Database\Eloquent\Collection;
use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\Exception\TransportException;
@ -13,21 +15,36 @@ use Symfony\Component\Mailer\Exception\TransportException;
*/
function user_angeltypes_unconfirmed_hint()
{
$unconfirmed_user_angeltypes = User_unconfirmed_AngelTypes(auth()->user()->id);
if (count($unconfirmed_user_angeltypes) == 0) {
$restrictedSupportedAngelTypes = auth()
->user()
->userAngelTypes()
->wherePivot('supporter', true)
->where('restricted', true)
->get();
/** @var Collection|UserAngelType[] $unconfirmed_user_angeltypes */
$unconfirmed_user_angeltypes = UserAngelType::query()
->with('AngelType')
->select(['user_angel_type.*', UserAngelType::query()->raw('count(angel_type_id) as users_count')])
->whereIn('angel_type_id', $restrictedSupportedAngelTypes->pluck('id')->toArray())
->whereNull('confirm_user_id')
->groupBy('angel_type_id')
->get();
if (!$unconfirmed_user_angeltypes->count()) {
return null;
}
$unconfirmed_links = [];
foreach ($unconfirmed_user_angeltypes as $user_angeltype) {
$unconfirmed_links[] = '<a class="text-info" href="'
. page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $user_angeltype['angeltype_id']])
. '">' . $user_angeltype['name']
. ' (+' . $user_angeltype['count'] . ')'
. page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $user_angeltype->angel_type_id])
. '">' . $user_angeltype->angelType->name
. ' (+' . $user_angeltype->count . ')'
. '</a>';
}
$count = count($unconfirmed_user_angeltypes);
$count = $unconfirmed_user_angeltypes->count();
return
_e(
'There is %d unconfirmed angeltype.',
@ -53,19 +70,16 @@ function user_angeltypes_delete_all_controller(): array
throw_redirect(page_link_to('angeltypes'));
}
$angeltype = AngelType::find($request->input('angeltype_id'));
if (empty($angeltype)) {
error(__('Angeltype doesn\'t exist.'));
throw_redirect(page_link_to('angeltypes'));
}
if (!User_is_AngelType_supporter(auth()->user(), $angeltype)) {
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
if (!auth()->user()->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
error(__('You are not allowed to delete all users for this angeltype.'));
throw_redirect(page_link_to('angeltypes'));
}
if ($request->hasPostData('deny_all')) {
UserAngelTypes_delete_all_unconfirmed($angeltype->id);
UserAngelType::whereAngelTypeId($angeltype->id)
->whereNull('confirm_user_id')
->delete();
engelsystem_log(sprintf('Denied all users for angeltype %s', AngelType_name_render($angeltype, true)));
success(sprintf(__('Denied all users for angeltype %s.'), AngelType_name_render($angeltype)));
@ -94,20 +108,22 @@ function user_angeltypes_confirm_all_controller(): array
}
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
if (!auth()->can('admin_user_angeltypes') && !User_is_AngelType_supporter($user, $angeltype)) {
if (!auth()->can('admin_user_angeltypes') && !$user->isAngelTypeSupporter($angeltype)) {
error(__('You are not allowed to confirm all users for this angeltype.'));
throw_redirect(page_link_to('angeltypes'));
}
if ($request->hasPostData('confirm_all')) {
$users = UserAngelTypes_all_unconfirmed($angeltype->id);
UserAngelTypes_confirm_all($angeltype->id, $user->id);
/** @var Collection|User[] $users */
$users = $angeltype->userAngelTypes()->wherePivot('confirm_user_id', '=', null)->get();
UserAngelType::whereAngelTypeId($angeltype->id)
->whereNull('confirm_user_id')
->update(['confirm_user_id' => $user->id]);
engelsystem_log(sprintf('Confirmed all users for angeltype %s', AngelType_name_render($angeltype, true)));
success(sprintf(__('Confirmed all users for angeltype %s.'), AngelType_name_render($angeltype)));
foreach ($users as $user) {
$user = User::find($user['user_id']);
user_angeltype_confirm_email($user, $angeltype);
}
@ -135,26 +151,18 @@ function user_angeltype_confirm_controller(): array
throw_redirect(page_link_to('angeltypes'));
}
$user_angeltype = UserAngelType($request->input('user_angeltype_id'));
if (empty($user_angeltype)) {
error(__('User angeltype doesn\'t exist.'));
throw_redirect(page_link_to('angeltypes'));
}
$angeltype = AngelType::findOrFail($user_angeltype['angeltype_id']);
if (!User_is_AngelType_supporter($user, $angeltype)) {
/** @var UserAngelType $user_angeltype */
$user_angeltype = UserAngelType::findOrFail($request->input('user_angeltype_id'));
$angeltype = $user_angeltype->angelType;
if (!$user->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
error(__('You are not allowed to confirm this users angeltype.'));
throw_redirect(page_link_to('angeltypes'));
}
$user_source = User::find($user_angeltype['user_id']);
if (!$user_source) {
error(__('User doesn\'t exist.'));
throw_redirect(page_link_to('angeltypes'));
}
$user_source = $user_angeltype->user;
if ($request->hasPostData('confirm_user')) {
UserAngelType_confirm($user_angeltype['id'], $user->id);
$user_angeltype->confirmUser()->associate($user);
$user_angeltype->save();
engelsystem_log(sprintf(
'%s confirmed for angeltype %s',
@ -253,21 +261,21 @@ function user_angeltype_delete_controller(): array
throw_redirect(page_link_to('angeltypes'));
}
$user_angeltype = UserAngelType($request->input('user_angeltype_id'));
if (empty($user_angeltype)) {
error(__('User angeltype doesn\'t exist.'));
throw_redirect(page_link_to('angeltypes'));
}
$angeltype = AngelType::findOrFail($user_angeltype['angeltype_id']);
$user_source = User::findOrFail($user_angeltype['user_id']);
if ($user->id != $user_angeltype['user_id'] && !User_is_AngelType_supporter($user, $angeltype)) {
/** @var UserAngelType $user_angeltype */
$user_angeltype = UserAngelType::findOrFail($request->input('user_angeltype_id'));
$angeltype = $user_angeltype->angelType;
$user_source = $user_angeltype->user;
if (
$user->id != $user_angeltype->user_id
&& !$user->isAngelTypeSupporter($angeltype)
&& !auth()->can('admin_user_angeltypes')
) {
error(__('You are not allowed to delete this users angeltype.'));
throw_redirect(page_link_to('angeltypes'));
}
if ($request->hasPostData('delete')) {
UserAngelType_delete($user_angeltype);
$user_angeltype->delete();
engelsystem_log(sprintf('User %s removed from %s.', User_Nick_render($user_source, true), $angeltype->name));
success(sprintf(__('User %s removed from %s.'), User_Nick_render($user_source), $angeltype->name));
@ -308,17 +316,14 @@ function user_angeltype_update_controller(): array
throw_redirect(page_link_to('angeltypes'));
}
$user_angeltype = UserAngelType($request->input('user_angeltype_id'));
if (empty($user_angeltype)) {
error(__('User angeltype doesn\'t exist.'));
throw_redirect(page_link_to('angeltypes'));
}
$angeltype = AngelType::findOrFail($user_angeltype['angeltype_id']);
$user_source = User::findOrFail($user_angeltype['user_id']);
/** @var UserAngelType $user_angeltype */
$user_angeltype = UserAngelType::findOrFail($request->input('user_angeltype_id'));
$angeltype = $user_angeltype->angelType;
$user_source = $user_angeltype->user;
if ($request->hasPostData('submit')) {
UserAngelType_update($user_angeltype['id'], $supporter);
$user_angeltype->supporter = $supporter;
$user_angeltype->save();
$msg = $supporter
? __('Added supporter rights for %s to %s.')
@ -353,7 +358,7 @@ function user_angeltype_add_controller(): array
$angeltype = AngelType::findOrFail(request()->input('angeltype_id'));
// User is joining by itself
if (!User_is_AngelType_supporter(auth()->user(), $angeltype)) {
if (!auth()->user()->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
return user_angeltype_join_controller($angeltype);
}
@ -369,8 +374,11 @@ function user_angeltype_add_controller(): array
if ($request->hasPostData('submit')) {
$user_source = load_user();
if (!UserAngelType_exists($user_source->id, $angeltype)) {
$user_angeltype_id = UserAngelType_create($user_source->id, $angeltype);
if (!$angeltype->userAngelTypes()->wherePivot('user_id', $user_source->id)->exists()) {
$userAngelType = new UserAngelType();
$userAngelType->user()->associate($user_source);
$userAngelType->angelType()->associate($angeltype);
$userAngelType->save();
engelsystem_log(sprintf(
'User %s added to %s.',
@ -384,7 +392,9 @@ function user_angeltype_add_controller(): array
));
if ($request->hasPostData('auto_confirm_user')) {
UserAngelType_confirm($user_angeltype_id, $user_source->id);
$userAngelType->confirmUser()->associate($user_source);
$userAngelType->save();
engelsystem_log(sprintf(
'User %s confirmed as %s.',
User_Nick_render($user_source, true),
@ -414,7 +424,8 @@ function user_angeltype_join_controller(AngelType $angeltype)
{
$user = auth()->user();
$user_angeltype = UserAngelType_by_User_and_AngelType($user->id, $angeltype);
/** @var UserAngelType $user_angeltype */
$user_angeltype = UserAngelType::whereUserId($user->id)->where('angel_type_id', $angeltype->id)->first();
if (!empty($user_angeltype)) {
error(sprintf(__('You are already a %s.'), $angeltype->name));
throw_redirect(page_link_to('angeltypes'));
@ -422,18 +433,22 @@ function user_angeltype_join_controller(AngelType $angeltype)
$request = request();
if ($request->hasPostData('submit')) {
$user_angeltype_id = UserAngelType_create($user->id, $angeltype);
$userAngelType = new UserAngelType();
$userAngelType->user()->associate($user);
$userAngelType->angelType()->associate($angeltype);
$userAngelType->save();
$success_message = sprintf(__('You joined %s.'), $angeltype->name);
engelsystem_log(sprintf(
'User %s joined %s.',
User_Nick_render($user, true),
AngelType_name_render($angeltype, true)
));
success($success_message);
success(sprintf(__('You joined %s.'), $angeltype->name));
if (auth()->can('admin_user_angeltypes') && $request->hasPostData('auto_confirm_user')) {
UserAngelType_confirm($user_angeltype_id, $user->id);
$userAngelType->confirmUser()->associate($user);
$userAngelType->save();
engelsystem_log(sprintf(
'User %s confirmed as %s.',
User_Nick_render($user, true),

View File

@ -17,9 +17,9 @@ function user_driver_license_required_hint()
return null;
}
$angeltypes = User_angeltypes($user->id);
$angeltypes = $user->userAngelTypes;
foreach ($angeltypes as $angeltype) {
if ($angeltype['requires_driver_license']) {
if ($angeltype->requires_driver_license) {
return sprintf(
__('You joined an angeltype which requires a driving license. Please edit your driving license information here: %s.'),
'<a href="' . user_driver_license_edit_link() . '" class="text-info">' . __('driving license information') . '</a>'

View File

@ -250,7 +250,7 @@ function user_controller()
$user_source,
auth()->can('admin_user'),
User_is_freeloader($user_source),
User_angeltypes($user_source->id),
$user_source->userAngelTypes,
$user_source->groups,
$shifts,
$user->id == $user_source->id,

View File

@ -3,7 +3,6 @@
namespace Engelsystem\Events\Listener;
use Engelsystem\Config\Config;
use Engelsystem\Database\Database;
use Engelsystem\Models\AngelType;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
@ -12,10 +11,10 @@ use Psr\Log\LoggerInterface;
class OAuth2
{
/** @var array */
protected $config;
protected array $config;
/** @var LoggerInterface */
protected $log;
protected LoggerInterface $log;
/**
* @param Config $config
@ -29,16 +28,14 @@ class OAuth2
/**
* @param string $event
* @param string $provider
* @param string $provider OAuth provider name
* @param Collection $data OAuth userdata
*/
public function login(string $event, string $provider, Collection $data)
public function login(string $event, string $provider, Collection $data): void
{
/** @var Database $db */
$db = app(Database::class);
$ssoTeams = $this->getSsoTeams($provider);
$user = auth()->user();
$currentUserAngeltypes = collect($db->select('SELECT * FROM UserAngelTypes WHERE user_id = ?', [$user->id]));
$currentUserAngeltypes = $user->userAngelTypes;
$userGroups = $data->get(($this->config[$provider] ?? [])['groups'] ?? 'groups', []);
foreach ($userGroups as $groupName) {
@ -47,7 +44,9 @@ class OAuth2
}
$team = $ssoTeams[$groupName];
$userAngeltype = $currentUserAngeltypes->where('angeltype_id', $team['id'])->first();
$angelType = AngelType::find($team['id']);
/** @var AngelType $userAngeltype */
$userAngeltype = $currentUserAngeltypes->where('pivot.angel_type_id', $team['id'])->first();
$supporter = $team['supporter'];
$confirmed = $supporter ? $user->id : null;
@ -56,15 +55,13 @@ class OAuth2
'SSO {provider}: Added to angeltype {angeltype}, confirmed: {confirmed}, supporter: {supporter}',
[
'provider' => $provider,
'angeltype' => AngelType::find($team['id'])->name,
'angeltype' => $angelType->name,
'confirmed' => $confirmed ? 'yes' : 'no',
'supporter' => $supporter ? 'yes' : 'no',
]
);
$db->insert(
'INSERT INTO UserAngelTypes (user_id, angeltype_id, confirm_user_id, supporter) VALUES (?, ?, ?, ?)',
[$user->id, $team['id'], $confirmed, $supporter]
);
$user->userAngelTypes()->attach($angelType, ['supporter' => $supporter, 'confirm_user_id' => $confirmed]);
continue;
}
@ -73,40 +70,33 @@ class OAuth2
continue;
}
if ($userAngeltype->supporter != $supporter) {
$db->update(
'UPDATE UserAngelTypes SET supporter=? WHERE id = ?',
[$supporter, $userAngeltype->id]
);
if ($userAngeltype->pivot->supporter != $supporter) {
$userAngeltype->pivot->supporter = $supporter;
$userAngeltype->pivot->save();
$this->log->info(
'SSO {provider}: Set supporter state for angeltype {angeltype}',
[
'provider' => $provider,
'angeltype' => AngelType::find($userAngeltype->angeltype_id)->name,
'angeltype' => $userAngeltype->pivot->angelType->name,
]
);
}
if (!$userAngeltype->confirm_user_id) {
$db->update(
'UPDATE UserAngelTypes SET confirm_user_id=? WHERE id = ?',
[$user->id, $userAngeltype->id]
);
if (!$userAngeltype->pivot->confirm_user_id) {
$userAngeltype->pivot->confirmUser()->associate($user);
$userAngeltype->pivot->save();
$this->log->info(
'SSO {provider}: Set confirmed state for angeltype {angeltype}',
[
'provider' => $provider,
'angeltype' => AngelType::find($userAngeltype->angeltype_id)->name,
'angeltype' => $userAngeltype->pivot->angelType->name,
]
);
}
}
}
/**
* @param string $provider
* @return array
*/
public function getSsoTeams(string $provider): array
{
$config = $this->config[$provider] ?? [];

View File

@ -18,7 +18,6 @@ $includeFiles = [
__DIR__ . '/../includes/model/ShiftsFilter.php',
__DIR__ . '/../includes/model/ShiftSignupState.php',
__DIR__ . '/../includes/model/Stats.php',
__DIR__ . '/../includes/model/UserAngelTypes_model.php',
__DIR__ . '/../includes/model/User_model.php',
__DIR__ . '/../includes/model/UserWorkLog_model.php',
__DIR__ . '/../includes/model/ValidationResult.php',

View File

@ -5,6 +5,7 @@ use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Shifts\ShiftType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Engelsystem\ShiftsFilter;
use Engelsystem\ShiftSignupState;
@ -376,7 +377,7 @@ function Shift_signup_allowed_angel(
}
if (empty($user_angeltype)) {
$user_angeltype = UserAngelType_by_User_and_AngelType($user->id, $angeltype);
$user_angeltype = UserAngelType::whereUserId($user->id)->where('angel_type_id', $angeltype->id)->first();
}
if (
@ -456,7 +457,7 @@ function Shift_signout_allowed($shift, AngelType $angeltype, $signout_user_id)
// angeltype supporter can sign out any user at any time from their supported angeltype
if (
auth()->can('shiftentry_edit_angeltype_supporter')
&& User_is_AngelType_supporter($user, $angeltype)
&& ($user->isAngelTypeSupporter($angeltype) || auth()->can('admin_user_angeltypes'))
) {
return true;
}
@ -495,7 +496,7 @@ function Shift_signup_allowed(
if (
auth()->can('shiftentry_edit_angeltype_supporter')
&& User_is_AngelType_supporter(auth()->user(), $angeltype)
&& (auth()->user()->isAngelTypeSupporter($angeltype) || auth()->can('admin_user_angeltypes'))
) {
return Shift_signup_allowed_angeltype_supporter($needed_angeltype, $shift_entries);
}

View File

@ -1,284 +0,0 @@
<?php
use Engelsystem\Database\Db;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\User;
/**
* User angeltypes model
*/
/**
* Checks if a user joined an angeltype.
*
* @param int $userId The user to be checked
* @param AngelType $angeltype The angeltype to be checked
* @return boolean
*/
function UserAngelType_exists($userId, AngelType $angeltype)
{
return count(Db::select('
SELECT `id`
FROM `UserAngelTypes`
WHERE `UserAngelTypes`.`user_id`=?
AND `angeltype_id`=?
', [$userId, $angeltype->id])) > 0;
}
/**
* List users angeltypes.
*
* @param int $userId
* @return array[]
*/
function User_angeltypes($userId)
{
return Db::select('
SELECT `angel_types`.*, `UserAngelTypes`.`confirm_user_id`, `UserAngelTypes`.`supporter`
FROM `UserAngelTypes`
JOIN `angel_types` ON `UserAngelTypes`.`angeltype_id` = `angel_types`.`id`
WHERE `UserAngelTypes`.`user_id`=?
', [$userId]);
}
/**
* Gets unconfirmed user angeltypes for angeltypes of which the given user is a supporter.
*
* @param int $userId
* @return array[]
*/
function User_unconfirmed_AngelTypes($userId)
{
return Db::select('
SELECT
`UserAngelTypes`.*,
`angel_types`.`name`,
count(`UnconfirmedMembers`.`user_id`) AS `count`
FROM `UserAngelTypes`
JOIN `angel_types` ON `UserAngelTypes`.`angeltype_id`=`angel_types`.`id`
JOIN `UserAngelTypes` AS `UnconfirmedMembers` ON `UserAngelTypes`.`angeltype_id`=`UnconfirmedMembers`.`angeltype_id`
WHERE `UserAngelTypes`.`user_id`=?
AND `UserAngelTypes`.`supporter`=TRUE
AND `angel_types`.`restricted`=TRUE
AND `UnconfirmedMembers`.`confirm_user_id` IS NULL
GROUP BY `UserAngelTypes`.`angeltype_id`, `UserAngelTypes`.`id`, angel_types.name, UserAngelTypes.user_id, UserAngelTypes.confirm_user_id, UserAngelTypes.supporter
ORDER BY `angel_types`.`name`
', [$userId]);
}
/**
* Returns true if user is angeltype supporter or has privilege admin_user_angeltypes.
*
* @param User $user
* @param AngelType $angeltype
* @return bool
*/
function User_is_AngelType_supporter($user, AngelType $angeltype)
{
if (!$user) {
return false;
}
$privileges = $user->privileges->pluck('name')->toArray();
return
count(
Db::select(
'
SELECT `id`
FROM `UserAngelTypes`
WHERE `user_id`=?
AND `angeltype_id`=?
AND `supporter`=TRUE
LIMIT 1
',
[
$user->id,
$angeltype->id
]
)
) > 0
|| in_array('admin_user_angeltypes', $privileges);
}
/**
* Add or remove supporter rights.
*
* @param int $user_angeltype_id
* @param bool $supporter
*/
function UserAngelType_update($user_angeltype_id, $supporter)
{
Db::update('
UPDATE `UserAngelTypes`
SET `supporter`=?
WHERE `id`=?
LIMIT 1
', [(int)$supporter, $user_angeltype_id]);
}
/**
* Delete all unconfirmed UserAngelTypes for given Angeltype.
*
* @param int $angeltype_id
*/
function UserAngelTypes_delete_all_unconfirmed(int $angeltype_id)
{
Db::delete('
DELETE FROM `UserAngelTypes`
WHERE `angeltype_id`=?
AND `confirm_user_id` IS NULL
', [$angeltype_id]);
}
/**
* Confirm all unconfirmed UserAngelTypes for given Angeltype.
*
* @param int $angeltype_id
* @param int $confirm_user_id
*/
function UserAngelTypes_confirm_all($angeltype_id, $confirm_user_id)
{
Db::update('
UPDATE `UserAngelTypes`
SET `confirm_user_id`=?
WHERE `angeltype_id`=?
AND `confirm_user_id` IS NULL
', [$confirm_user_id, $angeltype_id]);
}
/**
* Get all unconfirmed Users for given Angeltype
*
* @param int $angeltype_id
*/
function UserAngelTypes_all_unconfirmed($angeltype_id)
{
return Db::select('
SELECT *
FROM `UserAngelTypes`
WHERE `angeltype_id`=?
AND `confirm_user_id` IS NULL
', [$angeltype_id]);
}
/**
* Confirm an UserAngelType with confirming user.
*
* @param int $user_angeltype_id
* @param int $confirm_user_id
*/
function UserAngelType_confirm($user_angeltype_id, $confirm_user_id)
{
Db::update('
UPDATE `UserAngelTypes`
SET `confirm_user_id`=?
WHERE `id`=?
LIMIT 1', [$confirm_user_id, $user_angeltype_id]);
}
/**
* Delete an UserAngelType.
*
* @param array $user_angeltype
*/
function UserAngelType_delete($user_angeltype)
{
Db::delete('
DELETE FROM `UserAngelTypes`
WHERE `id`=?
LIMIT 1', [$user_angeltype['id']]);
}
/**
* Create an UserAngelType.
*
* @param int $userId
* @param AngelType $angeltype
* @return int
*/
function UserAngelType_create($userId, AngelType $angeltype)
{
Db::insert(
'
INSERT INTO `UserAngelTypes` (`user_id`, `angeltype_id`, `supporter`)
VALUES (?, ?, FALSE)
',
[
$userId,
$angeltype->id
]
);
return Db::getPdo()->lastInsertId();
}
/**
* Get an UserAngelType by its id.
*
* @param int $user_angeltype_id
* @return array|null
*/
function UserAngelType($user_angeltype_id)
{
$userAngelType = Db::selectOne('
SELECT *
FROM `UserAngelTypes`
WHERE `id`=?
LIMIT 1', [$user_angeltype_id]);
return empty($userAngelType) ? null : $userAngelType;
}
/**
* Get an UserAngelType by user and angeltype.
*
* @param int $userId
* @param AngelType $angeltype
* @return array|null
*/
function UserAngelType_by_User_and_AngelType($userId, AngelType $angeltype)
{
return Db::selectOne(
'
SELECT *
FROM `UserAngelTypes`
WHERE `user_id`=?
AND `angeltype_id`=?
LIMIT 1
',
[
$userId,
$angeltype->id
]
);
}
/**
* Get an UserAngelTypes by user
*
* @param int $userId
* @param bool $onlyConfirmed
* @return array[]|null
*/
function UserAngelTypes_by_User($userId, $onlyConfirmed = false)
{
return Db::select(
'
SELECT *
FROM `UserAngelTypes`
' . ($onlyConfirmed ? 'LEFT JOIN angel_types AS a ON a.id=UserAngelTypes.angeltype_id' : '') . '
WHERE `user_id`=?
'
. (
$onlyConfirmed ? 'AND (
a.`restricted`=0
OR (
NOT `UserAngelTypes`.`confirm_user_id` IS NULL
OR `UserAngelTypes`.`id` IS NULL
)
)' : ''
),
[$userId]
);
}

View File

@ -60,44 +60,21 @@ function User_is_freeloader($user)
/**
* Returns all users that are not member of given angeltype.
*
* @param array $angeltype Angeltype
* @param AngelType $angeltype Angeltype
*
* @return User[]|Collection
*/
function Users_by_angeltype_inverted($angeltype)
function Users_by_angeltype_inverted(AngelType $angeltype)
{
return User::query()
->select('users.*')
->leftJoin('UserAngelTypes', function ($query) use ($angeltype) {
->leftJoin('user_angel_type', function ($query) use ($angeltype) {
/** @var JoinClause $query */
$query
->on('users.id', '=', 'UserAngelTypes.user_id')
->where('UserAngelTypes.angeltype_id', '=', $angeltype['id']);
->on('users.id', '=', 'user_angel_type.user_id')
->where('user_angel_type.angel_type_id', '=', $angeltype->id);
})
->whereNull('UserAngelTypes.id')
->orderBy('users.name')
->get();
}
/**
* Returns all members of given angeltype.
*
* @param AngelType $angeltype
* @return User[]|Collection
*/
function Users_by_angeltype(AngelType $angeltype)
{
return User::query()
->select(
'users.*',
'UserAngelTypes.id AS user_angeltype_id',
'UserAngelTypes.confirm_user_id',
'UserAngelTypes.supporter',
'users_licenses.*'
)
->join('UserAngelTypes', 'users.id', '=', 'UserAngelTypes.user_id')
->leftJoin('users_licenses', 'users.id', '=', 'users_licenses.user_id')
->where('UserAngelTypes.angeltype_id', '=', $angeltype->id)
->whereNull('user_angel_type.id')
->orderBy('users.name')
->get();
}

View File

@ -34,6 +34,7 @@ function admin_free()
$angelType = $request->input('angeltype', '');
/** @var User[] $users */
$users = [];
if ($request->has('submit')) {
$query = User::with('personalData')
@ -52,16 +53,16 @@ function admin_free()
->groupBy('users.id');
if (!empty($angelType)) {
$query->join('UserAngelTypes', function ($join) use ($angelType) {
$query->join('user_angel_type', function ($join) use ($angelType) {
/** @var JoinClause $join */
$join->on('UserAngelTypes.user_id', '=', 'users.id')
->where('UserAngelTypes.angeltype_id', '=', $angelType);
$join->on('user_angel_type.user_id', '=', 'users.id')
->where('user_angel_type.angel_type_id', '=', $angelType);
});
$query->join('angel_types', function ($join) {
/** @var JoinClause $join */
$join->on('UserAngelTypes.angeltype_id', '=', 'angel_types.id')
->whereNotNull('UserAngelTypes.confirm_user_id')
$join->on('user_angel_type.angel_type_id', '=', 'angel_types.id')
->whereNotNull('user_angel_type.confirm_user_id')
->orWhere('angel_types.restricted', '=', '0');
});
}

View File

@ -2,7 +2,6 @@
use Carbon\Carbon;
use Engelsystem\Database\Database;
use Engelsystem\Database\Db;
use Engelsystem\Events\Listener\OAuth2;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Group;
@ -310,11 +309,9 @@ function guest_register()
// Assign angel-types
$user_angel_types_info = [];
foreach ($selected_angel_types as $selected_angel_type_id) {
Db::insert(
'INSERT INTO `UserAngelTypes` (`user_id`, `angeltype_id`, `supporter`) VALUES (?, ?, FALSE)',
[$user->id, $selected_angel_type_id]
);
$user_angel_types_info[] = $angel_types[$selected_angel_type_id];
$angelType = AngelType::findOrFail($selected_angel_type_id);
$user->userAngelTypes()->attach($angelType);
$user_angel_types_info[] = $angelType->name;
}
// Commit complete user data

View File

@ -4,7 +4,10 @@ use Engelsystem\Database\Db;
use Engelsystem\Helpers\Carbon;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\UserAngelType;
use Engelsystem\ShiftsFilter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Support\Collection;
/**
@ -157,6 +160,7 @@ function load_types()
error(__('The administration has not configured any angeltypes yet - or you are not subscribed to any angeltype.'));
throw_redirect(page_link_to('/'));
}
$types = Db::select(
'
SELECT
@ -165,15 +169,15 @@ function load_types()
(
`angel_types`.`restricted`=0
OR (
NOT `UserAngelTypes`.`confirm_user_id` IS NULL
OR `UserAngelTypes`.`id` IS NULL
NOT `user_angel_type`.`confirm_user_id` IS NULL
OR `user_angel_type`.`id` IS NULL
)
) AS `enabled`
FROM `angel_types`
LEFT JOIN `UserAngelTypes`
LEFT JOIN `user_angel_type`
ON (
`UserAngelTypes`.`angeltype_id`=`angel_types`.`id`
AND `UserAngelTypes`.`user_id`=?
`user_angel_type`.`angel_type_id`=`angel_types`.`id`
AND `user_angel_type`.`user_id`=?
)
ORDER BY `angel_types`.`name`
',
@ -181,9 +185,11 @@ function load_types()
$user->id,
]
);
if (empty($types)) {
return unrestricted_angeltypes();
}
return $types;
}
@ -208,12 +214,16 @@ function view_user_shifts()
$types = load_types();
$ownTypes = [];
foreach (UserAngelTypes_by_User($user->id, true) as $type) {
if (!$type['confirm_user_id'] && $type['restricted']) {
continue;
}
$ownTypes[] = (int)$type['angeltype_id'];
/** @var EloquentCollection|UserAngelType[] $userAngelTypes */
$userAngelTypes = UserAngelType::whereUserId($user->id)
->leftJoin('angel_types', 'user_angel_type.angel_type_id', 'angel_types.id')
->where(function (Builder $query) {
$query->whereNotNull('user_angel_type.confirm_user_id')
->orWhere('angel_types.restricted', false);
})
->get();
foreach ($userAngelTypes as $type) {
$ownTypes[] = $type->angel_type_id;
}
if (!$session->has('shifts-filter')) {

View File

@ -3,6 +3,7 @@
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\License;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Engelsystem\ShiftCalendarRenderer;
use Engelsystem\ShiftsFilterRenderer;
use Illuminate\Support\Collection;
@ -38,7 +39,7 @@ function AngelType_name_render(AngelType $angeltype, $plain = false)
*/
function AngelType_render_membership(AngelType $user_angeltype)
{
if (!empty($user_angeltype->user_angeltype_id)) {
if (!empty($user_angeltype->user_angel_type_id)) {
if ($user_angeltype->restricted) {
if (empty($user_angeltype->confirm_user_id)) {
return icon('mortarboard-fill') . __('Unconfirmed');
@ -136,7 +137,7 @@ function AngelType_edit_view(AngelType $angeltype, bool $supporter_mode)
* Renders the buttons for the angeltype view.
*
* @param AngelType $angeltype
* @param array|null $user_angeltype
* @param UserAngelType|null $user_angeltype
* @param bool $admin_angeltypes
* @param bool $supporter
* @param License $user_driver_license
@ -145,7 +146,7 @@ function AngelType_edit_view(AngelType $angeltype, bool $supporter_mode)
*/
function AngelType_view_buttons(
AngelType $angeltype,
$user_angeltype,
?UserAngelType $user_angeltype,
$admin_angeltypes,
$supporter,
$user_driver_license,
@ -173,14 +174,14 @@ function AngelType_view_buttons(
error(__('This angeltype requires a driver license. Please enter your driver license information!'));
}
if ($angeltype->restricted && empty($user_angeltype['confirm_user_id'])) {
if ($angeltype->restricted && !$user_angeltype->confirm_user_id) {
error(sprintf(
__('You are unconfirmed for this angeltype. Please go to the introduction for %s to get confirmed.'),
$angeltype->name
));
}
$buttons[] = button(
page_link_to('user_angeltypes', ['action' => 'delete', 'user_angeltype_id' => $user_angeltype['id']]),
page_link_to('user_angeltypes', ['action' => 'delete', 'user_angeltype_id' => $user_angeltype->id]),
icon('box-arrow-right') . __('leave')
);
}
@ -230,12 +231,12 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
$member['has_license_forklift'] = icon_bool($member->license->drive_forklift);
}
if ($angeltype->restricted && empty($member['confirm_user_id'])) {
if ($angeltype->restricted && empty($member->pivot->confirm_user_id)) {
$member['actions'] = table_buttons([
button(
page_link_to(
'user_angeltypes',
['action' => 'confirm', 'user_angeltype_id' => $member['user_angeltype_id']]
['action' => 'confirm', 'user_angeltype_id' => $member->pivot->id]
),
__('confirm'),
'btn-sm'
@ -243,20 +244,20 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
button(
page_link_to(
'user_angeltypes',
['action' => 'delete', 'user_angeltype_id' => $member['user_angeltype_id']]
['action' => 'delete', 'user_angeltype_id' => $member->pivot->id]
),
__('deny'),
'btn-sm'
)
]);
$members_unconfirmed[] = $member;
} elseif ($member['supporter']) {
} elseif ($member->pivot->supporter) {
if ($admin_angeltypes) {
$member['actions'] = table_buttons([
button(
page_link_to('user_angeltypes', [
'action' => 'update',
'user_angeltype_id' => $member['user_angeltype_id'],
'user_angeltype_id' => $member->pivot->id,
'supporter' => 0
]),
icon('person-fill-down') . __('Remove supporter rights'),
@ -274,7 +275,7 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
button(
page_link_to('user_angeltypes', [
'action' => 'update',
'user_angeltype_id' => $member['user_angeltype_id'],
'user_angeltype_id' => $member->pivot->id,
'supporter' => 1
]),
icon('person-fill-up') . __('Add supporter rights'),
@ -284,7 +285,7 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
button(
page_link_to('user_angeltypes', [
'action' => 'delete',
'user_angeltype_id' => $member['user_angeltype_id']
'user_angeltype_id' => $member->pivot->id
]),
icon('trash') . __('remove'),
'btn-sm'
@ -338,7 +339,7 @@ function AngelType_view_table_headers(AngelType $angeltype, $supporter, $admin_a
*
* @param AngelType $angeltype
* @param User[] $members
* @param array $user_angeltype
* @param UserAngelType|null $user_angeltype
* @param bool $admin_user_angeltypes
* @param bool $admin_angeltypes
* @param bool $supporter
@ -352,7 +353,7 @@ function AngelType_view_table_headers(AngelType $angeltype, $supporter, $admin_a
function AngelType_view(
AngelType $angeltype,
$members,
$user_angeltype,
?UserAngelType $user_angeltype,
$admin_user_angeltypes,
$admin_angeltypes,
$supporter,
@ -553,13 +554,13 @@ function AngelTypes_about_view_angeltype(AngelType $angeltype)
$html .= AngelTypes_render_contact_info($angeltype);
}
if (isset($angeltype->user_angeltype_id)) {
if (isset($angeltype->user_angel_type_id)) {
$buttons = [];
if (!empty($angeltype->user_angeltype_id)) {
if (!empty($angeltype->user_angel_type_id)) {
$buttons[] = button(
page_link_to(
'user_angeltypes',
['action' => 'delete', 'user_angeltype_id' => $angeltype->user_angeltype_id]
['action' => 'delete', 'user_angeltype_id' => $angeltype->user_angel_type_id]
),
icon('box-arrow-right') . __('leave')
);

View File

@ -4,6 +4,7 @@ use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Shifts\ShiftType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Engelsystem\ShiftSignupState;
use Illuminate\Support\Collection;
@ -75,20 +76,21 @@ function Shift_editor_info_render($shift)
/**
* @param array $shift
* @param AngelType $angeltype
* @param array $user_angeltype
* @return string
*/
function Shift_signup_button_render($shift, AngelType $angeltype, $user_angeltype = null)
function Shift_signup_button_render($shift, AngelType $angeltype)
{
if (empty($user_angeltype)) {
$user_angeltype = UserAngelType_by_User_and_AngelType(auth()->user()->id, $angeltype);
}
/** @var UserAngelType|null $user_angeltype */
$user_angeltype = UserAngelType::whereUserId(auth()->user()->id)
->where('angel_type_id', $angeltype->id)
->first();
if (
isset($angeltype->shift_signup_state)
&& (
$angeltype->shift_signup_state->isSignupAllowed()
|| User_is_AngelType_supporter(auth()->user(), $angeltype)
|| auth()->user()->isAngelTypeSupporter($angeltype)
|| auth()->can('admin_user_angeltypes')
)
) {
return button(shift_entry_create_link($shift, $angeltype), __('Sign up'));
@ -101,6 +103,7 @@ function Shift_signup_button_render($shift, AngelType $angeltype, $user_angeltyp
)
);
}
return '';
}
@ -208,7 +211,8 @@ function Shift_view($shift, ShiftType $shifttype, Room $room, $angeltypes_source
function Shift_view_render_needed_angeltype($needed_angeltype, $angeltypes, $shift, $user_shift_admin)
{
$angeltype = $angeltypes[$needed_angeltype['TID']];
$angeltype_supporter = User_is_AngelType_supporter(auth()->user(), $angeltype);
$angeltype_supporter = auth()->user()->isAngelTypeSupporter($angeltype)
|| auth()->can('admin_user_angeltypes');
$needed_angels = '';

View File

@ -2,15 +2,16 @@
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
/**
* @param array $user_angeltype
* @param UserAngelType $user_angeltype
* @param User $user
* @param AngelType $angeltype
* @param bool $supporter
* @return string
*/
function UserAngelType_update_view($user_angeltype, User $user, AngelType $angeltype, bool $supporter)
function UserAngelType_update_view(UserAngelType $user_angeltype, User $user, AngelType $angeltype, bool $supporter)
{
return page_with_title($supporter ? __('Add supporter rights') : __('Remove supporter rights'), [
msg(),
@ -31,7 +32,7 @@ function UserAngelType_update_view($user_angeltype, User $user, AngelType $angel
]),
], page_link_to('user_angeltypes', [
'action' => 'update',
'user_angeltype_id' => $user_angeltype['id'],
'user_angeltype_id' => $user_angeltype->id,
'supporter' => ($supporter ? '1' : '0'),
])),
]);
@ -80,12 +81,12 @@ function UserAngelTypes_confirm_all_view(AngelType $angeltype)
}
/**
* @param array $user_angeltype
* @param UserAngelType $user_angeltype
* @param User $user
* @param AngelType $angeltype
* @return string
*/
function UserAngelType_confirm_view($user_angeltype, $user, AngelType $angeltype)
function UserAngelType_confirm_view(UserAngelType $user_angeltype, User $user, AngelType $angeltype)
{
return page_with_title(__('Confirm angeltype for user'), [
msg(),
@ -99,17 +100,17 @@ function UserAngelType_confirm_view($user_angeltype, $user, AngelType $angeltype
button(angeltype_link($angeltype->id), icon('x-lg') . __('cancel')),
form_submit('confirm_user', icon('check-lg') . __('yes'), 'btn-primary', false),
]),
], page_link_to('user_angeltypes', ['action' => 'confirm', 'user_angeltype_id' => $user_angeltype['id']])),
], page_link_to('user_angeltypes', ['action' => 'confirm', 'user_angeltype_id' => $user_angeltype->id])),
]);
}
/**
* @param array $user_angeltype
* @param UserAngelType $user_angeltype
* @param User $user
* @param AngelType $angeltype
* @return string
*/
function UserAngelType_delete_view($user_angeltype, $user, AngelType $angeltype)
function UserAngelType_delete_view(UserAngelType $user_angeltype, User $user, AngelType $angeltype)
{
return page_with_title(__('Remove angeltype'), [
msg(),
@ -123,7 +124,7 @@ function UserAngelType_delete_view($user_angeltype, $user, AngelType $angeltype)
button(angeltype_link($angeltype->id), icon('x-lg') . __('cancel')),
form_submit('delete', icon('check-lg') . __('yes'), 'btn-primary', false),
]),
], page_link_to('user_angeltypes', ['action' => 'delete', 'user_angeltype_id' => $user_angeltype['id']])),
], page_link_to('user_angeltypes', ['action' => 'delete', 'user_angeltype_id' => $user_angeltype->id])),
], true);
}

View File

@ -432,7 +432,7 @@ function User_view_worklog(Worklog $worklog, $admin_user_worklog_privilege)
* @param User $user_source
* @param bool $admin_user_privilege
* @param bool $freeloader
* @param array[] $user_angeltypes
* @param AngelType[] $user_angeltypes
* @param Group[] $user_groups
* @param array[] $shifts
* @param bool $its_me
@ -488,7 +488,7 @@ function User_view(
$needs_drivers_license = false;
foreach ($user_angeltypes as $angeltype) {
$needs_drivers_license = $needs_drivers_license || $angeltype['requires_driver_license'];
$needs_drivers_license = $needs_drivers_license || $angeltype->requires_driver_license;
}
return page_with_title(
@ -719,7 +719,7 @@ function User_view_state_admin($freeloader, $user_source)
}
/**
* @param array[] $user_angeltypes
* @param AngelType[] $user_angeltypes
* @return string
*/
function User_angeltypes_render($user_angeltypes)
@ -727,11 +727,11 @@ function User_angeltypes_render($user_angeltypes)
$output = [];
foreach ($user_angeltypes as $angeltype) {
$class = 'text-success';
if ($angeltype['restricted'] == 1 && empty($angeltype['confirm_user_id'])) {
if ($angeltype->restricted && !$angeltype->pivot->confirm_user_id) {
$class = 'text-warning';
}
$output[] = '<a href="' . angeltype_link($angeltype['id']) . '" class="' . $class . '">'
. ($angeltype['supporter'] ? icon('patch-check') : '') . $angeltype['name']
$output[] = '<a href="' . angeltype_link($angeltype->id) . '" class="' . $class . '">'
. ($angeltype->pivot->supporter ? icon('patch-check') : '') . $angeltype->name
. '</a>';
}
return div('col-md-2', [

View File

@ -5,7 +5,10 @@ declare(strict_types=1);
namespace Engelsystem\Models;
use Illuminate\Database\Eloquent\Builder;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Query\Builder as QueryBuilder;
/**
@ -21,6 +24,9 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
* @property boolean $show_on_dashboard # Show on public dashboard
* @property boolean $hide_register # Hide from registration page
*
* @property-read Collection|User[] $userAngelTypes
* @property-read UserAngelType $pivot
*
* @method static QueryBuilder|AngelType[] whereId($value)
* @method static QueryBuilder|AngelType[] whereName($value)
* @method static QueryBuilder|AngelType[] whereDescription($value)
@ -62,13 +68,12 @@ class AngelType extends BaseModel
'hide_register' => 'boolean',
];
/**
* @codeCoverageIgnore For some reasons parent::boot gets ignored here 0o
*/
protected static function boot(): void
public function userAngelTypes(): BelongsToMany
{
parent::boot();
static::addGlobalScope('order', fn(Builder $builder) => $builder->orderBy('name'));
return $this
->belongsToMany(User::class, 'user_angel_type')
->using(UserAngelType::class)
->withPivot(UserAngelType::getPivotAttributes());
}
public function hasContactInfo(): bool
@ -77,4 +82,13 @@ class AngelType extends BaseModel
|| !empty($this->contact_dect)
|| !empty($this->contact_email);
}
/**
* @codeCoverageIgnore For some reasons parent::boot get s ignored here 0o
*/
protected static function boot(): void
{
parent::boot();
static::addGlobalScope('order', fn(Builder $builder) => $builder->orderBy('name'));
}
}

View File

@ -3,6 +3,7 @@
namespace Engelsystem\Models\User;
use Carbon\Carbon;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\BaseModel;
use Engelsystem\Models\Group;
use Engelsystem\Models\Message;
@ -11,6 +12,7 @@ use Engelsystem\Models\NewsComment;
use Engelsystem\Models\OAuth;
use Engelsystem\Models\Privilege;
use Engelsystem\Models\Question;
use Engelsystem\Models\UserAngelType;
use Engelsystem\Models\Worklog;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
@ -42,6 +44,8 @@ use Illuminate\Support\Collection as SupportCollection;
* @property-read Collection|NewsComment[] $newsComments
* @property-read Collection|OAuth[] $oauth
* @property-read SupportCollection|Privilege[] $privileges
* @property-read Collection|AngelType[] $userAngelTypes
* @property-read UserAngelType $pivot
* @property-read Collection|Worklog[] $worklogs
* @property-read Collection|Worklog[] $worklogsCreated
* @property-read Collection|Question[] $questionsAsked
@ -171,6 +175,29 @@ class User extends BaseModel
->withDefault();
}
/**
* @return BelongsToMany
*/
public function userAngelTypes(): BelongsToMany
{
return $this
->belongsToMany(AngelType::class, 'user_angel_type')
->using(UserAngelType::class)
->withPivot(UserAngelType::getPivotAttributes());
}
/**
* @param AngelType $angelType
* @return bool
*/
public function isAngelTypeSupporter(AngelType $angelType): bool
{
return $this->userAngelTypes()
->wherePivot('angel_type_id', $angelType->id)
->wherePivot('supporter', true)
->exists();
}
/**
* @return HasMany
*/

View File

@ -3,14 +3,14 @@
namespace Engelsystem\Models\User;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Eloquent\Builder;
/**
* @property int $user_id
*
* @property-read QueryBuilder|User $user
* @property-read User $user
*
* @method static QueryBuilder|static[] whereUserId($value)
* @method static Builder|static[] whereUserId($value)
*/
trait UsesUserModel
{

View File

@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Models;
use Engelsystem\Models\User\User;
use Engelsystem\Models\User\UsesUserModel;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Query\Builder as QueryBuilder;
/**
* @mixin Builder
*
* @property int $id
* @property int $angel_type_id
* @property int $confirm_user_id
* @property bool $supporter
*
* @property-read AngelType $angelType
* @property-read User $confirmUser
*
* @method static QueryBuilder|AngelType[] whereId($value)
* @method static QueryBuilder|AngelType[] whereAngelTypeId($value)
* @method static QueryBuilder|AngelType[] whereConfirmUserId($value)
* @method static QueryBuilder|AngelType[] whereSupporter($value)
*/
class UserAngelType extends Pivot
{
use HasFactory;
use UsesUserModel;
/** @var bool Increment the IDs */
public $incrementing = true;
/** @var bool Disable timestamps */
public $timestamps = false;
/** @var array */
protected $fillable = [
'user_id',
'angel_type_id',
'confirm_user_id',
'supporter',
];
/** @var string[] */
protected $casts = [
'user_id' => 'integer',
'angel_type_id' => 'integer',
'confirm_user_id' => 'integer',
'supporter' => 'boolean',
];
/**
* Returns a list of attributes that can be requested for this pivot table
*
* @return string[]
*/
public static function getPivotAttributes(): array
{
return ['id', 'confirm_user_id', 'supporter'];
}
public function angelType(): BelongsTo
{
return $this->belongsTo(AngelType::class);
}
public function confirmUser(): BelongsTo
{
return $this->belongsTo(User::class, 'confirm_user_id');
}
}

View File

@ -3,6 +3,8 @@
namespace Engelsystem\Test\Unit\Models;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
class AngelTypeTest extends ModelTest
{
@ -35,6 +37,30 @@ class AngelTypeTest extends ModelTest
$this->assertEquals($expected, $model->hasContactInfo());
}
/**
* @covers \Engelsystem\Models\AngelType::userAngelTypes
*/
public function testUserAngelTypes(): void
{
User::factory(2)->create();
$user1 = User::factory()->create();
User::factory(1)->create();
$user2 = User::factory()->create();
$angelType = new AngelType(['name' => 'Test']);
$angelType->save();
$angelType->userAngelTypes()->attach($user1);
$angelType->userAngelTypes()->attach($user2);
/** @var UserAngelType $userAngelType */
$userAngelType = UserAngelType::find(1);
$this->assertEquals($angelType->id, $userAngelType->angelType->id);
$angeltypes = $angelType->userAngelTypes;
$this->assertCount(2, $angeltypes);
}
/**
* @covers \Engelsystem\Models\AngelType::boot
*/

View File

@ -41,8 +41,8 @@ class ScheduleTest extends ModelTest
$st->save();
$schedule = new Schedule($this->data);
$schedule->save();
$schedule->shiftType()->associate($st);
$schedule->save();
$this->assertEquals('Shift Type', Schedule::find(1)->shiftType->name);
}

View File

@ -4,6 +4,7 @@ namespace Engelsystem\Test\Unit\Models\User;
use Carbon\Carbon;
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\BaseModel;
use Engelsystem\Models\Group;
use Engelsystem\Models\News;
@ -18,6 +19,7 @@ use Engelsystem\Models\User\PersonalData;
use Engelsystem\Models\User\Settings;
use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Engelsystem\Models\Worklog;
use Engelsystem\Test\Unit\Models\ModelTest;
use Exception;
@ -212,6 +214,52 @@ class UserTest extends ModelTest
$this->assertEquals($relatedModelIds, $user->{$name}->modelKeys());
}
/**
* @covers \Engelsystem\Models\User\User::userAngelTypes
* @return void
*/
public function testUserAngelTypes()
{
AngelType::factory(2)->create();
$angelType1 = AngelType::factory()->create();
AngelType::factory(1)->create();
$angelType2 = AngelType::factory()->create();
$user = new User($this->data);
$user->save();
$user->userAngelTypes()->attach($angelType1);
$user->userAngelTypes()->attach($angelType2);
/** @var UserAngelType $userAngelType */
$userAngelType = UserAngelType::find(1);
$this->assertEquals($user->id, $userAngelType->user->id);
$angeltypes = $user->userAngelTypes;
$this->assertCount(2, $angeltypes);
}
/**
* @covers \Engelsystem\Models\User\User::isAngelTypeSupporter
* @return void
*/
public function testIsAngelTypeSupporter()
{
/** @var AngelType $angelType1 */
$angelType1 = AngelType::factory()->create();
/** @var AngelType $angelType2 */
$angelType2 = AngelType::factory()->create();
$user = new User($this->data);
$user->save();
$user->userAngelTypes()->attach($angelType1, ['supporter' => true]);
$user->userAngelTypes()->attach($angelType2);
$this->assertTrue($user->isAngelTypeSupporter($angelType1));
$this->assertFalse($user->isAngelTypeSupporter($angelType2));
}
/**
* @covers \Engelsystem\Models\User\User::privileges
* @covers \Engelsystem\Models\User\User::getPrivilegesAttribute

View File

@ -0,0 +1,112 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Test\Unit\Models;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Illuminate\Database\Eloquent\Model;
class UserAngelTypeTest extends ModelTest
{
/** @var User|Model */
protected $user;
/** @var User|Model */
protected $confirmed;
/** @var AngelType|Model */
protected $angeltype;
/**
* @covers \Engelsystem\Models\UserAngelType
*/
public function testCreateDefault(): void
{
$model = new UserAngelType();
$model->user()->associate($this->user);
$model->angelType()->associate($this->angeltype);
$model->save();
/** @var UserAngelType $model */
$model = UserAngelType::find(1);
$this->assertEquals($this->user->id, $model->user->id);
$this->assertEquals($this->angeltype->id, $model->angelType->id);
$this->assertNull($model->confirmUser);
$this->assertFalse($model->supporter);
}
/**
* @covers \Engelsystem\Models\UserAngelType
* @covers \Engelsystem\Models\UserAngelType::angelType
* @covers \Engelsystem\Models\UserAngelType::confirmUser
*/
public function testCreateAssociation(): void
{
$this->user
->userAngelTypes()
->attach($this->angeltype, ['confirm_user_id' => $this->confirmed->id, 'supporter' => true]);
/** @var UserAngelType $model */
$model = UserAngelType::find(1);
$this->assertEquals($this->user->id, $model->user->id);
$this->assertEquals($this->angeltype->id, $model->angelType->id);
$this->assertEquals($this->confirmed->id, $model->confirmUser->id);
$this->assertTrue($model->supporter);
}
/**
* @covers \Engelsystem\Models\UserAngelType::confirmUser
*/
public function testConfirmUser(): void
{
$model = new UserAngelType();
$model->user()->associate($this->user);
$model->angelType()->associate($this->angeltype);
$model->confirmUser()->associate($this->confirmed);
$model->save();
/** @var UserAngelType $model */
$model = UserAngelType::find(1);
$this->assertEquals($this->confirmed->id, $model->confirmUser->id);
}
/**
* @covers \Engelsystem\Models\UserAngelType::angelType
*/
public function testAngelType(): void
{
$model = new UserAngelType();
$model->user()->associate($this->user);
$model->angelType()->associate($this->angeltype);
$model->save();
/** @var UserAngelType $model */
$model = UserAngelType::find(1);
$this->assertEquals($this->angeltype->id, $model->angelType->id);
}
/**
* @covers \Engelsystem\Models\UserAngelType::getPivotAttributes
*/
public function testGetPivotAttributes(): void
{
$attributes = UserAngelType::getPivotAttributes();
$this->assertContains('id', $attributes);
$this->assertContains('supporter', $attributes);
$this->assertContains('confirm_user_id', $attributes);
}
public function setUp(): void
{
parent::setUp();
$this->user = User::factory()->create(['id' => 42]);
$this->confirmed = User::factory()->create(['id' => 1337]);
$this->angeltype = AngelType::factory()->create(['id' => 21]);
}
}