Permissions refactoring
* Migration: Added groups, privileges, user_groups, group_privileges, improved references * Models: Added Group, Privilege and integrated it into User * Replaced old permission handling with new models
This commit is contained in:
parent
35815b0838
commit
99afe3f651
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories\Engelsystem\Models;
|
||||
|
||||
use Engelsystem\Models\Group;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class GroupFactory extends Factory
|
||||
{
|
||||
/** @var string */
|
||||
protected $model = Group::class;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->word(),
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories\Engelsystem\Models;
|
||||
|
||||
use Engelsystem\Models\Privilege;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class PrivilegeFactory extends Factory
|
||||
{
|
||||
/** @var string */
|
||||
protected $model = Privilege::class;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->word(),
|
||||
'description' => $this->faker->text(),
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,274 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Migrations;
|
||||
|
||||
use Engelsystem\Database\Migration\Migration;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use stdClass;
|
||||
|
||||
class CreatePrivilegesAndGroupsRelatedTables extends Migration
|
||||
{
|
||||
use ChangesReferences;
|
||||
use Reference;
|
||||
|
||||
/**
|
||||
* Creates the new table, copies the data and drops the old one.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
$hasPrevious = $this->schema->hasTable('Privileges');
|
||||
|
||||
if ($hasPrevious) {
|
||||
// Rename because some DBMS handle identifiers case-insensitive
|
||||
$this->schema->rename('Groups', 'groups_old');
|
||||
$this->schema->rename('Privileges', 'privileges_old');
|
||||
}
|
||||
|
||||
$this->createNew();
|
||||
|
||||
if ($hasPrevious) {
|
||||
$this->copyOldToNew();
|
||||
|
||||
$this->changeReferences(
|
||||
'groups_old',
|
||||
'UID',
|
||||
'groups',
|
||||
'id'
|
||||
);
|
||||
$this->changeReferences(
|
||||
'privileges_old',
|
||||
'id',
|
||||
'privileges',
|
||||
'id'
|
||||
);
|
||||
$this->changeReferences(
|
||||
'UserGroups',
|
||||
'id',
|
||||
'users_groups',
|
||||
'id'
|
||||
);
|
||||
$this->changeReferences(
|
||||
'GroupPrivileges',
|
||||
'id',
|
||||
'group_privileges',
|
||||
'id'
|
||||
);
|
||||
|
||||
$this->schema->drop('UserGroups');
|
||||
$this->schema->drop('GroupPrivileges');
|
||||
$this->schema->drop('groups_old');
|
||||
$this->schema->drop('privileges_old');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreates the previous table, copies the data and drops the new one.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// Rename because some DBMS handle identifiers case-insensitive
|
||||
$this->schema->rename('groups', 'groups_new');
|
||||
$this->schema->rename('privileges', 'privileges_new');
|
||||
|
||||
$this->createOldTable();
|
||||
$this->copyNewToOld();
|
||||
|
||||
$this->changeReferences(
|
||||
'groups_new',
|
||||
'id',
|
||||
'Groups',
|
||||
'UID',
|
||||
'integer'
|
||||
);
|
||||
$this->changeReferences(
|
||||
'privileges_new',
|
||||
'id',
|
||||
'Privileges',
|
||||
'id'
|
||||
);
|
||||
$this->changeReferences(
|
||||
'users_groups',
|
||||
'id',
|
||||
'UserGroups',
|
||||
'id'
|
||||
);
|
||||
$this->changeReferences(
|
||||
'group_privileges',
|
||||
'id',
|
||||
'GroupPrivileges',
|
||||
'id'
|
||||
);
|
||||
|
||||
$this->schema->drop('users_groups');
|
||||
$this->schema->drop('group_privileges');
|
||||
$this->schema->drop('groups_new');
|
||||
$this->schema->drop('privileges_new');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function createNew(): void
|
||||
{
|
||||
$this->schema->create('groups', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name', 35)->unique();
|
||||
});
|
||||
|
||||
$this->schema->create('privileges', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name', 128)->unique();
|
||||
$table->string('description', 1024);
|
||||
});
|
||||
|
||||
$this->schema->create('users_groups', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$this->referencesUser($table)->index();
|
||||
$this->references($table, 'groups')->index();
|
||||
});
|
||||
|
||||
$this->schema->create('group_privileges', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$this->references($table, 'groups')->index();
|
||||
$this->references($table, 'privileges')->index();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function createOldTable(): void
|
||||
{
|
||||
$this->schema->create('Groups', function (Blueprint $table) {
|
||||
$table->string('Name', 35);
|
||||
$table->integer('UID')->primary();
|
||||
});
|
||||
|
||||
$this->schema->create('Privileges', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name', 128)->unique();
|
||||
$table->string('desc', 1024);
|
||||
});
|
||||
|
||||
$this->schema->create('UserGroups', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$this->references($table, 'users', 'uid');
|
||||
$this->references($table, 'Groups', 'group_id', 'UID', false, 'integer')->index();
|
||||
$table->index(['uid', 'group_id']);
|
||||
});
|
||||
|
||||
$this->schema->create('GroupPrivileges', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$this->references($table, 'Groups', 'group_id', 'UID', false, 'integer');
|
||||
$this->references($table, 'Privileges', 'privilege_id')->index();
|
||||
$table->index(['group_id', 'privilege_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function copyOldToNew(): void
|
||||
{
|
||||
$connection = $this->schema->getConnection();
|
||||
|
||||
/** @var stdClass[] $records */
|
||||
$records = $connection
|
||||
->table('groups_old')
|
||||
->get();
|
||||
foreach ($records as $record) {
|
||||
$connection->table('groups')->insert([
|
||||
'id' => $record->UID,
|
||||
'name' => $record->Name,
|
||||
]);
|
||||
}
|
||||
|
||||
$records = $connection
|
||||
->table('privileges_old')
|
||||
->get();
|
||||
foreach ($records as $record) {
|
||||
$connection->table('privileges')->insert([
|
||||
'id' => $record->id,
|
||||
'name' => $record->name,
|
||||
'description' => $record->desc,
|
||||
]);
|
||||
}
|
||||
|
||||
$records = $connection
|
||||
->table('UserGroups')
|
||||
->get();
|
||||
foreach ($records as $record) {
|
||||
$connection->table('users_groups')->insert([
|
||||
'id' => $record->id,
|
||||
'user_id' => $record->uid,
|
||||
'group_id' => $record->group_id,
|
||||
]);
|
||||
}
|
||||
|
||||
$records = $connection
|
||||
->table('GroupPrivileges')
|
||||
->get();
|
||||
foreach ($records as $record) {
|
||||
$connection->table('group_privileges')->insert([
|
||||
'id' => $record->id,
|
||||
'group_id' => $record->group_id,
|
||||
'privilege_id' => $record->privilege_id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function copyNewToOld(): void
|
||||
{
|
||||
$connection = $this->schema->getConnection();
|
||||
|
||||
/** @var Collection|stdClass[] $records */
|
||||
$records = $connection
|
||||
->table('groups_new')
|
||||
->get();
|
||||
foreach ($records as $record) {
|
||||
$connection->table('Groups')->insert([
|
||||
'Name' => $record->name,
|
||||
'UID' => $record->id,
|
||||
]);
|
||||
}
|
||||
|
||||
$records = $connection
|
||||
->table('privileges_new')
|
||||
->get();
|
||||
foreach ($records as $record) {
|
||||
$connection->table('Privileges')->insert([
|
||||
'id' => $record->id,
|
||||
'name' => $record->name,
|
||||
'desc' => $record->description,
|
||||
]);
|
||||
}
|
||||
|
||||
$records = $connection
|
||||
->table('users_groups')
|
||||
->get();
|
||||
foreach ($records as $record) {
|
||||
$connection->table('UserGroups')->insert([
|
||||
'id' => $record->id,
|
||||
'uid' => $record->user_id,
|
||||
'group_id' => $record->group_id,
|
||||
]);
|
||||
}
|
||||
|
||||
$records = $connection
|
||||
->table('group_privileges')
|
||||
->get();
|
||||
foreach ($records as $record) {
|
||||
$connection->table('GroupPrivileges')->insert([
|
||||
'id' => $record->id,
|
||||
'group_id' => $record->group_id,
|
||||
'privilege_id' => $record->privilege_id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,47 +11,56 @@ trait Reference
|
|||
/**
|
||||
* @param Blueprint $table
|
||||
* @param bool $setPrimary
|
||||
* @return ColumnDefinition
|
||||
*/
|
||||
protected function referencesUser(Blueprint $table, bool $setPrimary = false)
|
||||
protected function referencesUser(Blueprint $table, bool $setPrimary = false): ColumnDefinition
|
||||
{
|
||||
$this->references($table, 'users', null, $setPrimary);
|
||||
return $this->references($table, 'users', null, null, $setPrimary);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Blueprint $table
|
||||
* @param string $targetTable
|
||||
* @param string|null $fromColumn
|
||||
* @param string|null $targetColumn
|
||||
* @param bool $setPrimary
|
||||
*
|
||||
* @param string $type
|
||||
* @return ColumnDefinition
|
||||
*/
|
||||
protected function references(
|
||||
Blueprint $table,
|
||||
string $targetTable,
|
||||
?string $fromColumn = null,
|
||||
bool $setPrimary = false
|
||||
?string $targetColumn = null,
|
||||
bool $setPrimary = false,
|
||||
string $type = 'unsignedInteger'
|
||||
): ColumnDefinition {
|
||||
$fromColumn = $fromColumn ?? Str::singular($targetTable) . '_id';
|
||||
$col = $table->unsignedInteger($fromColumn);
|
||||
$col = $table->{$type}($fromColumn);
|
||||
|
||||
if ($setPrimary) {
|
||||
$table->primary($fromColumn);
|
||||
}
|
||||
|
||||
$this->addReference($table, $fromColumn, $targetTable);
|
||||
$this->addReference($table, $fromColumn, $targetTable, $targetColumn ?: 'id');
|
||||
|
||||
return $col;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Blueprint $table
|
||||
* @param string $fromColumn
|
||||
* @param string $targetTable
|
||||
* @param Blueprint $table
|
||||
* @param string $fromColumn
|
||||
* @param string $targetTable
|
||||
* @param string|null $targetColumn
|
||||
*/
|
||||
protected function addReference(Blueprint $table, string $fromColumn, string $targetTable)
|
||||
{
|
||||
protected function addReference(
|
||||
Blueprint $table,
|
||||
string $fromColumn,
|
||||
string $targetTable,
|
||||
?string $targetColumn = null
|
||||
) {
|
||||
$table->foreign($fromColumn)
|
||||
->references('id')->on($targetTable)
|
||||
->references($targetColumn ?: 'id')->on($targetTable)
|
||||
->onUpdate('cascade')
|
||||
->onDelete('cascade');
|
||||
}
|
||||
|
|
|
@ -251,7 +251,7 @@ function user_controller()
|
|||
auth()->can('admin_user'),
|
||||
User_is_freeloader($user_source),
|
||||
User_angeltypes($user_source->id),
|
||||
User_groups($user_source->id),
|
||||
$user_source->groups,
|
||||
$shifts,
|
||||
$user->id == $user_source->id,
|
||||
$tshirt_score,
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
$includeFiles = [
|
||||
__DIR__ . '/../includes/sys_auth.php',
|
||||
__DIR__ . '/../includes/sys_form.php',
|
||||
__DIR__ . '/../includes/sys_log.php',
|
||||
__DIR__ . '/../includes/sys_menu.php',
|
||||
|
@ -22,7 +21,6 @@ $includeFiles = [
|
|||
__DIR__ . '/../includes/model/ShiftTypes_model.php',
|
||||
__DIR__ . '/../includes/model/Stats.php',
|
||||
__DIR__ . '/../includes/model/UserAngelTypes_model.php',
|
||||
__DIR__ . '/../includes/model/UserGroups_model.php',
|
||||
__DIR__ . '/../includes/model/User_model.php',
|
||||
__DIR__ . '/../includes/model/UserWorkLog_model.php',
|
||||
__DIR__ . '/../includes/model/ValidationResult.php',
|
||||
|
|
|
@ -78,7 +78,7 @@ function User_is_AngelType_supporter($user, $angeltype)
|
|||
return false;
|
||||
}
|
||||
|
||||
$privileges = privileges_for_user($user->id);
|
||||
$privileges = $user->privileges->pluck('name')->toArray();
|
||||
|
||||
return (count(Db::select(
|
||||
'
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Engelsystem\Database\Db;
|
||||
|
||||
/**
|
||||
* Returns users groups
|
||||
*
|
||||
* @param int $userId
|
||||
* @return array[]
|
||||
*/
|
||||
function User_groups($userId)
|
||||
{
|
||||
return Db::select(
|
||||
'
|
||||
SELECT `Groups`.*
|
||||
FROM `UserGroups`
|
||||
JOIN `Groups` ON `Groups`.`UID`=`UserGroups`.`group_id`
|
||||
WHERE `UserGroups`.`uid`=?
|
||||
ORDER BY `UserGroups`.`group_id`
|
||||
',
|
||||
[$userId]
|
||||
);
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
<?php
|
||||
|
||||
use Engelsystem\Database\Db;
|
||||
use Engelsystem\Models\Group;
|
||||
use Engelsystem\Models\Privilege;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
|
@ -17,18 +20,14 @@ function admin_groups()
|
|||
{
|
||||
$html = '';
|
||||
$request = request();
|
||||
$groups = Db::select('SELECT * FROM `Groups` ORDER BY `Name`');
|
||||
/** @var Group[]|Collection $groups */
|
||||
$groups = Group::query()->orderBy('name')->get();
|
||||
|
||||
if (!$request->has('action')) {
|
||||
$groups_table = [];
|
||||
foreach ($groups as $group) {
|
||||
$privileges = Db::select('
|
||||
SELECT `name`
|
||||
FROM `GroupPrivileges`
|
||||
JOIN `Privileges` ON (`GroupPrivileges`.`privilege_id` = `Privileges`.`id`)
|
||||
WHERE `group_id`=?
|
||||
ORDER BY `name`
|
||||
', [$group['UID']]);
|
||||
/** @var Privilege[]|Collection $privileges */
|
||||
$privileges = $group->privileges()->orderBy('name')->get();
|
||||
$privileges_html = [];
|
||||
|
||||
foreach ($privileges as $privilege) {
|
||||
|
@ -36,12 +35,12 @@ function admin_groups()
|
|||
}
|
||||
|
||||
$groups_table[] = [
|
||||
'name' => $group['Name'],
|
||||
'name' => $group->name,
|
||||
'privileges' => join(', ', $privileges_html),
|
||||
'actions' => button(
|
||||
page_link_to(
|
||||
'admin_groups',
|
||||
['action' => 'edit', 'id' => $group['UID']]
|
||||
['action' => 'edit', 'id' => $group->id]
|
||||
),
|
||||
__('edit'),
|
||||
'btn-sm'
|
||||
|
@ -65,34 +64,26 @@ function admin_groups()
|
|||
return error('Incomplete call, missing Groups ID.', true);
|
||||
}
|
||||
|
||||
$group = Db::select('SELECT * FROM `Groups` WHERE `UID`=? LIMIT 1', [$group_id]);
|
||||
/** @var Group|null $group */
|
||||
$group = Group::find($group_id);
|
||||
if (!empty($group)) {
|
||||
$privileges = Db::select('
|
||||
SELECT `Privileges`.*, `GroupPrivileges`.`group_id`
|
||||
FROM `Privileges`
|
||||
LEFT OUTER JOIN `GroupPrivileges`
|
||||
ON (
|
||||
`Privileges`.`id` = `GroupPrivileges`.`privilege_id`
|
||||
AND `GroupPrivileges`.`group_id`=?
|
||||
)
|
||||
ORDER BY `Privileges`.`name`
|
||||
', [$group_id]);
|
||||
$privileges = groupPrivilegesWithSelected($group);
|
||||
$privileges_form = [];
|
||||
foreach ($privileges as $privilege) {
|
||||
$privileges_form[] = form_checkbox(
|
||||
'privileges[]',
|
||||
$privilege['desc'] . ' (' . $privilege['name'] . ')',
|
||||
$privilege['group_id'] != '',
|
||||
$privilege['id'],
|
||||
'privilege-' . $privilege['name']
|
||||
$privilege->description . ' (' . $privilege->name . ')',
|
||||
$privilege->selected != '',
|
||||
$privilege->id,
|
||||
'privilege-' . $privilege->name
|
||||
);
|
||||
}
|
||||
|
||||
$privileges_form[] = form_submit('submit', __('Save'));
|
||||
$html .= page_with_title(__('Edit group'), [
|
||||
$html .= page_with_title(__('Edit group') . ' ' . $group->name, [
|
||||
form(
|
||||
$privileges_form,
|
||||
page_link_to('admin_groups', ['action' => 'save', 'id' => $group_id])
|
||||
page_link_to('admin_groups', ['action' => 'save', 'id' => $group->id])
|
||||
)
|
||||
]);
|
||||
} else {
|
||||
|
@ -110,29 +101,21 @@ function admin_groups()
|
|||
return error('Incomplete call, missing Groups ID.', true);
|
||||
}
|
||||
|
||||
$group = Db::selectOne('SELECT * FROM `Groups` WHERE `UID`=? LIMIT 1', [$group_id]);
|
||||
/** @var Group|null $group */
|
||||
$group = Group::find($group_id);
|
||||
$privileges = $request->request->all('privileges');
|
||||
if (!empty($group)) {
|
||||
Db::delete('DELETE FROM `GroupPrivileges` WHERE `group_id`=?', [$group_id]);
|
||||
$group->privileges()->detach();
|
||||
$privilege_names = [];
|
||||
foreach ($privileges as $privilege) {
|
||||
$privilege = (int)$privilege;
|
||||
$privilege = Privilege::find($privilege);
|
||||
if ($privilege) {
|
||||
$group_privileges_source = Db::selectOne(
|
||||
'SELECT `name` FROM `Privileges` WHERE `id`=? LIMIT 1',
|
||||
[$privilege]
|
||||
);
|
||||
if (!empty($group_privileges_source)) {
|
||||
Db::insert(
|
||||
'INSERT INTO `GroupPrivileges` (`group_id`, `privilege_id`) VALUES (?, ?)',
|
||||
[$group_id, $privilege]
|
||||
);
|
||||
$privilege_names[] = $group_privileges_source['name'];
|
||||
}
|
||||
$group->privileges()->attach($privilege);
|
||||
$privilege_names[] = $privilege->name;
|
||||
}
|
||||
}
|
||||
engelsystem_log(
|
||||
'Group privileges of group ' . $group['Name']
|
||||
'Group privileges of group ' . $group->name
|
||||
. ' edited: ' . join(', ', $privilege_names)
|
||||
);
|
||||
throw_redirect(page_link_to('admin_groups'));
|
||||
|
@ -144,3 +127,24 @@ function admin_groups()
|
|||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Group $group
|
||||
* @return Collection|Privilege[]
|
||||
*/
|
||||
function groupPrivilegesWithSelected(Group $group): Collection
|
||||
{
|
||||
return Privilege::query()
|
||||
->join('group_privileges', function ($query) use ($group) {
|
||||
/** @var JoinClause $query */
|
||||
$query
|
||||
->where('privileges.id', '=', $query->raw('group_privileges.privilege_id'))
|
||||
->where('group_privileges.group_id', $group->id)
|
||||
;
|
||||
}, null, null, 'left outer')
|
||||
->orderBy('name')
|
||||
->get([
|
||||
'privileges.*',
|
||||
'group_privileges.group_id as selected'
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<?php
|
||||
|
||||
use Engelsystem\Database\DB;
|
||||
use Engelsystem\Models\Group;
|
||||
use Engelsystem\Models\User\User;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
|
@ -126,20 +128,15 @@ function admin_user()
|
|||
|
||||
$html .= '<hr />';
|
||||
|
||||
$my_highest_group = DB::selectOne(
|
||||
'SELECT group_id FROM `UserGroups` WHERE `uid`=? ORDER BY `group_id` DESC LIMIT 1',
|
||||
[$user->id]
|
||||
);
|
||||
/** @var Group $my_highest_group */
|
||||
$my_highest_group = $user->groups()->orderByDesc('id')->first();
|
||||
if (!empty($my_highest_group)) {
|
||||
$my_highest_group = $my_highest_group['group_id'];
|
||||
$my_highest_group = $my_highest_group->id;
|
||||
}
|
||||
|
||||
$angel_highest_group = DB::selectOne(
|
||||
'SELECT group_id FROM `UserGroups` WHERE `uid`=? ORDER BY `group_id` DESC LIMIT 1',
|
||||
[$user_id]
|
||||
);
|
||||
$angel_highest_group = $user_source->groups()->orderByDesc('id')->first();
|
||||
if (!empty($angel_highest_group)) {
|
||||
$angel_highest_group = $angel_highest_group['group_id'];
|
||||
$angel_highest_group = $angel_highest_group->id;
|
||||
}
|
||||
|
||||
if (
|
||||
|
@ -152,26 +149,11 @@ function admin_user()
|
|||
$html .= form_csrf();
|
||||
$html .= '<table>';
|
||||
|
||||
$groups = DB::select(
|
||||
'
|
||||
SELECT *
|
||||
FROM `Groups`
|
||||
LEFT OUTER JOIN `UserGroups` ON (
|
||||
`UserGroups`.`group_id` = `Groups`.`UID`
|
||||
AND `UserGroups`.`uid` = ?
|
||||
)
|
||||
WHERE `Groups`.`UID` <= ?
|
||||
ORDER BY `Groups`.`Name`
|
||||
',
|
||||
[
|
||||
$user_id,
|
||||
$my_highest_group,
|
||||
]
|
||||
);
|
||||
$groups = changeableGroups($my_highest_group, $user_id);
|
||||
foreach ($groups as $group) {
|
||||
$html .= '<tr><td><input type="checkbox" name="groups[]" value="' . $group['UID'] . '" '
|
||||
. ($group['group_id'] != '' ? ' checked="checked"' : '')
|
||||
. ' /></td><td>' . $group['Name'] . '</td></tr>';
|
||||
$html .= '<tr><td><input type="checkbox" name="groups[]" value="' . $group->id . '" '
|
||||
. ($group->selected ? ' checked="checked"' : '')
|
||||
. ' /></td><td>' . $group->name . '</td></tr>';
|
||||
}
|
||||
|
||||
$html .= '</table><br>';
|
||||
|
@ -190,44 +172,26 @@ function admin_user()
|
|||
} else {
|
||||
switch ($request->input('action')) {
|
||||
case 'save_groups':
|
||||
if ($user_id != $user->id || auth()->can('admin_groups')) {
|
||||
$my_highest_group = DB::selectOne(
|
||||
'SELECT * FROM `UserGroups` WHERE `uid`=? ORDER BY `group_id` DESC LIMIT 1',
|
||||
[$user->id]
|
||||
);
|
||||
$angel_highest_group = DB::selectOne(
|
||||
'SELECT * FROM `UserGroups` WHERE `uid`=? ORDER BY `group_id` DESC LIMIT 1',
|
||||
[$user_id]
|
||||
);
|
||||
$angel = User::findOrFail($user_id);
|
||||
if ($angel->id != $user->id || auth()->can('admin_groups')) {
|
||||
/** @var Group $my_highest_group */
|
||||
$my_highest_group = $user->groups()->orderByDesc('id')->first();
|
||||
/** @var Group $angel_highest_group */
|
||||
$angel_highest_group = $angel->groups()->orderByDesc('id')->first();
|
||||
|
||||
if (
|
||||
$my_highest_group
|
||||
&& (
|
||||
empty($angel_highest_group)
|
||||
|| ($my_highest_group['group_id'] >= $angel_highest_group['group_id'])
|
||||
|| ($my_highest_group->id >= $angel_highest_group->id)
|
||||
)
|
||||
) {
|
||||
$groups_source = DB::select(
|
||||
'
|
||||
SELECT *
|
||||
FROM `Groups`
|
||||
LEFT OUTER JOIN `UserGroups` ON (
|
||||
`UserGroups`.`group_id` = `Groups`.`UID`
|
||||
AND `UserGroups`.`uid` = ?
|
||||
)
|
||||
WHERE `Groups`.`UID` <= ?
|
||||
ORDER BY `Groups`.`Name`
|
||||
',
|
||||
[
|
||||
$user_id,
|
||||
$my_highest_group['group_id'],
|
||||
]
|
||||
);
|
||||
$groups_source = changeableGroups($my_highest_group->id, $angel->id);
|
||||
$groups = [];
|
||||
$grouplist = [];
|
||||
$groupList = [];
|
||||
foreach ($groups_source as $group) {
|
||||
$groups[$group['UID']] = $group;
|
||||
$grouplist[] = $group['UID'];
|
||||
$groups[$group->id] = $group;
|
||||
$groupList[] = $group->id;
|
||||
}
|
||||
|
||||
$groupsRequest = $request->input('groups');
|
||||
|
@ -235,20 +199,17 @@ function admin_user()
|
|||
$groupsRequest = [];
|
||||
}
|
||||
|
||||
DB::delete('DELETE FROM `UserGroups` WHERE `uid`=?', [$user_id]);
|
||||
$angel->groups()->detach();
|
||||
$user_groups_info = [];
|
||||
foreach ($groupsRequest as $group) {
|
||||
if (in_array($group, $grouplist)) {
|
||||
DB::insert(
|
||||
'INSERT INTO `UserGroups` (`uid`, `group_id`) VALUES (?, ?)',
|
||||
[$user_id, $group]
|
||||
);
|
||||
$user_groups_info[] = $groups[$group]['Name'];
|
||||
if (in_array($group, $groupList)) {
|
||||
$group = $groups[$group];
|
||||
$angel->groups()->attach($group);
|
||||
$user_groups_info[] = $group->name;
|
||||
}
|
||||
}
|
||||
$user_source = User::find($user_id);
|
||||
engelsystem_log(
|
||||
'Set groups of ' . User_Nick_render($user_source, true) . ' to: '
|
||||
'Set groups of ' . User_Nick_render($angel, true) . ' to: '
|
||||
. join(', ', $user_groups_info)
|
||||
);
|
||||
$html .= success('Benutzergruppen gespeichert.', true);
|
||||
|
@ -321,3 +282,24 @@ function admin_user()
|
|||
$html
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $myHighestGroup
|
||||
* @param $angelId
|
||||
* @return Collection|Group[]
|
||||
*/
|
||||
function changeableGroups($myHighestGroup, $angelId): Collection
|
||||
{
|
||||
return Group::query()
|
||||
->where('groups.id', '<=', $myHighestGroup)
|
||||
->join('users_groups', function ($query) use ($angelId) {
|
||||
/** @var JoinClause $query */
|
||||
$query->where('users_groups.group_id', '=', $query->raw('groups.id'))
|
||||
->where('users_groups.user_id', $angelId);
|
||||
}, null, null, 'left outer')
|
||||
->orderBy('name')
|
||||
->get([
|
||||
'groups.*',
|
||||
'users_groups.group_id as selected'
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use Carbon\Carbon;
|
|||
use Engelsystem\Database\Database;
|
||||
use Engelsystem\Database\Db;
|
||||
use Engelsystem\Events\Listener\OAuth2;
|
||||
use Engelsystem\Models\Group;
|
||||
use Engelsystem\Models\OAuth;
|
||||
use Engelsystem\Models\User\Contact;
|
||||
use Engelsystem\Models\User\PersonalData;
|
||||
|
@ -299,7 +300,8 @@ function guest_register()
|
|||
}
|
||||
|
||||
// Assign user-group and set password
|
||||
Db::insert('INSERT INTO `UserGroups` (`uid`, `group_id`) VALUES (?, 20)', [$user->id]);
|
||||
$defaultGroup = Group::find(auth()->getDefaultRole());
|
||||
$user->groups()->attach($defaultGroup);
|
||||
if ($enable_password) {
|
||||
auth()->setPassword($user, $request->postData('password'));
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Engelsystem\Database\Db;
|
||||
|
||||
/**
|
||||
* @param int $user_id
|
||||
* @return array
|
||||
*/
|
||||
function privileges_for_user($user_id)
|
||||
{
|
||||
$privileges = [];
|
||||
$user_privileges = Db::select('
|
||||
SELECT `Privileges`.`name`
|
||||
FROM `users`
|
||||
JOIN `UserGroups` ON (`users`.`id` = `UserGroups`.`uid`)
|
||||
JOIN `GroupPrivileges` ON (`UserGroups`.`group_id` = `GroupPrivileges`.`group_id`)
|
||||
JOIN `Privileges` ON (`GroupPrivileges`.`privilege_id` = `Privileges`.`id`)
|
||||
WHERE `users`.`id`=?
|
||||
', [$user_id]);
|
||||
foreach ($user_privileges as $user_privilege) {
|
||||
$privileges[] = $user_privilege['name'];
|
||||
}
|
||||
return $privileges;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $group_id
|
||||
* @return array
|
||||
*/
|
||||
function privileges_for_group($group_id)
|
||||
{
|
||||
$privileges = [];
|
||||
$groups_privileges = Db::select('
|
||||
SELECT `name`
|
||||
FROM `GroupPrivileges`
|
||||
JOIN `Privileges` ON (`GroupPrivileges`.`privilege_id` = `Privileges`.`id`)
|
||||
WHERE `group_id`=?
|
||||
', [$group_id]);
|
||||
foreach ($groups_privileges as $guest_privilege) {
|
||||
$privileges[] = $guest_privilege['name'];
|
||||
}
|
||||
return $privileges;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Engelsystem\Models\Group;
|
||||
use Engelsystem\Models\Room;
|
||||
use Engelsystem\Models\User\User;
|
||||
use Engelsystem\Models\Worklog;
|
||||
|
@ -431,7 +432,7 @@ function User_view_worklog(Worklog $worklog, $admin_user_worklog_privilege)
|
|||
* @param bool $admin_user_privilege
|
||||
* @param bool $freeloader
|
||||
* @param array[] $user_angeltypes
|
||||
* @param array[] $user_groups
|
||||
* @param Group[] $user_groups
|
||||
* @param array[] $shifts
|
||||
* @param bool $its_me
|
||||
* @param int $tshirt_score
|
||||
|
@ -734,14 +735,14 @@ function User_angeltypes_render($user_angeltypes)
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array[] $user_groups
|
||||
* @param Group[] $user_groups
|
||||
* @return string
|
||||
*/
|
||||
function User_groups_render($user_groups)
|
||||
{
|
||||
$output = [];
|
||||
foreach ($user_groups as $group) {
|
||||
$output[] = __($group['Name']);
|
||||
$output[] = __($group->name);
|
||||
}
|
||||
|
||||
return div('col-md-2', [
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Engelsystem\Helpers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Engelsystem\Models\Group;
|
||||
use Engelsystem\Models\User\User;
|
||||
use Engelsystem\Models\User\User as UserRepository;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
@ -10,26 +11,29 @@ use Symfony\Component\HttpFoundation\Session\Session;
|
|||
|
||||
class Authenticator
|
||||
{
|
||||
/** @var User */
|
||||
protected $user = null;
|
||||
/** @var User|null */
|
||||
protected ?User $user = null;
|
||||
|
||||
/** @var ServerRequestInterface */
|
||||
protected $request;
|
||||
protected ServerRequestInterface $request;
|
||||
|
||||
/** @var Session */
|
||||
protected $session;
|
||||
protected Session $session;
|
||||
|
||||
/** @var UserRepository */
|
||||
protected $userRepository;
|
||||
protected UserRepository $userRepository;
|
||||
|
||||
/** @var string[] */
|
||||
protected $permissions;
|
||||
protected array $permissions = [];
|
||||
|
||||
/** @var int|string|null */
|
||||
protected $passwordAlgorithm = PASSWORD_DEFAULT;
|
||||
|
||||
/** @var int */
|
||||
protected $guestRole = 10;
|
||||
protected int $defaultRole = 20;
|
||||
|
||||
/** @var int */
|
||||
protected int $guestRole = 10;
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
|
@ -48,7 +52,7 @@ class Authenticator
|
|||
*
|
||||
* @return User|null
|
||||
*/
|
||||
public function user()
|
||||
public function user(): ?User
|
||||
{
|
||||
if ($this->user) {
|
||||
return $this->user;
|
||||
|
@ -77,7 +81,7 @@ class Authenticator
|
|||
* @param string $parameter
|
||||
* @return User|null
|
||||
*/
|
||||
public function apiUser($parameter = 'api_key')
|
||||
public function apiUser(string $parameter = 'api_key'): ?User
|
||||
{
|
||||
if ($this->user) {
|
||||
return $this->user;
|
||||
|
@ -88,6 +92,7 @@ class Authenticator
|
|||
return null;
|
||||
}
|
||||
|
||||
/** @var User|null $user */
|
||||
$user = $this
|
||||
->userRepository
|
||||
->whereApiKey($params[$parameter])
|
||||
|
@ -113,7 +118,7 @@ class Authenticator
|
|||
$user = $this->user();
|
||||
|
||||
if ($user) {
|
||||
$this->permissions = $this->getPermissionsByUser($user);
|
||||
$this->permissions = $user->privileges->pluck('name')->toArray();
|
||||
|
||||
$user->last_login_at = new Carbon();
|
||||
$user->save();
|
||||
|
@ -122,7 +127,9 @@ class Authenticator
|
|||
}
|
||||
|
||||
if (empty($this->permissions)) {
|
||||
$this->permissions = $this->getPermissionsByGroup($this->guestRole);
|
||||
/** @var Group $group */
|
||||
$group = Group::find($this->guestRole);
|
||||
$this->permissions = $group->privileges->pluck('name')->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +147,7 @@ class Authenticator
|
|||
* @param string $password
|
||||
* @return User|null
|
||||
*/
|
||||
public function authenticate(string $login, string $password)
|
||||
public function authenticate(string $login, string $password): ?User
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->userRepository->whereName($login)->first();
|
||||
|
@ -164,7 +171,7 @@ class Authenticator
|
|||
* @param string $password
|
||||
* @return bool
|
||||
*/
|
||||
public function verifyPassword(User $user, string $password)
|
||||
public function verifyPassword(User $user, string $password): bool
|
||||
{
|
||||
if (!password_verify($password, $user->password)) {
|
||||
return false;
|
||||
|
@ -206,7 +213,23 @@ class Authenticator
|
|||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getGuestRole()
|
||||
public function getDefaultRole(): int
|
||||
{
|
||||
return $this->defaultRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $defaultRole
|
||||
*/
|
||||
public function setDefaultRole(int $defaultRole)
|
||||
{
|
||||
$this->defaultRole = $defaultRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getGuestRole(): int
|
||||
{
|
||||
return $this->guestRole;
|
||||
}
|
||||
|
@ -218,24 +241,4 @@ class Authenticator
|
|||
{
|
||||
$this->guestRole = $guestRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @return array
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function getPermissionsByUser($user)
|
||||
{
|
||||
return privileges_for_user($user->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $groupId
|
||||
* @return array
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function getPermissionsByGroup(int $groupId)
|
||||
{
|
||||
return privileges_for_group($groupId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ class AuthenticatorServiceProvider extends ServiceProvider
|
|||
$authenticator = $this->app->make(Authenticator::class);
|
||||
$authenticator->setPasswordAlgorithm($config->get('password_algorithm'));
|
||||
$authenticator->setGuestRole($config->get('auth_guest_role', $authenticator->getGuestRole()));
|
||||
$authenticator->setDefaultRole($config->get('auth_default_role', $authenticator->getDefaultRole()));
|
||||
|
||||
$this->app->instance(Authenticator::class, $authenticator);
|
||||
$this->app->instance('authenticator', $authenticator);
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Models;
|
||||
|
||||
use Engelsystem\Models\User\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
*
|
||||
* @property-read Collection|Privilege[] $privileges
|
||||
* @property-read Collection|User[] $users
|
||||
*
|
||||
* @method static Builder|Group whereId($value)
|
||||
* @method static Builder|Group whereName($value)
|
||||
*/
|
||||
class Group extends BaseModel
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/** @var string[] */
|
||||
protected $fillable = [
|
||||
'name',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function privileges(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Privilege::class, 'group_privileges');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function users(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(User::class, 'users_groups');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $description
|
||||
*
|
||||
* @property-read Collection|Group[] $groups
|
||||
*
|
||||
* @method static Builder|Privilege whereId($value)
|
||||
* @method static Builder|Privilege whereName($value)
|
||||
* @method static Builder|Privilege whereDescription($value)
|
||||
*/
|
||||
class Privilege extends BaseModel
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/** @var string[] */
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function groups(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Group::class, 'group_privileges');
|
||||
}
|
||||
}
|
|
@ -4,43 +4,51 @@ namespace Engelsystem\Models\User;
|
|||
|
||||
use Carbon\Carbon;
|
||||
use Engelsystem\Models\BaseModel;
|
||||
use Engelsystem\Models\Group;
|
||||
use Engelsystem\Models\Message;
|
||||
use Engelsystem\Models\News;
|
||||
use Engelsystem\Models\NewsComment;
|
||||
use Engelsystem\Models\OAuth;
|
||||
use Engelsystem\Models\Privilege;
|
||||
use Engelsystem\Models\Question;
|
||||
use Engelsystem\Models\Worklog;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||
use Illuminate\Support\Collection as SupportCollection;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $email
|
||||
* @property string $password
|
||||
* @property string $api_key
|
||||
* @property Carbon|null $last_login_at
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $updated_at
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $email
|
||||
* @property string $password
|
||||
* @property string $api_key
|
||||
* @property Carbon|null $last_login_at
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $updated_at
|
||||
*
|
||||
* @property-read QueryBuilder|Contact $contact
|
||||
* @property-read QueryBuilder|License $license
|
||||
* @property-read QueryBuilder|PersonalData $personalData
|
||||
* @property-read QueryBuilder|Settings $settings
|
||||
* @property-read QueryBuilder|State $state
|
||||
* @property-read Collection|News[] $news
|
||||
* @property-read Collection|NewsComment[] $newsComments
|
||||
* @property-read Collection|OAuth[] $oauth
|
||||
* @property-read Collection|Worklog[] $worklogs
|
||||
* @property-read Collection|Worklog[] $worklogsCreated
|
||||
* @property-read int|null $news_count
|
||||
* @property-read int|null $news_comments_count
|
||||
* @property-read int|null $oauth_count
|
||||
* @property-read int|null $worklogs_count
|
||||
* @property-read int|null $worklogs_created_count
|
||||
* @property-read QueryBuilder|Contact $contact
|
||||
* @property-read QueryBuilder|License $license
|
||||
* @property-read QueryBuilder|PersonalData $personalData
|
||||
* @property-read QueryBuilder|Settings $settings
|
||||
* @property-read QueryBuilder|State $state
|
||||
*
|
||||
* @property-read Collection|Group[] $groups
|
||||
* @property-read Collection|News[] $news
|
||||
* @property-read Collection|NewsComment[] $newsComments
|
||||
* @property-read Collection|OAuth[] $oauth
|
||||
* @property-read SupportCollection|Privilege[] $privileges
|
||||
* @property-read Collection|Worklog[] $worklogs
|
||||
* @property-read Collection|Worklog[] $worklogsCreated
|
||||
* @property-read Collection|Question[] $questionsAsked
|
||||
* @property-read Collection|Question[] $questionsAnswered
|
||||
* @property-read Collection|Message[] $messagesReceived
|
||||
* @property-read Collection|Message[] $messagesSent
|
||||
* @property-read Collection|Message[] $messages
|
||||
*
|
||||
* @method static QueryBuilder|User[] whereId($value)
|
||||
* @method static QueryBuilder|User[] whereName($value)
|
||||
|
@ -50,12 +58,6 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
|
|||
* @method static QueryBuilder|User[] whereLastLoginAt($value)
|
||||
* @method static QueryBuilder|User[] whereCreatedAt($value)
|
||||
* @method static QueryBuilder|User[] whereUpdatedAt($value)
|
||||
*
|
||||
* @property-read Collection|Question[] $questionsAsked
|
||||
* @property-read Collection|Question[] $questionsAnswered
|
||||
* @property-read Collection|Message[] $messagesReceived
|
||||
* @property-read Collection|Message[] $messagesSent
|
||||
* @property-read Collection|Message[] $messages
|
||||
*/
|
||||
class User extends BaseModel
|
||||
{
|
||||
|
@ -94,6 +96,14 @@ class User extends BaseModel
|
|||
->withDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function groups(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Group::class, 'users_groups');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne
|
||||
*/
|
||||
|
@ -104,6 +114,33 @@ class User extends BaseModel
|
|||
->withDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder
|
||||
*/
|
||||
public function privileges(): Builder
|
||||
{
|
||||
/** @var Builder $builder */
|
||||
$builder = Privilege::query()
|
||||
->whereIn('id', function ($query) {
|
||||
/** @var QueryBuilder $query */
|
||||
$query->select('privilege_id')
|
||||
->from('group_privileges')
|
||||
->join('users_groups', 'users_groups.group_id', '=', 'group_privileges.group_id')
|
||||
->where('users_groups.user_id', '=', $this->id)
|
||||
->distinct();
|
||||
});
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SupportCollection
|
||||
*/
|
||||
public function getPrivilegesAttribute(): SupportCollection
|
||||
{
|
||||
return $this->privileges()->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne
|
||||
*/
|
||||
|
|
|
@ -7,6 +7,7 @@ use Engelsystem\Controllers\HomeController;
|
|||
use Engelsystem\Helpers\Authenticator;
|
||||
use Engelsystem\Http\Redirector;
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Models\User\User;
|
||||
use Engelsystem\Test\Unit\TestCase;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
|
@ -21,7 +22,7 @@ class HomeControllerTest extends TestCase
|
|||
$config = new Config(['home_site' => '/foo']);
|
||||
/** @var Authenticator|MockObject $auth */
|
||||
$auth = $this->createMock(Authenticator::class);
|
||||
$this->setExpects($auth, 'user', null, true);
|
||||
$this->setExpects($auth, 'user', null, new User());
|
||||
/** @var Redirector|MockObject $redirect */
|
||||
$redirect = $this->createMock(Redirector::class);
|
||||
$this->setExpects($redirect, 'to', ['/foo'], new Response());
|
||||
|
|
|
@ -20,9 +20,11 @@ class AuthenticatorServiceProviderTest extends ServiceProviderTest
|
|||
$app = new Application();
|
||||
$app->bind(ServerRequestInterface::class, Request::class);
|
||||
|
||||
$config = new Config();
|
||||
$config->set('password_algorithm', PASSWORD_DEFAULT);
|
||||
$config->set('auth_guest_role', 42);
|
||||
$config = new Config([
|
||||
'password_algorithm' => PASSWORD_DEFAULT,
|
||||
'auth_guest_role' => 42,
|
||||
'auth_default_role' => 1337,
|
||||
]);
|
||||
$app->instance('config', $config);
|
||||
|
||||
$serviceProvider = new AuthenticatorServiceProvider($app);
|
||||
|
@ -36,5 +38,6 @@ class AuthenticatorServiceProviderTest extends ServiceProviderTest
|
|||
$auth = $app->get(Authenticator::class);
|
||||
$this->assertEquals(PASSWORD_DEFAULT, $auth->getPasswordAlgorithm());
|
||||
$this->assertEquals(42, $auth->getGuestRole());
|
||||
$this->assertEquals(1337, $auth->getDefaultRole());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
namespace Engelsystem\Test\Unit\Helpers;
|
||||
|
||||
use Engelsystem\Helpers\Authenticator;
|
||||
use Engelsystem\Models\Group;
|
||||
use Engelsystem\Models\Privilege;
|
||||
use Engelsystem\Models\User\User;
|
||||
use Engelsystem\Test\Unit\HasDatabase;
|
||||
use Engelsystem\Test\Unit\Helpers\Stub\UserModelImplementation;
|
||||
|
@ -108,14 +110,23 @@ class AuthenticatorTest extends ServiceProviderTest
|
|||
*/
|
||||
public function testCan()
|
||||
{
|
||||
$this->initDatabase();
|
||||
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
||||
/** @var Session|MockObject $session */
|
||||
$session = $this->createMock(Session::class);
|
||||
/** @var UserModelImplementation|MockObject $userRepository */
|
||||
$userRepository = new UserModelImplementation();
|
||||
/** @var User|MockObject $user */
|
||||
$user = $this->createMock(User::class);
|
||||
/** @var User $user */
|
||||
$user = User::factory()->create();
|
||||
/** @var Group $group */
|
||||
$group = Group::factory()->create();
|
||||
/** @var Privilege $privilege */
|
||||
$privilege = Privilege::factory()->create(['name' => 'bar']);
|
||||
|
||||
$user->groups()->attach($group);
|
||||
$group->privileges()->attach($privilege);
|
||||
|
||||
$session->expects($this->once())
|
||||
->method('get')
|
||||
|
@ -128,20 +139,14 @@ class AuthenticatorTest extends ServiceProviderTest
|
|||
/** @var Authenticator|MockObject $auth */
|
||||
$auth = $this->getMockBuilder(Authenticator::class)
|
||||
->setConstructorArgs([$request, $session, $userRepository])
|
||||
->onlyMethods(['getPermissionsByGroup', 'getPermissionsByUser', 'user'])
|
||||
->onlyMethods(['user'])
|
||||
->getMock();
|
||||
$auth->expects($this->exactly(1))
|
||||
->method('getPermissionsByGroup')
|
||||
->with(10)
|
||||
->willReturn([]);
|
||||
$auth->expects($this->exactly(1))
|
||||
->method('getPermissionsByUser')
|
||||
->with($user)
|
||||
->willReturn(['bar']);
|
||||
$auth->expects($this->exactly(2))
|
||||
->method('user')
|
||||
->willReturnOnConsecutiveCalls(null, $user);
|
||||
|
||||
Group::factory()->create(['id' => $auth->getGuestRole()]);
|
||||
|
||||
// No user, no permissions
|
||||
$this->assertFalse($auth->can('foo'));
|
||||
|
||||
|
@ -245,6 +250,18 @@ class AuthenticatorTest extends ServiceProviderTest
|
|||
$this->assertEquals(PASSWORD_ARGON2I, $auth->getPasswordAlgorithm());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Authenticator::setDefaultRole
|
||||
* @covers \Engelsystem\Helpers\Authenticator::getDefaultRole
|
||||
*/
|
||||
public function testDefaultRole()
|
||||
{
|
||||
$auth = $this->getAuthenticator();
|
||||
|
||||
$auth->setDefaultRole(1337);
|
||||
$this->assertEquals(1337, $auth->getDefaultRole());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Authenticator::setGuestRole
|
||||
* @covers \Engelsystem\Helpers\Authenticator::getGuestRole
|
||||
|
@ -262,8 +279,7 @@ class AuthenticatorTest extends ServiceProviderTest
|
|||
*/
|
||||
protected function getAuthenticator()
|
||||
{
|
||||
return new class extends Authenticator
|
||||
{
|
||||
return new class extends Authenticator {
|
||||
/** @noinspection PhpMissingParentConstructorInspection */
|
||||
public function __construct()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Test\Unit\Models;
|
||||
|
||||
use Engelsystem\Models\Group;
|
||||
use Engelsystem\Models\Privilege;
|
||||
use Engelsystem\Models\User\User;
|
||||
|
||||
class GroupTest extends ModelTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Models\Group::privileges
|
||||
*/
|
||||
public function testPrivileges(): void
|
||||
{
|
||||
/** @var Privilege $privilege1 */
|
||||
$privilege1 = Privilege::factory()->create();
|
||||
/** @var Privilege $privilege2 */
|
||||
$privilege2 = Privilege::factory()->create();
|
||||
|
||||
$model = new Group();
|
||||
$model->name = 'Some Group';
|
||||
$model->save();
|
||||
|
||||
$model->privileges()->attach($privilege1);
|
||||
$model->privileges()->attach($privilege2);
|
||||
|
||||
/** @var Group $savedModel */
|
||||
$savedModel = Group::first();
|
||||
$this->assertEquals('Some Group', $savedModel->name);
|
||||
$this->assertEquals($privilege1->name, $savedModel->privileges[0]->name);
|
||||
$this->assertEquals($privilege2->name, $savedModel->privileges[1]->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Models\Group::users
|
||||
*/
|
||||
public function testUsers(): void
|
||||
{
|
||||
/** @var User $user1 */
|
||||
$user1 = User::factory()->create();
|
||||
/** @var User $user2 = */
|
||||
$user2 = User::factory()->create();
|
||||
|
||||
$model = new Group();
|
||||
$model->name = 'Some Group';
|
||||
$model->save();
|
||||
|
||||
$model->users()->attach($user1);
|
||||
$model->users()->attach($user2);
|
||||
|
||||
/** @var Group $savedModel */
|
||||
$savedModel = Group::first();
|
||||
$this->assertEquals($user1->name, $savedModel->users[0]->name);
|
||||
$this->assertEquals($user2->name, $savedModel->users[1]->name);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Test\Unit\Models;
|
||||
|
||||
use Engelsystem\Models\Group;
|
||||
use Engelsystem\Models\Privilege;
|
||||
|
||||
class PrivilegeTest extends ModelTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Models\Privilege::groups
|
||||
*/
|
||||
public function testGroups(): void
|
||||
{
|
||||
/** @var Group $group1 */
|
||||
$group1 = Group::factory()->create();
|
||||
/** @var Group $group2 */
|
||||
$group2 = Group::factory()->create();
|
||||
|
||||
$model = new Privilege();
|
||||
$model->name = 'Some Privilege';
|
||||
$model->description = 'Some long description';
|
||||
$model->save();
|
||||
|
||||
$model->groups()->attach($group1);
|
||||
$model->groups()->attach($group2);
|
||||
|
||||
/** @var Privilege $savedModel */
|
||||
$savedModel = Privilege::first();
|
||||
$this->assertEquals('Some Privilege', $savedModel->name);
|
||||
$this->assertEquals('Some long description', $savedModel->description);
|
||||
$this->assertEquals($group1->name, $savedModel->groups[0]->name);
|
||||
$this->assertEquals($group2->name, $savedModel->groups[1]->name);
|
||||
}
|
||||
}
|
|
@ -5,9 +5,11 @@ namespace Engelsystem\Test\Unit\Models\User;
|
|||
use Carbon\Carbon;
|
||||
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
|
||||
use Engelsystem\Models\BaseModel;
|
||||
use Engelsystem\Models\Group;
|
||||
use Engelsystem\Models\News;
|
||||
use Engelsystem\Models\NewsComment;
|
||||
use Engelsystem\Models\OAuth;
|
||||
use Engelsystem\Models\Privilege;
|
||||
use Engelsystem\Models\Question;
|
||||
use Engelsystem\Models\User\Contact;
|
||||
use Engelsystem\Models\User\HasUserModel;
|
||||
|
@ -19,6 +21,7 @@ use Engelsystem\Models\User\User;
|
|||
use Engelsystem\Models\Worklog;
|
||||
use Engelsystem\Test\Unit\Models\ModelTest;
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UserTest extends ModelTest
|
||||
|
@ -81,60 +84,6 @@ class UserTest extends ModelTest
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Models\User\User::contact
|
||||
* @covers \Engelsystem\Models\User\User::license
|
||||
* @covers \Engelsystem\Models\User\User::personalData
|
||||
* @covers \Engelsystem\Models\User\User::settings
|
||||
* @covers \Engelsystem\Models\User\User::state
|
||||
*
|
||||
* @dataProvider hasOneRelationsProvider
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $name
|
||||
* @param array $data
|
||||
* @throws Exception
|
||||
*/
|
||||
public function testHasOneRelations($class, $name, $data)
|
||||
{
|
||||
$user = new User($this->data);
|
||||
$user->save();
|
||||
|
||||
/** @var HasUserModel $contact */
|
||||
$contact = new $class($data);
|
||||
$contact->user()
|
||||
->associate($user)
|
||||
->save();
|
||||
|
||||
$this->assertArraySubset($data, (array)$user->{$name}->attributesToArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Models\User\User::news()
|
||||
*
|
||||
* @dataProvider hasManyRelationsProvider
|
||||
*
|
||||
* @param string $class Class name of the related models
|
||||
* @param string $name Name of the accessor for the related models
|
||||
* @param array $modelData List of the related models
|
||||
*/
|
||||
public function testHasManyRelations(string $class, string $name, array $modelData): void
|
||||
{
|
||||
$user = new User($this->data);
|
||||
$user->save();
|
||||
|
||||
$relatedModelIds = [];
|
||||
|
||||
foreach ($modelData as $data) {
|
||||
/** @var BaseModel $model */
|
||||
$model = $this->app->make($class);
|
||||
$stored = $model->create($data + ['user_id' => $user->id]);
|
||||
$relatedModelIds[] = $stored->id;
|
||||
}
|
||||
|
||||
$this->assertEquals($relatedModelIds, $user->{$name}->modelKeys());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
|
@ -160,6 +109,156 @@ class UserTest extends ModelTest
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function belongsToManyRelationsProvider(): array
|
||||
{
|
||||
return [
|
||||
'groups' => [
|
||||
Group::class,
|
||||
'groups',
|
||||
[
|
||||
[
|
||||
'name' => 'Lorem',
|
||||
],
|
||||
[
|
||||
'name' => 'Ipsum',
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Models\User\User::contact
|
||||
* @covers \Engelsystem\Models\User\User::license
|
||||
* @covers \Engelsystem\Models\User\User::personalData
|
||||
* @covers \Engelsystem\Models\User\User::settings
|
||||
* @covers \Engelsystem\Models\User\User::state
|
||||
*
|
||||
* @dataProvider hasOneRelationsProvider
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $name
|
||||
* @param array $data
|
||||
* @throws Exception
|
||||
*/
|
||||
public function testHasOneRelations($class, $name, $data)
|
||||
{
|
||||
$user = new User($this->data);
|
||||
$user->save();
|
||||
|
||||
/** @var HasUserModel $instance */
|
||||
$instance = new $class($data);
|
||||
$instance->user()
|
||||
->associate($user)
|
||||
->save();
|
||||
|
||||
$this->assertArraySubset($data, (array)$user->{$name}->attributesToArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Models\User\User::news()
|
||||
*
|
||||
* @dataProvider hasManyRelationsProvider
|
||||
*
|
||||
* @param string $class Class name of the related models
|
||||
* @param string $name Name of the accessor for the related models
|
||||
* @param array $modelData List of the related models
|
||||
*/
|
||||
public function testHasManyRelations(string $class, string $name, array $modelData): void
|
||||
{
|
||||
$user = new User($this->data);
|
||||
$user->save();
|
||||
|
||||
$relatedModelIds = [];
|
||||
|
||||
foreach ($modelData as $data) {
|
||||
/** @var BaseModel $model */
|
||||
$model = $this->app->make($class);
|
||||
$stored = $model->create($data + ['user_id' => $user->id]);
|
||||
$relatedModelIds[] = $stored->id;
|
||||
}
|
||||
|
||||
$this->assertEquals($relatedModelIds, $user->{$name}->modelKeys());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Models\User\User::groups
|
||||
*
|
||||
* @dataProvider belongsToManyRelationsProvider
|
||||
*
|
||||
* @param string $class Class name of the related models
|
||||
* @param string $name Name of the accessor for the related models
|
||||
* @param array $modelData List of the related models
|
||||
*/
|
||||
public function testBelongsToManyRelations(string $class, string $name, array $modelData): void
|
||||
{
|
||||
$user = new User($this->data);
|
||||
$user->save();
|
||||
|
||||
$relatedModelIds = [];
|
||||
|
||||
foreach ($modelData as $data) {
|
||||
/** @var BaseModel $model */
|
||||
$model = $this->app->make($class);
|
||||
$stored = $model->create($data);
|
||||
$stored->users()->attach($user);
|
||||
$relatedModelIds[] = $stored->id;
|
||||
}
|
||||
|
||||
$this->assertEquals($relatedModelIds, $user->{$name}->modelKeys());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Models\User\User::privileges
|
||||
* @covers \Engelsystem\Models\User\User::getPrivilegesAttribute
|
||||
*/
|
||||
public function testPrivileges()
|
||||
{
|
||||
$user = new User($this->data);
|
||||
$user->save();
|
||||
|
||||
/** @var Group $group1 */
|
||||
$group1 = Group::factory()->create();
|
||||
/** @var Group $group2 */
|
||||
$group2 = Group::factory()->create();
|
||||
/** @var Group $group3 */
|
||||
$group3 = Group::factory()->create();
|
||||
/** @var Privilege $privilege1 */
|
||||
$privilege1 = Privilege::factory()->create();
|
||||
/** @var Privilege $privilege2 */
|
||||
$privilege2 = Privilege::factory()->create();
|
||||
/** @var Privilege $privilege3 */
|
||||
$privilege3 = Privilege::factory()->create();
|
||||
/** @var Privilege $privilege4 */
|
||||
$privilege4 = Privilege::factory()->create();
|
||||
|
||||
$user->groups()->attach($group1);
|
||||
$user->groups()->attach($group2);
|
||||
|
||||
$group1->privileges()->attach($privilege1);
|
||||
$group1->privileges()->attach($privilege2);
|
||||
|
||||
$group2->privileges()->attach($privilege2);
|
||||
$group2->privileges()->attach($privilege3);
|
||||
|
||||
$group3->privileges()->attach($privilege3);
|
||||
$group3->privileges()->attach($privilege4);
|
||||
|
||||
/** @var User $createdUser */
|
||||
$createdUser = User::first();
|
||||
$this->assertInstanceOf(Builder::class, $createdUser->privileges());
|
||||
|
||||
$privileges = $createdUser->privileges->pluck('name');
|
||||
$this->assertCount(3, $privileges);
|
||||
$this->assertContains($privilege1->name, $privileges);
|
||||
$this->assertContains($privilege2->name, $privileges);
|
||||
$this->assertContains($privilege3->name, $privileges);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that accessing the NewsComments of an User works.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue