mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-05-07 20:32:26 +00:00
Enhanced admin panel
This commit is contained in:
committed by
Constantin Graf
parent
42ad5e004a
commit
0bf8a25d64
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Enums\Weekday;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
@@ -81,7 +82,7 @@ class CreateNewUser implements CreatesNewUsers
|
||||
|
||||
$organization->users()->attach(
|
||||
$user, [
|
||||
'role' => 'owner',
|
||||
'role' => Role::Owner->value,
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Actions\Jetstream;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
@@ -42,7 +43,7 @@ class CreateOrganization implements CreatesTeams
|
||||
|
||||
$organization->users()->attach(
|
||||
$user, [
|
||||
'role' => 'owner',
|
||||
'role' => Role::Owner->value,
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Filament\Resources\UserResource\Pages;
|
||||
use App\Filament\Resources\UserResource\RelationManagers\OrganizationsRelationManager;
|
||||
use App\Filament\Resources\UserResource\RelationManagers\OwnedOrganizationsRelationManager;
|
||||
use App\Models\User;
|
||||
use Exception;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
@@ -15,6 +16,7 @@ use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use STS\FilamentImpersonate\Tables\Actions\Impersonate;
|
||||
|
||||
class UserResource extends Resource
|
||||
{
|
||||
@@ -70,6 +72,19 @@ class UserResource extends Resource
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Impersonate::make()->before(function (User $record): void {
|
||||
if ($record->currentTeam === null) {
|
||||
$organization = $record->organizations()->where('personal_team', '=', true)->first();
|
||||
if ($organization === null) {
|
||||
$organization = $record->organizations()->first();
|
||||
}
|
||||
if ($organization === null) {
|
||||
throw new Exception('User has no organization');
|
||||
}
|
||||
$record->currentTeam()->associate($organization);
|
||||
$record->save();
|
||||
}
|
||||
}),
|
||||
Tables\Actions\EditAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace App\Filament\Resources\UserResource\Pages;
|
||||
use App\Filament\Resources\UserResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
use STS\FilamentImpersonate\Pages\Actions\Impersonate;
|
||||
|
||||
class EditUser extends EditRecord
|
||||
{
|
||||
@@ -15,6 +16,7 @@ class EditUser extends EditRecord
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Impersonate::make()->record($this->getRecord()),
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -126,6 +126,11 @@ class User extends Authenticatable implements FilamentUser, MustVerifyEmail
|
||||
return in_array($this->email, config('auth.super_admins', []), true) && $this->hasVerifiedEmail();
|
||||
}
|
||||
|
||||
public function canBeImpersonated(): bool
|
||||
{
|
||||
return $this->is_placeholder === false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<Organization>
|
||||
*/
|
||||
|
||||
@@ -59,10 +59,14 @@ class PermissionStore
|
||||
?->membership
|
||||
?->role;
|
||||
|
||||
if ($role === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @var Role|null $roleObj */
|
||||
$roleObj = Jetstream::findRole($role);
|
||||
|
||||
return $role !== null ? ($roleObj?->permissions ?? []) : [];
|
||||
return $roleObj?->permissions ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"nwidart/laravel-modules": "dev-feature/fixed_path",
|
||||
"pxlrbt/filament-environment-indicator": "^2.0",
|
||||
"spatie/temporary-directory": "^2.2",
|
||||
"stechstudio/filament-impersonate": "^3.8",
|
||||
"tightenco/ziggy": "^2.1.0",
|
||||
"tpetry/laravel-postgresql-enhanced": "^0.38.0",
|
||||
"wikimedia/composer-merge-plugin": "^2.1.0"
|
||||
|
||||
Generated
+132
-23
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "ad100a87fbe76efc70708726bc921412",
|
||||
"content-hash": "5779fb7e87efa88e5db2b37e64fe89e3",
|
||||
"packages": [
|
||||
{
|
||||
"name": "anourvalar/eloquent-serialize",
|
||||
@@ -74,28 +74,28 @@
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
"version": "2.0.8",
|
||||
"version": "v3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Bacon/BaconQrCode.git",
|
||||
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22"
|
||||
"reference": "510de6eca6248d77d31b339d62437cc995e2fb41"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22",
|
||||
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22",
|
||||
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/510de6eca6248d77d31b339d62437cc995e2fb41",
|
||||
"reference": "510de6eca6248d77d31b339d62437cc995e2fb41",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"dasprid/enum": "^1.0.3",
|
||||
"ext-iconv": "*",
|
||||
"php": "^7.1 || ^8.0"
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phly/keep-a-changelog": "^2.1",
|
||||
"phpunit/phpunit": "^7 | ^8 | ^9",
|
||||
"spatie/phpunit-snapshot-assertions": "^4.2.9",
|
||||
"squizlabs/php_codesniffer": "^3.4"
|
||||
"phly/keep-a-changelog": "^2.12",
|
||||
"phpunit/phpunit": "^10.5.11 || 11.0.4",
|
||||
"spatie/phpunit-snapshot-assertions": "^5.1.5",
|
||||
"squizlabs/php_codesniffer": "^3.9"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-imagick": "to generate QR code images"
|
||||
@@ -122,9 +122,9 @@
|
||||
"homepage": "https://github.com/Bacon/BaconQrCode",
|
||||
"support": {
|
||||
"issues": "https://github.com/Bacon/BaconQrCode/issues",
|
||||
"source": "https://github.com/Bacon/BaconQrCode/tree/2.0.8"
|
||||
"source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.0"
|
||||
},
|
||||
"time": "2022-12-07T17:46:57+00:00"
|
||||
"time": "2024-04-18T11:16:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "blade-ui-kit/blade-heroicons",
|
||||
@@ -3496,6 +3496,73 @@
|
||||
},
|
||||
"time": "2024-02-28T15:07:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lab404/laravel-impersonate",
|
||||
"version": "1.7.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/404labfr/laravel-impersonate.git",
|
||||
"reference": "82cad73700a8699d63de169bb41abd5ae283e9a8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/404labfr/laravel-impersonate/zipball/82cad73700a8699d63de169bb41abd5ae283e9a8",
|
||||
"reference": "82cad73700a8699d63de169bb41abd5ae283e9a8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0",
|
||||
"php": "^7.2 | ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.3.3",
|
||||
"orchestra/testbench": "^4.0 | ^5.0 | ^6.0 | ^7.0 | ^8.0 | ^9.0",
|
||||
"phpunit/phpunit": "^7.5 | ^8.0 | ^9.0 | ^10.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Lab404\\Impersonate\\ImpersonateServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Lab404\\Impersonate\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Marceau Casals",
|
||||
"email": "marceau@casals.fr"
|
||||
}
|
||||
],
|
||||
"description": "Laravel Impersonate is a plugin that allows to you to authenticate as your users.",
|
||||
"keywords": [
|
||||
"auth",
|
||||
"impersonate",
|
||||
"impersonation",
|
||||
"laravel",
|
||||
"laravel-package",
|
||||
"laravel-plugin",
|
||||
"package",
|
||||
"plugin",
|
||||
"user"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/404labfr/laravel-impersonate/issues",
|
||||
"source": "https://github.com/404labfr/laravel-impersonate/tree/1.7.5"
|
||||
},
|
||||
"time": "2024-03-11T14:26:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-diactoros",
|
||||
"version": "3.3.1",
|
||||
@@ -3583,20 +3650,20 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/fortify",
|
||||
"version": "v1.21.1",
|
||||
"version": "v1.21.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/fortify.git",
|
||||
"reference": "405388fd399264715573e23ed2f368fbce426da3"
|
||||
"reference": "cb122ceec7f8d0231985c1dde8161b3c561bfe90"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/fortify/zipball/405388fd399264715573e23ed2f368fbce426da3",
|
||||
"reference": "405388fd399264715573e23ed2f368fbce426da3",
|
||||
"url": "https://api.github.com/repos/laravel/fortify/zipball/cb122ceec7f8d0231985c1dde8161b3c561bfe90",
|
||||
"reference": "cb122ceec7f8d0231985c1dde8161b3c561bfe90",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"bacon/bacon-qr-code": "^2.0",
|
||||
"bacon/bacon-qr-code": "^3.0",
|
||||
"ext-json": "*",
|
||||
"illuminate/support": "^10.0|^11.0",
|
||||
"php": "^8.1",
|
||||
@@ -3644,7 +3711,7 @@
|
||||
"issues": "https://github.com/laravel/fortify/issues",
|
||||
"source": "https://github.com/laravel/fortify"
|
||||
},
|
||||
"time": "2024-03-19T20:08:25+00:00"
|
||||
"time": "2024-04-25T14:17:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
@@ -8038,6 +8105,48 @@
|
||||
],
|
||||
"time": "2023-12-25T11:46:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "stechstudio/filament-impersonate",
|
||||
"version": "3.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/stechstudio/filament-impersonate.git",
|
||||
"reference": "d24a9ffc1ef2f87940d151ca1cb2c2d2e5e524a8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/stechstudio/filament-impersonate/zipball/d24a9ffc1ef2f87940d151ca1cb2c2d2e5e524a8",
|
||||
"reference": "d24a9ffc1ef2f87940d151ca1cb2c2d2e5e524a8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"filament/filament": "^3.0",
|
||||
"lab404/laravel-impersonate": "^1.7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"STS\\FilamentImpersonate\\FilamentImpersonateServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"STS\\FilamentImpersonate\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "A Filament package to impersonate your users.",
|
||||
"support": {
|
||||
"issues": "https://github.com/stechstudio/filament-impersonate/issues",
|
||||
"source": "https://github.com/stechstudio/filament-impersonate/tree/3.8"
|
||||
},
|
||||
"time": "2024-03-25T03:05:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/clock",
|
||||
"version": "v7.0.5",
|
||||
@@ -13908,16 +14017,16 @@
|
||||
},
|
||||
{
|
||||
"name": "spatie/ignition",
|
||||
"version": "1.13.2",
|
||||
"version": "1.14.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/ignition.git",
|
||||
"reference": "952798e239d9969e4e694b124c2cc222798dbb28"
|
||||
"reference": "80385994caed328f6f9c9952926932e65b9b774c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/ignition/zipball/952798e239d9969e4e694b124c2cc222798dbb28",
|
||||
"reference": "952798e239d9969e4e694b124c2cc222798dbb28",
|
||||
"url": "https://api.github.com/repos/spatie/ignition/zipball/80385994caed328f6f9c9952926932e65b9b774c",
|
||||
"reference": "80385994caed328f6f9c9952926932e65b9b774c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -13987,7 +14096,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-16T08:49:17+00:00"
|
||||
"time": "2024-04-26T08:45:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-ignition",
|
||||
|
||||
+65
-37
@@ -44,8 +44,8 @@ return [
|
||||
],
|
||||
'replacements' => [
|
||||
'routes/web' => ['LOWER_NAME', 'STUDLY_NAME', 'MODULE_NAMESPACE', 'CONTROLLER_NAMESPACE'],
|
||||
'routes/api' => ['LOWER_NAME', 'STUDLY_NAME'],
|
||||
'vite' => ['LOWER_NAME'],
|
||||
'routes/api' => ['LOWER_NAME', 'STUDLY_NAME', 'MODULE_NAMESPACE', 'CONTROLLER_NAMESPACE'],
|
||||
'vite' => ['LOWER_NAME', 'STUDLY_NAME'],
|
||||
'json' => ['LOWER_NAME', 'STUDLY_NAME', 'MODULE_NAMESPACE', 'PROVIDER_NAMESPACE'],
|
||||
'views/index' => ['LOWER_NAME'],
|
||||
'views/master' => ['LOWER_NAME', 'STUDLY_NAME'],
|
||||
@@ -58,6 +58,7 @@ return [
|
||||
'AUTHOR_EMAIL',
|
||||
'MODULE_NAMESPACE',
|
||||
'PROVIDER_NAMESPACE',
|
||||
'APP_FOLDER_NAME',
|
||||
],
|
||||
],
|
||||
'gitkeep' => true,
|
||||
@@ -93,8 +94,18 @@ return [
|
||||
| the migration files?
|
||||
|
|
||||
*/
|
||||
|
||||
'migration' => base_path('database/migrations'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| The app path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| app folder name
|
||||
| for example can change it to 'src' or 'App'
|
||||
*/
|
||||
'app_folder' => 'app/',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Generator path
|
||||
@@ -103,35 +114,52 @@ return [
|
||||
| Setting the generate key to false will not generate that folder
|
||||
*/
|
||||
'generator' => [
|
||||
// app/
|
||||
'channels' => ['path' => 'app/Broadcasting', 'generate' => false],
|
||||
'command' => ['path' => 'app/Console', 'generate' => false],
|
||||
'emails' => ['path' => 'app/Emails', 'generate' => false],
|
||||
'event' => ['path' => 'app/Events', 'generate' => false],
|
||||
'jobs' => ['path' => 'app/Jobs', 'generate' => false],
|
||||
'listener' => ['path' => 'app/Listeners', 'generate' => false],
|
||||
'model' => ['path' => 'app/Models', 'generate' => false],
|
||||
'notifications' => ['path' => 'app/Notifications', 'generate' => false],
|
||||
'observer' => ['path' => 'app/Observers', 'generate' => false],
|
||||
'policies' => ['path' => 'app/Policies', 'generate' => false],
|
||||
'provider' => ['path' => 'app/Providers', 'generate' => true],
|
||||
'route-provider' => ['path' => 'app/Providers', 'generate' => true],
|
||||
'repository' => ['path' => 'app/Repositories', 'generate' => false],
|
||||
'resource' => ['path' => 'app/Transformers', 'generate' => false],
|
||||
'rules' => ['path' => 'app/Rules', 'generate' => false],
|
||||
'component-class' => ['path' => 'app/View/Components', 'generate' => false],
|
||||
'service' => ['path' => 'app/Services', 'generate' => false],
|
||||
|
||||
// app/Http/
|
||||
'controller' => ['path' => 'app/Http/Controllers', 'generate' => true],
|
||||
'filter' => ['path' => 'app/Http/Middleware', 'generate' => false],
|
||||
'request' => ['path' => 'app/Http/Requests', 'generate' => false],
|
||||
|
||||
// config/
|
||||
'config' => ['path' => 'config', 'generate' => true],
|
||||
'command' => ['path' => 'App/Console', 'generate' => false],
|
||||
'channels' => ['path' => 'App/Broadcasting', 'generate' => false],
|
||||
'migration' => ['path' => 'Database/migrations', 'generate' => false],
|
||||
'seeder' => ['path' => 'Database/Seeders', 'generate' => true],
|
||||
'factory' => ['path' => 'Database/Factories', 'generate' => false],
|
||||
'model' => ['path' => 'App/Models', 'generate' => false],
|
||||
'observer' => ['path' => 'App/Observers', 'generate' => false],
|
||||
'routes' => ['path' => 'routes', 'generate' => true],
|
||||
'controller' => ['path' => 'App/Http/Controllers', 'generate' => true],
|
||||
'filter' => ['path' => 'App/Http/Middleware', 'generate' => false],
|
||||
'request' => ['path' => 'App/Http/Requests', 'generate' => false],
|
||||
'provider' => ['path' => 'App/Providers', 'generate' => true],
|
||||
'assets' => ['path' => 'resources/assets', 'generate' => false],
|
||||
|
||||
// database/
|
||||
'migration' => ['path' => 'database/migrations', 'generate' => true],
|
||||
'seeder' => ['path' => 'database/seeders', 'namespace' => 'Database\Seeders', 'generate' => true],
|
||||
'factory' => ['path' => 'database/factories', 'namespace' => 'Database\Factories', 'generate' => true],
|
||||
|
||||
// lang/
|
||||
'lang' => ['path' => 'lang', 'generate' => false],
|
||||
|
||||
// resource/
|
||||
'assets' => ['path' => 'resources/assets', 'generate' => true],
|
||||
'views' => ['path' => 'resources/views', 'generate' => true],
|
||||
'test' => ['path' => 'tests/Unit', 'generate' => false],
|
||||
'test-feature' => ['path' => 'tests/Feature', 'generate' => false],
|
||||
'repository' => ['path' => 'App/Repositories', 'generate' => false],
|
||||
'event' => ['path' => 'App/Events', 'generate' => false],
|
||||
'listener' => ['path' => 'App/Listeners', 'generate' => false],
|
||||
'policies' => ['path' => 'App/Policies', 'generate' => false],
|
||||
'rules' => ['path' => 'App/Rules', 'generate' => false],
|
||||
'jobs' => ['path' => 'App/Jobs', 'generate' => false],
|
||||
'emails' => ['path' => 'App/Emails', 'generate' => false],
|
||||
'notifications' => ['path' => 'App/Notifications', 'generate' => false],
|
||||
'resource' => ['path' => 'App/resources', 'generate' => false],
|
||||
'component-view' => ['path' => 'resources/views/components', 'generate' => false],
|
||||
'component-class' => ['path' => 'App/View/Components', 'generate' => false],
|
||||
|
||||
// routes/
|
||||
'routes' => ['path' => 'routes', 'generate' => true],
|
||||
|
||||
// tests/
|
||||
'test-unit' => ['path' => 'tests/Unit', 'generate' => true],
|
||||
'test-feature' => ['path' => 'tests/Feature', 'generate' => true],
|
||||
],
|
||||
],
|
||||
|
||||
@@ -158,13 +186,13 @@ return [
|
||||
| directory. This is useful if you host the package in packagist website.
|
||||
|
|
||||
*/
|
||||
|
||||
'scan' => [
|
||||
'enabled' => false,
|
||||
'paths' => [
|
||||
base_path('vendor/*/*'),
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Composer File Template
|
||||
@@ -173,12 +201,11 @@ return [
|
||||
| Here is the config for the composer.json file, generated by this package
|
||||
|
|
||||
*/
|
||||
|
||||
'composer' => [
|
||||
'vendor' => 'nwidart',
|
||||
'vendor' => env('MODULE_VENDOR', 'solidtime-io'),
|
||||
'author' => [
|
||||
'name' => 'Nicolas Widart',
|
||||
'email' => 'n.widart@gmail.com',
|
||||
'name' => env('MODULE_AUTHOR_NAME', 'Nicolas Widart'),
|
||||
'email' => env('MODULE_AUTHOR_EMAIL', 'n.widart@gmail.com'),
|
||||
],
|
||||
'composer-output' => false,
|
||||
],
|
||||
@@ -192,11 +219,12 @@ return [
|
||||
|
|
||||
*/
|
||||
'cache' => [
|
||||
'enabled' => false,
|
||||
'driver' => 'file',
|
||||
'key' => 'laravel-modules',
|
||||
'lifetime' => 60,
|
||||
'enabled' => env('MODULES_CACHE_ENABLED', false),
|
||||
'driver' => env('MODULES_CACHE_DRIVER', 'file'),
|
||||
'key' => env('MODULES_CACHE_KEY', 'laravel-modules'),
|
||||
'lifetime' => env('MODULES_CACHE_LIFETIME', 60),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Choose what laravel-modules will register as custom namespaces.
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Enums\Weekday;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
@@ -100,7 +101,9 @@ class UserFactory extends Factory
|
||||
->when(is_callable($callback), $callback)
|
||||
->create();
|
||||
|
||||
$organization->users()->attach($user, ['role' => 'owner']);
|
||||
$organization->users()->attach($user, ['role' => Role::Owner->value]);
|
||||
$user->currentTeam()->associate($organization);
|
||||
$user->save();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +25,14 @@ class DatabaseSeeder extends Seeder
|
||||
public function run(): void
|
||||
{
|
||||
$this->deleteAll();
|
||||
$userAcmeOwner = User::factory()->create([
|
||||
$userAcmeOwner = User::factory()->withPersonalOrganization()->create([
|
||||
'name' => 'Acme Owner',
|
||||
'email' => 'owner@acme.test',
|
||||
]);
|
||||
$organizationAcme = Organization::factory()->withOwner($userAcmeOwner)->create([
|
||||
'name' => 'ACME Corp',
|
||||
'personal_team' => false,
|
||||
'currency' => 'EUR',
|
||||
]);
|
||||
$userAcmeManager = User::factory()->withPersonalOrganization()->create([
|
||||
'name' => 'Acme Manager',
|
||||
@@ -80,29 +82,35 @@ class DatabaseSeeder extends Seeder
|
||||
->forUser($userAcmeEmployee)
|
||||
->forOrganization($organizationAcme)
|
||||
->create();
|
||||
$client = Client::factory()->create([
|
||||
$client = Client::factory()->forOrganization($organizationAcme)->create([
|
||||
'name' => 'Big Company',
|
||||
]);
|
||||
$bigCompanyProject = Project::factory()->forClient($client)->create([
|
||||
$bigCompanyProject = Project::factory()->forOrganization($organizationAcme)->forClient($client)->create([
|
||||
'name' => 'Big Company Project',
|
||||
]);
|
||||
Task::factory()->forProject($bigCompanyProject)->create();
|
||||
Task::factory()->forOrganization($organizationAcme)->forProject($bigCompanyProject)->create();
|
||||
|
||||
$internalProject = Project::factory()->create([
|
||||
$internalProject = Project::factory()->forOrganization($organizationAcme)->create([
|
||||
'name' => 'Internal Project',
|
||||
]);
|
||||
|
||||
$organization2 = Organization::factory()->create([
|
||||
$organization2Owner = User::factory()->create([
|
||||
'name' => 'Other Owner',
|
||||
'email' => 'owner@rival-company.test',
|
||||
]);
|
||||
$organization2 = Organization::factory()->withOwner($organization2Owner)->create([
|
||||
'name' => 'Rival Corp',
|
||||
'personal_team' => true,
|
||||
'currency' => 'USD',
|
||||
]);
|
||||
$userAcmeManager = User::factory()->withPersonalOrganization()->create([
|
||||
'name' => 'Other User',
|
||||
'email' => 'test@rival-company.test',
|
||||
]);
|
||||
$userAcmeManager->organizations()->attach($organization2, [
|
||||
'role' => 'admin',
|
||||
'role' => Role::Admin->value,
|
||||
]);
|
||||
$otherCompanyProject = Project::factory()->forClient($client)->create([
|
||||
$otherCompanyProject = Project::factory()->forOrganization($organization2)->forClient($client)->create([
|
||||
'name' => 'Scale Company',
|
||||
]);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Models\Membership;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
@@ -29,6 +30,6 @@ class CreateTeamTest extends TestCase
|
||||
$this->assertCount(2, $user->fresh()->ownedTeams);
|
||||
$this->assertEquals('Test Organization', $newOrganization->name);
|
||||
$member = Membership::query()->whereBelongsTo($user, 'user')->whereBelongsTo($newOrganization, 'organization')->firstOrFail();
|
||||
$this->assertSame('owner', $member->role);
|
||||
$this->assertSame(Role::Owner->value, $member->role);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Models\Membership;
|
||||
use App\Models\User;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
@@ -58,7 +59,7 @@ class RegistrationTest extends TestCase
|
||||
$organization = $user->organizations()->firstOrFail();
|
||||
$this->assertSame(true, $organization->personal_team);
|
||||
$member = Membership::query()->whereBelongsTo($user, 'user')->whereBelongsTo($organization, 'organization')->firstOrFail();
|
||||
$this->assertSame('owner', $member->role);
|
||||
$this->assertSame(Role::Owner->value, $member->role);
|
||||
}
|
||||
|
||||
public function test_new_users_can_register_and_frontend_can_send_timezone_for_user(): void
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
@@ -64,12 +65,12 @@ class UpdateTeamMemberRoleTest extends TestCase
|
||||
|
||||
// Act
|
||||
$response = $this->withoutExceptionHandling()->put('/teams/'.$user->currentTeam->id.'/members/'.$otherUser->getKey(), [
|
||||
'role' => 'owner',
|
||||
'role' => Role::Owner->value,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$this->assertTrue($otherUser->fresh()->hasTeamRole(
|
||||
$user->currentTeam->fresh(), 'owner'
|
||||
$user->currentTeam->fresh(), Role::Owner->value
|
||||
));
|
||||
$this->assertSame($user->currentTeam->fresh()->user_id, $otherUser->getKey());
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Service;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Enums\Weekday;
|
||||
use App\Models\Organization;
|
||||
use App\Models\Project;
|
||||
@@ -267,7 +268,7 @@ class DashboardServiceTest extends TestCase
|
||||
]);
|
||||
$organization = Organization::factory()->withOwner($user)->create();
|
||||
$organization->users()->attach($user, [
|
||||
'role' => 'owner',
|
||||
'role' => Role::Owner->value,
|
||||
]);
|
||||
$project1 = Project::factory()->forOrganization($organization)->create();
|
||||
$project2 = Project::factory()->forOrganization($organization)->create();
|
||||
|
||||
Reference in New Issue
Block a user