summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Scheller <igor.scheller@igorshp.de>2019-07-28 17:14:42 +0200
committerIgor Scheller <igor.scheller@igorshp.de>2019-07-29 00:58:06 +0200
commit219c54411bb765bebd7813ad3e49ab05acf0b150 (patch)
tree9cf1cea8fccac16030e308df63352c2237311c0e
parentc1f6374f377d7b6d2aeefa464837226279a521a3 (diff)
Permissions: Added models and migrations
-rw-r--r--composer.json1
-rw-r--r--db/migrations/2019_07_21_000002_create_teams_roles_and_permissions_tables.php464
-rw-r--r--src/Helpers/Authenticator.php2
-rw-r--r--src/Models/Auth/Permission.php57
-rw-r--r--src/Models/Auth/Role.php71
-rw-r--r--src/Models/BaseModel.php3
-rw-r--r--src/Models/Team.php99
-rw-r--r--src/Models/User/User.php55
-rw-r--r--tests/Unit/HasDatabase.php1
-rw-r--r--tests/Unit/Helpers/AuthenticatorTest.php2
-rw-r--r--tests/Unit/Models/Auth/AuthModelTest.php109
-rw-r--r--tests/Unit/Models/Auth/PermissionTest.php50
-rw-r--r--tests/Unit/Models/Auth/RoleTest.php68
-rw-r--r--tests/Unit/Models/TeamTest.php71
-rw-r--r--tests/Unit/Models/User/UserTest.php72
15 files changed, 1119 insertions, 6 deletions
diff --git a/composer.json b/composer.json
index a1f2101b..7f680efd 100644
--- a/composer.json
+++ b/composer.json
@@ -33,6 +33,7 @@
"psr/http-server-middleware": "^1.0",
"psr/log": "^1.1",
"respect/validation": "^1.1",
+ "staudenmeir/eloquent-has-many-deep": "^1.8",
"swiftmailer/swiftmailer": "^6.2",
"symfony/http-foundation": "^4.3",
"symfony/psr-http-message-bridge": "^1.2",
diff --git a/db/migrations/2019_07_21_000002_create_teams_roles_and_permissions_tables.php b/db/migrations/2019_07_21_000002_create_teams_roles_and_permissions_tables.php
new file mode 100644
index 00000000..80f49841
--- /dev/null
+++ b/db/migrations/2019_07_21_000002_create_teams_roles_and_permissions_tables.php
@@ -0,0 +1,464 @@
+<?php
+
+namespace Engelsystem\Migrations;
+
+use Engelsystem\Database\Migration\Migration;
+use Engelsystem\Models\Auth\Permission;
+use Engelsystem\Models\Auth\Role;
+use Engelsystem\Models\Team;
+use Engelsystem\Models\User\User;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Database\Schema\Blueprint;
+use stdClass;
+
+class CreateTeamsRolesAndPermissionsTables extends Migration
+{
+ use ChangesReferences;
+ use Reference;
+
+ /**
+ * Run the migration
+ */
+ public function up()
+ {
+ $this->schema->create('teams', function (Blueprint $table) {
+ $table->increments('id');
+
+ $table->string('name')->unique();
+ $table->text('description')->nullable();
+
+ $table->string('contact_name')->nullable()->default(null);
+ $table->string('contact_email')->nullable()->default(null);
+ $table->string('contact_dect', 40)->nullable()->default(null);
+
+ $table->boolean('restricted')->default(false);
+ $table->boolean('self_signup')->default(true);
+ $table->boolean('requires_drivers_license')->default(false);
+ $table->boolean('show_on_frontend')->default(true);
+ $table->boolean('show_on_dashboard')->default(true);
+
+ $table->timestamps();
+ });
+
+ $this->schema->create('roles', function (Blueprint $table) {
+ $table->increments('id');
+
+ $table->string('name')->unique();
+ $table->text('description')->nullable();
+
+ $table->timestamps();
+ });
+
+ $this->schema->create('permissions', function (Blueprint $table) {
+ $table->increments('id');
+
+ $table->string('name')->unique();
+ $table->text('description')->nullable();
+
+ $table->timestamps();
+ });
+
+ $this->schema->create('team_user', function (Blueprint $table) {
+ $table->increments('id');
+
+ $this->referencesUser($table);
+ $this->references($table, 'teams', 'team_id');
+ $table->boolean('confirmed')->default(true);
+
+ $table->timestamps();
+
+ $table->unique(['team_id', 'user_id']);
+ });
+
+ $this->schema->create('supporter_team', function (Blueprint $table) {
+ $table->increments('id');
+
+ $this->referencesUser($table);
+ $this->references($table, 'teams', 'team_id');
+
+ $table->timestamps();
+
+ $table->unique(['team_id', 'user_id']);
+ });
+
+ $this->schema->create('role_team', function (Blueprint $table) {
+ $table->increments('id');
+
+ $this->references($table, 'teams', 'team_id');
+ $this->references($table, 'roles', 'role_id');
+
+ $table->timestamps();
+
+ $table->unique(['role_id', 'team_id']);
+ });
+
+ $this->schema->create('permission_role', function (Blueprint $table) {
+ $table->increments('id');
+
+ $this->references($table, 'roles', 'role_id');
+ $this->references($table, 'permissions', 'permission_id');
+
+ $table->timestamps();
+
+ $table->unique(['permission_id', 'role_id']);
+ });
+
+ if ($this->schema->hasTable('AngelTypes')) {
+ $connection = $this->schema->getConnection();
+ $connection
+ ->table('Groups')
+ ->update([
+ 'UID' => $connection->raw('UID / 10')
+ ]);
+
+ /** @var Team[] $teams */
+ $teams = [];
+ /** @var stdClass[] $users */
+ $angelTypes = $connection->table('AngelTypes')->get();
+ foreach ($angelTypes as $data) {
+ $team = new Team([
+ 'name' => $data->name,
+ 'description' => $data->description ?: null,
+ 'contact_name' => $data->contact_name ?: null,
+ 'contact_email' => $data->contact_email ?: null,
+ 'contact_dect' => $data->contact_dect ?: null,
+ 'restricted' => (bool)$data->restricted,
+ 'self_signup' => !(bool)$data->no_self_signup,
+ 'requires_drivers_license' => (bool)$data->requires_driver_license,
+ 'show_on_dashboard' => (bool)$data->show_on_dashboard,
+ ]);
+ $team->setAttribute('id', $data->id);
+
+ $team->save();
+
+ $teams[$team->id] = $team;
+ $teams[$team->name] = $team;
+ }
+
+ /** @var Role[] $roles */
+ $roles = [];
+ /** @var stdClass[] $groups */
+ $groups = $connection->table('Groups')->get();
+ foreach ($groups as $data) {
+ $role = new Role([
+ 'name' => $data->Name,
+ 'description' => null,
+ ]);
+ $role->setAttribute('id', $data->UID);
+
+ $role->save();
+
+ $roles[$role->id] = $role;
+ }
+
+ /** @var Permission[] $permissions */
+ $permissions = [];
+ /** @var stdClass[] $privileges */
+ $privileges = $connection->table('Privileges')->get();
+ foreach ($privileges as $data) {
+ $permission = new Permission([
+ 'name' => $data->name,
+ 'description' => $data->desc ?: null,
+ ]);
+ $permission->setAttribute('id', $data->id);
+
+ $permission->save();
+
+ $permissions[$permission->id] = $permission;
+ }
+
+ $this->changeReferences(
+ 'AngelTypes',
+ 'id',
+ 'teams',
+ 'id'
+ );
+
+ $this->changeReferences(
+ 'Groups',
+ 'UID',
+ 'roles',
+ 'id'
+ );
+
+ $this->changeReferences(
+ 'Privileges',
+ 'id',
+ 'permissions',
+ 'id'
+ );
+
+ /** @var stdClass[] $groupPrivileges */
+ $groupPrivileges = $connection->table('GroupPrivileges')->get();
+ foreach ($groupPrivileges as $data) {
+ $roles[$data->group_id]
+ ->permissions()
+ ->attach($permissions[$data->privilege_id]);
+ }
+
+ foreach ($roles as $role) {
+ if ($role->name == 'Guest' || Team::whereName($role->name)->count()) {
+ continue;
+ }
+
+ $team = new Team([
+ 'name' => $role->name,
+ 'description' => $role->description,
+ 'restricted' => $role->name != 'Angel',
+ 'show_on_frontend' => !in_array($role->name, ['Developer']),
+ 'show_on_dashboard' => !in_array($role->name, ['Developer', 'News Admin']),
+ ]);
+
+ $team->save();
+
+ $teams[$team->id] = $team;
+ $teams[$team->name] = $team;
+ }
+
+ /** @var stdClass $userAngelTypes */
+ $userAngelTypes = $connection
+ ->table('UserAngelTypes')
+ ->orderBy('user_id')
+ ->orderBy('angeltype_id')
+ ->get();
+ foreach ($userAngelTypes as $userAngelType) {
+ $teams[$userAngelType->angeltype_id]->users()->attach(
+ $userAngelType->user_id,
+ ['confirmed' => (bool)$userAngelType->confirm_user_id]
+ );
+
+ if ($userAngelType->supporter) {
+ $teams[$userAngelType->angeltype_id]->supporters()->attach($userAngelType->user_id);
+ }
+ }
+
+ /** @var stdClass[] $userGroups */
+ $userGroups = $connection
+ ->table('UserGroups')
+ ->leftJoin('Groups', 'group_id', '=', 'Groups.UID')
+ ->orderBy('UserGroups.uid')
+ ->orderBy('Groups.Name')
+ ->get(['Groups.Name AS group_name', 'UserGroups.uid AS user_id']);
+ foreach ($userGroups as $userGroup) {
+ $teams[$userGroup->group_name]->users()->attach($userGroup->user_id);
+ }
+
+ /** @var stdClass[] $teamRoles */
+ $teamRoles = $connection
+ ->table('roles')
+ ->join('teams', 'roles.name', '=', 'teams.name')
+ ->get(['roles.id AS role_id', 'teams.id AS team_id']);
+ foreach ($teamRoles as $teamRole) {
+ $teams[$teamRole->team_id]->roles()->attach($teamRole->role_id);
+ }
+
+ $this->schema->table('GroupPrivileges', function (Blueprint $table) {
+ $table->unsignedInteger('id')->unsigned()->autoIncrement()->change();
+ });
+ }
+
+ $this->schema->dropIfExists('GroupPrivileges');
+ $this->schema->dropIfExists('UserGroups');
+ $this->schema->dropIfExists('UserAngelTypes');
+ $this->schema->dropIfExists('Privileges');
+ $this->schema->dropIfExists('Groups');
+ $this->schema->dropIfExists('AngelTypes');
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down()
+ {
+ $connection = $this->schema->getConnection();
+
+ $this->schema->create('AngelTypes', function (Blueprint $table) {
+ $table->increments('id');
+
+ $table->string('name', 50);
+ $table->boolean('restricted');
+ $table->text('description');
+ $table->boolean('requires_driver_license');
+ $table->boolean('no_self_signup');
+ $table->string('contact_name', 250)->nullable();
+ $table->string('contact_dect', 40)->nullable();
+ $table->string('contact_email', 250)->nullable();
+ $table->boolean('show_on_dashboard');
+
+ $table->unique('name');
+ });
+
+ $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('UserAngelTypes', function (Blueprint $table) {
+ $table->increments('id');
+
+ $this->referencesUser($table);
+ $this->references($table, 'teams', 'angeltype_id');
+ $this->references($table, 'users', 'confirm_user_id')->nullable();
+ $table->boolean('supporter')->nullable();
+
+ $table->index(['user_id', 'angeltype_id', 'confirm_user_id']);
+ $table->index(['angeltype_id']);
+ $table->index(['confirm_user_id']);
+ $table->index(['supporter']);
+ });
+
+ $this->schema->create('UserGroups', function (Blueprint $table) {
+ $table->increments('id');
+
+ $this->references($table, 'users', 'uid');
+ $this->references($table, 'roles', 'group_id');
+
+ $table->index(['uid', 'group_id']);
+ $table->index(['group_id']);
+ });
+
+ $this->schema->create('GroupPrivileges', function (Blueprint $table) {
+ $table->increments('id');
+
+ $this->references($table, 'roles', 'group_id');
+ $this->references($table, 'permissions', 'privilege_id');
+
+ $table->index(['group_id', 'privilege_id']);
+ $table->index(['privilege_id']);
+ });
+
+ $roleNames = Role::all('name')->pluck('name')->toArray();
+ $teams = Team::query()
+ ->whereNotIn('name', $roleNames)
+ ->get();
+ foreach ($teams as $team) {
+ /** @var Team $team */
+ $connection
+ ->table('AngelTypes')
+ ->insert([
+ 'id' => $team->id,
+ 'name' => $team->name,
+ 'description' => $team->description ?: '',
+ 'restricted' => $team->restricted,
+ 'requires_driver_license' => $team->requires_drivers_license,
+ 'no_self_signup' => !$team->self_signup,
+ 'contact_name' => $team->contact_name,
+ 'contact_dect' => $team->contact_dect,
+ 'contact_email' => $team->contact_email,
+ 'show_on_dashboard' => $team->show_on_dashboard
+ ]);
+ }
+
+ foreach (Role::all() as $role) {
+ $connection
+ ->table('Groups')
+ ->insert([
+ 'Name' => $role->name,
+ 'UID' => $role->id,
+ ]);
+ }
+
+ foreach (Permission::all() as $permission) {
+ $connection
+ ->table('Privileges')
+ ->insert([
+ 'id' => $permission->id,
+ 'name' => $permission->name,
+ 'desc' => $permission->description
+ ]);
+ }
+
+
+ $teams = Team::with('users', 'supporters')
+ ->whereNotIn('name', $roleNames)
+ ->get();
+ foreach ($teams as $team) {
+ /** @var User[]|Collection $supporters */
+ $supporters = $team->supporters;
+ foreach ($team->users as $user) {
+ /** @var User $user */
+ $connection
+ ->table('UserAngelTypes')
+ ->insert([
+ 'user_id' => $user->id,
+ 'angeltype_id' => $team->id,
+ 'confirm_user_id' => $user->pivot->confirmed ?: null,
+ 'supporter' => $supporters->where('id', '=', $user->id)->count(),
+ ]);
+ }
+ }
+
+ $teams = Team::with('users')
+ ->whereIn('name', $roleNames)
+ ->get();
+ foreach ($teams as $team) {
+ foreach ($team->users as $user) {
+ $role = Role::whereName($team->name)->first();
+ /** @var User $user */
+ $connection
+ ->table('UserGroups')
+ ->insert([
+ 'uid' => $user->id,
+ 'group_id' => $role ? $role->id : $team->id,
+ ]);
+ }
+ }
+
+ foreach (Permission::with('roles')->get() as $permission) {
+ foreach ($permission->roles as $role) {
+ $connection
+ ->table('GroupPrivileges')
+ ->insert([
+ 'group_id' => $role->id,
+ 'privilege_id' => $permission->id,
+ ]);
+ }
+ }
+
+ $this->schema->drop('permission_role');
+ $this->schema->drop('role_team');
+ $this->schema->drop('supporter_team');
+ $this->schema->drop('team_user');
+
+ $this->changeReferences(
+ 'teams',
+ 'id',
+ 'AngelTypes',
+ 'id',
+ 'unsignedInteger'
+ );
+
+ $this->changeReferences(
+ 'roles',
+ 'id',
+ 'Groups',
+ 'UID',
+ 'integer'
+ );
+
+ $this->changeReferences(
+ 'permissions',
+ 'id',
+ 'Privileges',
+ 'id'
+ );
+
+ $this->schema->drop('permissions');
+ $this->schema->drop('roles');
+ $this->schema->drop('teams');
+
+ $connection
+ ->table('Groups')
+ ->update([
+ 'UID' => $connection->raw('UID * 10')
+ ]);
+ }
+}
diff --git a/src/Helpers/Authenticator.php b/src/Helpers/Authenticator.php
index a7fbe8c7..f1e054ef 100644
--- a/src/Helpers/Authenticator.php
+++ b/src/Helpers/Authenticator.php
@@ -29,7 +29,7 @@ class Authenticator
protected $passwordAlgorithm = PASSWORD_DEFAULT;
/** @var int */
- protected $guestRole = 10;
+ protected $guestRole = 1;
/**
* @param ServerRequestInterface $request
diff --git a/src/Models/Auth/Permission.php b/src/Models/Auth/Permission.php
new file mode 100644
index 00000000..1a4fd3e4
--- /dev/null
+++ b/src/Models/Auth/Permission.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Engelsystem\Models\Auth;
+
+use Engelsystem\Models\BaseModel;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
+use Staudenmeir\EloquentHasManyDeep\HasManyDeep;
+
+/**
+ * @property integer $id
+ * @property string $name
+ * @property string|null $description
+ * @property \Carbon\Carbon $created_at
+ * @property \Carbon\Carbon $updated_at
+ *
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\Auth\Role[] $roles
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] $users
+ *
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User whereId($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereName($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereDescription($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereCreatedAt($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereUpdatedAt($value)
+ */
+class Permission extends BaseModel
+{
+ /** @var bool enable timestamps */
+ public $timestamps = true;
+
+ /** The attributes that are mass assignable */
+ protected $fillable = [
+ 'name',
+ 'description',
+ ];
+
+ /**
+ * The roles that have this permission
+ *
+ * @return BelongsToMany
+ */
+ public function roles()
+ {
+ return $this
+ ->belongsToMany(Role::class)
+ ->withTimestamps();
+ }
+
+ /**
+ * The users that that have the permission
+ *
+ * @return HasManyDeep
+ */
+ public function users()
+ {
+ return $this->hasManyDeepFromRelations($this->roles(), (new Role)->users());
+ }
+}
diff --git a/src/Models/Auth/Role.php b/src/Models/Auth/Role.php
new file mode 100644
index 00000000..ede93ae1
--- /dev/null
+++ b/src/Models/Auth/Role.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace Engelsystem\Models\Auth;
+
+use Engelsystem\Models\BaseModel;
+use Engelsystem\Models\Team;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
+use Staudenmeir\EloquentHasManyDeep\HasManyDeep;
+
+/**
+ * @property integer $id
+ * @property string $name
+ * @property string|null $description
+ * @property \Carbon\Carbon $created_at
+ * @property \Carbon\Carbon $updated_at
+ *
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\Auth\Permission[] $permissions
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\Team[] $teams
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] $users
+ *
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User whereId($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereName($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereDescription($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereCreatedAt($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereUpdatedAt($value)
+ */
+class Role extends BaseModel
+{
+ /** @var bool enable timestamps */
+ public $timestamps = true;
+
+ /** The attributes that are mass assignable */
+ protected $fillable = [
+ 'name',
+ 'description',
+ ];
+
+ /**
+ * The roles permissions
+ *
+ * @return BelongsToMany
+ */
+ public function permissions()
+ {
+ return $this
+ ->belongsToMany(Permission::class)
+ ->withTimestamps();
+ }
+
+ /**
+ * The teams that that have the role assigned
+ *
+ * @return BelongsToMany
+ */
+ public function teams()
+ {
+ return $this
+ ->belongsToMany(Team::class)
+ ->withTimestamps();
+ }
+
+ /**
+ * The users that that have the role assigned
+ *
+ * @return HasManyDeep
+ */
+ public function users()
+ {
+ return $this->hasManyDeepFromRelations($this->teams(), (new Team)->users());
+ }
+}
diff --git a/src/Models/BaseModel.php b/src/Models/BaseModel.php
index 49255905..2eae2efc 100644
--- a/src/Models/BaseModel.php
+++ b/src/Models/BaseModel.php
@@ -5,9 +5,12 @@ namespace Engelsystem\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
+use Staudenmeir\EloquentHasManyDeep\HasRelationships as HasManyDeep;
abstract class BaseModel extends Model
{
+ use HasManyDeep;
+
/** @var bool Disable timestamps by default because of "Datensparsamkeit" */
public $timestamps = false;
diff --git a/src/Models/Team.php b/src/Models/Team.php
new file mode 100644
index 00000000..b6acaadc
--- /dev/null
+++ b/src/Models/Team.php
@@ -0,0 +1,99 @@
+<?php
+
+namespace Engelsystem\Models;
+
+use Engelsystem\Models\Auth\Role;
+use Engelsystem\Models\User\User;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
+
+/**
+ * @property integer $id
+ * @property string $name
+ * @property string|null $description
+ * @property string|null $contact_name
+ * @property string|null $contact_dect
+ * @property string|null $contact_email
+ * @property bool $restricted Join Needs additional
+ * confirmation
+ * @property bool $self_signup Can signup for shifts
+ * @property bool $requires_drivers_license
+ * @property bool $show_on_frontend
+ * @property bool $show_on_dashboard
+ * @property \Carbon\Carbon $created_at
+ * @property \Carbon\Carbon $updated_at
+ *
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\Auth\Role[] $roles
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] $supporters
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] $users
+ *
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User whereId($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereName($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereDescription($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereContactName($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereContactDect($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereContactEmail($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereRestricted($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereSelfSignup($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[]
+ * whereRequiresDriversLicense($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereShowOnFrontend($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereShowOnDashboard($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereCreatedAt($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereUpdatedAt($value)
+ */
+class Team extends BaseModel
+{
+ /** @var bool enable timestamps */
+ public $timestamps = true;
+
+ /** The attributes that are mass assignable */
+ protected $fillable = [
+ 'name',
+ 'description',
+ 'contact_name',
+ 'contact_dect',
+ 'contact_email',
+ 'restricted',
+ 'self_signup',
+ 'requires_drivers_license',
+ 'show_on_frontend',
+ 'show_on_dashboard',
+ ];
+
+ /**
+ * The roles that belong to the team
+ *
+ * @return BelongsToMany
+ */
+ public function roles()
+ {
+ return $this
+ ->belongsToMany(Role::class)
+ ->withTimestamps();
+ }
+
+ /**
+ * The users that that support to the team
+ *
+ * @return BelongsToMany
+ */
+ public function supporters()
+ {
+ return $this
+ ->belongsToMany(User::class, 'supporter_team')
+ ->withTimestamps();
+ }
+
+ /**
+ * The users that that belong to the team
+ *
+ * @return BelongsToMany
+ */
+ public function users()
+ {
+ return $this
+ ->belongsToMany(User::class)
+ ->withPivot(['confirmed'])
+ ->withTimestamps();
+ }
+}
diff --git a/src/Models/User/User.php b/src/Models/User/User.php
index 4be3246c..b92ed5fe 100644
--- a/src/Models/User/User.php
+++ b/src/Models/User/User.php
@@ -2,8 +2,12 @@
namespace Engelsystem\Models\User;
+use Engelsystem\Models\Auth\Role;
use Engelsystem\Models\BaseModel;
+use Engelsystem\Models\Team;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
+use Staudenmeir\EloquentHasManyDeep\HasManyDeep;
/**
* @property integer $id
@@ -19,8 +23,12 @@ use Illuminate\Database\Eloquent\Relations\HasOne;
* @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\PersonalData $personalData
* @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\Settings $settings
* @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\State $state
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\Auth\Permission[] $permissions
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\Auth\Role[] $roles
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\Team[] $supports
+ * @property-read \Illuminate\Database\Query\Builder|\Engelsystem\Models\Team[] $teams
*
- * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User whereId($value)
+ * @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereName($value)
* @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] whereEmail($value)
* @method static \Illuminate\Database\Query\Builder|\Engelsystem\Models\User\User[] wherePassword($value)
@@ -75,6 +83,51 @@ class User extends BaseModel
}
/**
+ * The permissions that the user has
+ *
+ * @return HasManyDeep
+ */
+ public function permissions()
+ {
+ return $this->hasManyDeepFromRelations($this->roles(), (new Role)->permissions());
+ }
+
+ /**
+ * The roles that belong to the user
+ *
+ * @return HasManyDeep
+ */
+ public function roles()
+ {
+ return $this->hasManyDeepFromRelations($this->teams(), (new Team)->roles());
+ }
+
+ /**
+ * The teams that are supported by the user
+ *
+ * @return BelongsToMany
+ */
+ public function supports()
+ {
+ return $this
+ ->belongsToMany(Team::class, 'supporter_team')
+ ->withTimestamps();
+ }
+
+ /**
+ * The teams that belong to the user
+ *
+ * @return BelongsToMany
+ */
+ public function teams()
+ {
+ return $this
+ ->belongsToMany(Team::class)
+ ->withPivot(['confirmed'])
+ ->withTimestamps();
+ }
+
+ /**
* @return HasOne
*/
public function settings()
diff --git a/tests/Unit/HasDatabase.php b/tests/Unit/HasDatabase.php
index 7fd42f96..85b59435 100644
--- a/tests/Unit/HasDatabase.php
+++ b/tests/Unit/HasDatabase.php
@@ -46,6 +46,7 @@ trait HasDatabase
['migration' => '2018_01_01_000005_add_angel_supporter_permissions'],
['migration' => '2018_12_27_000000_fix_missing_arrival_dates'],
['migration' => '2019_07_21_000000_fix_old_character_set'],
+ ['migration' => '2019_07_21_000001_fix_old_groups_table_id_and_name'],
]);
$migration->run(__DIR__ . '/../../db/migrations');
diff --git a/tests/Unit/Helpers/AuthenticatorTest.php b/tests/Unit/Helpers/AuthenticatorTest.php
index d601a77f..8dc14370 100644
--- a/tests/Unit/Helpers/AuthenticatorTest.php
+++ b/tests/Unit/Helpers/AuthenticatorTest.php
@@ -132,7 +132,7 @@ class AuthenticatorTest extends ServiceProviderTest
->getMock();
$auth->expects($this->exactly(1))
->method('getPermissionsByGroup')
- ->with(10)
+ ->with(1)
->willReturn([]);
$auth->expects($this->exactly(1))
->method('getPermissionsByUser')
diff --git a/tests/Unit/Models/Auth/AuthModelTest.php b/tests/Unit/Models/Auth/AuthModelTest.php
new file mode 100644
index 00000000..754e120a
--- /dev/null
+++ b/tests/Unit/Models/Auth/AuthModelTest.php
@@ -0,0 +1,109 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Models\Auth;
+
+use Engelsystem\Models\Auth\Permission;
+use Engelsystem\Models\Auth\Role;
+use Engelsystem\Models\BaseModel;
+use Engelsystem\Models\Team;
+use Engelsystem\Models\User\User;
+use Engelsystem\Test\Unit\Models\ModelTest;
+
+abstract class AuthModelTest extends ModelTest
+{
+ /** @var array */
+ protected $user = [
+ 'name' => 'Test User',
+ 'password' => 'nope',
+ 'email' => 'foo@bar.batz',
+ 'api_key' => 'Test123',
+ ];
+
+ /** @var array */
+ protected $team = [
+ 'name' => 'Test Team',
+ ];
+
+ /** @var array */
+ protected $role = [
+ 'name' => 'Test Role',
+ ];
+
+ /** @var array */
+ protected $permission = [
+ 'name' => 'foo.bar',
+ ];
+
+ /**
+ * @param array $data
+ * @return Permission
+ */
+ protected function getPermission($data = [])
+ {
+ /** @var Permission $model */
+ $model = $this->getModel(Permission::class, array_merge($this->permission, $data));
+
+ return $model;
+ }
+
+ /**
+ * @param Permission|Permission[] $permissions
+ * @param array $data
+ * @return Role
+ */
+ protected function getRole($permissions = [], $data = [])
+ {
+ /** @var Role $model */
+ $model = $this->getModel(Role::class, array_merge($this->role, $data), ['permissions' => $permissions]);
+
+ return $model;
+ }
+
+ /**
+ * @param Role|Role[] $roles
+ * @param array $data
+ * @return Team
+ */
+ protected function getTeam($roles = [], $data = [])
+ {
+ /** @var Team $model */
+ $model = $this->getModel(Team::class, array_merge($this->team, $data), ['roles' => $roles]);
+
+ return $model;
+ }
+
+ /**
+ * @param Team|Team[] $teams
+ * @param array $data
+ * @return User
+ */
+ protected function getUser($teams = [], $data = [])
+ {
+ /** @var User $model */
+ $model = $this->getModel(User::class, array_merge($this->user, $data), ['teams' => $teams]);
+
+ return $model;
+ }
+
+ /**
+ * @param string $class BaseModel implementation name
+ * @param array $data
+ * @param array $attachments
+ * @return BaseModel
+ */
+ protected function getModel($class, $data = [], $attachments = [])
+ {
+ /** @var BaseModel $instance */
+ $instance = new $class($data);
+ $instance->save();
+
+ foreach ($attachments as $type => $attachment) {
+ $objects = is_object($attachment) ? [$attachment] : $attachment;
+ foreach ($objects as $object) {
+ $instance->$type()->attach($object);
+ }
+ }
+
+ return $instance;
+ }
+}
diff --git a/tests/Unit/Models/Auth/PermissionTest.php b/tests/Unit/Models/Auth/PermissionTest.php
new file mode 100644
index 00000000..bb5f7605
--- /dev/null
+++ b/tests/Unit/Models/Auth/PermissionTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Models\Auth;
+
+use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
+use Engelsystem\Models\Auth\Permission;
+
+class PermissionTest extends AuthModelTest
+{
+ use ArraySubsetAsserts;
+
+ /** @var array */
+ protected $data = [
+ 'name' => 'foo.bar',
+ 'description' => 'Allows bar in foo',
+ ];
+
+ /**
+ * @covers \Engelsystem\Models\Auth\Permission::roles
+ */
+ public function testPermissions()
+ {
+ $role = $this->getRole();
+ $role2 = $this->getRole([], ['name' => 'Example Role']);
+
+ $permission = new Permission($this->data);
+ $permission->save();
+ $permission->roles()->attach($role);
+ $permission->roles()->attach($role2);
+
+ $this->assertCount(2, $permission->roles);
+ $this->assertEquals('Test Role', $permission->roles()->get()->first()->name);
+ }
+
+ /**
+ * @covers \Engelsystem\Models\Auth\Permission::users
+ */
+ public function testUsers()
+ {
+ $role = $this->getRole();
+ $team = $this->getTeam($role);
+ $this->getUser($team);
+
+ $permission = new Permission($this->data);
+ $permission->save();
+ $permission->roles()->attach($role);
+
+ $this->assertEquals('Test User', $permission->users()->get()->first()->name);
+ }
+}
diff --git a/tests/Unit/Models/Auth/RoleTest.php b/tests/Unit/Models/Auth/RoleTest.php
new file mode 100644
index 00000000..10c22f9c
--- /dev/null
+++ b/tests/Unit/Models/Auth/RoleTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Models\Auth;
+
+use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
+use Engelsystem\Models\Auth\Role;
+
+class RoleTest extends AuthModelTest
+{
+ use ArraySubsetAsserts;
+
+ /** @var array */
+ protected $data = [
+ 'name' => 'Test Role',
+ 'description' => 'Lorem Ipsum',
+ ];
+
+ /**
+ * @covers \Engelsystem\Models\Auth\Role::permissions
+ */
+ public function testPermissions()
+ {
+ $permission = $this->getPermission();
+ $permission2 = $this->getPermission(['name' => 'Another Permission']);
+
+ $role = new Role($this->data);
+ $role->save();
+ $role->permissions()->attach($permission);
+ $role->permissions()->attach($permission2);
+
+ $this->assertCount(2, $role->permissions);
+ $this->assertEquals('foo.bar', $role->permissions()->get()->first()->name);
+ }
+
+ /**
+ * @covers \Engelsystem\Models\Auth\Role::teams
+ */
+ public function testTeams()
+ {
+ $team = $this->getTeam();
+
+ $role = new Role($this->data);
+ $role->save();
+ $role->teams()->attach($team);
+
+ $this->assertEquals('Test Team', $role->teams()->get()->first()->name);
+ }
+
+ /**
+ * @covers \Engelsystem\Models\Auth\Role::users
+ */
+ public function testUsers()
+ {
+ $team = $this->getTeam();
+ $team2 = $this->getTeam([], ['name' => 'Dev']);
+ $this->getUser($team);
+ $this->getUser($team, ['name' => 'Foo', 'email' => 'foo@xample.com']);
+ $this->getUser($team2, ['name' => 'Bar', 'email' => 'bar@xample.com']);
+
+ $role = new Role($this->data);
+ $role->save();
+ $role->teams()->attach($team);
+ $role->teams()->attach($team2);
+
+ $this->assertCount(3, $role->users()->get());
+ $this->assertEquals('Test User', $role->users()->get()->first()->name);
+ }
+}
diff --git a/tests/Unit/Models/TeamTest.php b/tests/Unit/Models/TeamTest.php
new file mode 100644
index 00000000..fdd5be44
--- /dev/null
+++ b/tests/Unit/Models/TeamTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Models;
+
+use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
+use Engelsystem\Models\Team;
+use Engelsystem\Test\Unit\Models\Auth\AuthModelTest;
+
+class TeamTest extends AuthModelTest
+{
+ use ArraySubsetAsserts;
+
+ /** @var array */
+ protected $data = [
+ 'name' => 'Example team',
+ 'description' => 'Lorem Ipsum',
+ 'contact_name' => 'Con Tact',
+ 'contact_dect' => '1337',
+ 'contact_email' => 'foo@bar.batz',
+ 'restricted' => false,
+ 'self_signup' => true,
+ 'requires_drivers_license' => false,
+ 'show_on_frontend' => true,
+ 'show_on_dashboard' => true,
+ ];
+
+ /**
+ * @covers \Engelsystem\Models\Team::roles
+ */
+ public function testRoles()
+ {
+ $role = $this->getRole();
+ $role2 = $this->getRole([], ['name' => 'Another Role']);
+
+ $team = new Team($this->data);
+ $team->save();
+ $team->roles()->attach($role);
+ $team->roles()->attach($role2);
+
+ $this->assertCount(2, $team->roles);
+ $this->assertEquals('Test Role', $team->roles()->get()->first()->name);
+ }
+
+ /**
+ * @covers \Engelsystem\Models\Team::supporters
+ */
+ public function testSupporters()
+ {
+ $user = $this->getUser();
+
+ $team = new Team($this->data);
+ $team->save();
+ $team->supporters()->attach($user);
+
+ $this->assertEquals('Test User', $team->supporters()->get()->first()->name);
+ }
+
+ /**
+ * @covers \Engelsystem\Models\Team::users
+ */
+ public function testUsers()
+ {
+ $user = $this->getUser();
+
+ $team = new Team($this->data);
+ $team->save();
+ $team->users()->attach($user);
+
+ $this->assertEquals('Test User', $team->users()->get()->first()->name);
+ }
+}
diff --git a/tests/Unit/Models/User/UserTest.php b/tests/Unit/Models/User/UserTest.php
index a0d20bc2..4696d56a 100644
--- a/tests/Unit/Models/User/UserTest.php
+++ b/tests/Unit/Models/User/UserTest.php
@@ -1,6 +1,6 @@
<?php
-namespace Engelsystem\Test\Unit\Models;
+namespace Engelsystem\Test\Unit\Models\User;
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
use Engelsystem\Models\User\Contact;
@@ -9,12 +9,13 @@ use Engelsystem\Models\User\PersonalData;
use Engelsystem\Models\User\Settings;
use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User;
-use Engelsystem\Test\Unit\Models\ModelTest;
+use Engelsystem\Test\Unit\Models\Auth\AuthModelTest;
-class UserTest extends ModelTest
+class UserTest extends AuthModelTest
{
use ArraySubsetAsserts;
+ /** @var array */
protected $data = [
'name' => 'lorem',
'password' => '',
@@ -87,4 +88,69 @@ class UserTest extends ModelTest
$this->assertArraySubset($data, (array)$user->{$name}->attributesToArray());
}
+
+ /**
+ * @covers \Engelsystem\Models\User\User::permissions
+ */
+ public function testPermissions()
+ {
+ $permission = $this->getPermission();
+ $role = $this->getRole($permission);
+ $team = $this->getTeam($role);
+
+ $user = new User($this->data);
+ $user->save();
+ $user->teams()->attach($team);
+
+ $this->assertEquals('foo.bar', $user->permissions()->first()->name);
+ }
+
+ /**
+ * @covers \Engelsystem\Models\User\User::roles
+ */
+ public function testRoles()
+ {
+ $role = $this->getRole();
+ $role2 = $this->getRole([], ['name' => 'Foo Role']);
+ $team = $this->getTeam([$role, $role2]);
+
+ $user = new User($this->data);
+ $user->save();
+ $user->teams()->attach($team);
+
+ $this->assertCount(2, $user->roles);
+ $this->assertEquals('Test Role', $user->roles()->get()->first()->name);
+ }
+
+ /**
+ * @covers \Engelsystem\Models\User\User::supports
+ */
+ public function testSupports()
+ {
+ $team = $this->getTeam();
+
+ $user = new User($this->data);
+ $user->save();
+ $user->teams()->attach($team);
+ $user->supports()->attach($team);
+
+ $this->assertEquals('Test Team', $user->supports()->get()->first()->name);
+ }
+
+ /**
+ * @covers \Engelsystem\Models\User\User::teams
+ */
+ public function testTeams()
+ {
+ $team = $this->getTeam();
+ $team2 = $this->getTeam([], ['name' => 'Another Team']);
+
+ $user = new User($this->data);
+ $user->save();
+ $user->teams()->attach($team);
+ $user->teams()->attach($team2);
+
+ $this->assertCount(2, $user->teams);
+ $this->assertEquals('Test Team', $user->teams()->get()->first()->name);
+ }
}