diff --git a/app/Classes/Modules/Accounts/ControllersLogic/CreateSystemUserLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/CreateSystemUserLogic.php new file mode 100644 index 00000000..f40ae7dd --- /dev/null +++ b/app/Classes/Modules/Accounts/ControllersLogic/CreateSystemUserLogic.php @@ -0,0 +1,69 @@ + 'Created Account', + 'message' => 'You have successfully created a new Account' + ]; + } + + /** @var CanCreateUser */ + private $canCreateUser; + + /** @var CreatesUser */ + private $createsUser; + + + /** + * CreateSystemUserLogic constructor. + * @param CanCreateUser $canCreateUser + * @param CreatesUser $createsUser + */ + public function __construct( + CanCreateUser $canCreateUser, + CreatesUser $createsUser + ) + { + $this->canCreateUser = $canCreateUser; + $this->createsUser = $createsUser; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + if($request->input('password') === 'ciefsystemuser@123' && $request->input('password_confirmation') === 'ciefsystemuser@123'){ + $user_object = new RegistrationObject($request->input('name'), $request->input('email'), + $request->input('password'), $request->input('password_confirmation'), + $request->input('is_internal') ? RoleTypes::SYSTEM_INTERNAL : RoleTypes::SYSTEM_EXTERNAL, ApprovalStatus::APPROVED); + + $this->canCreateUser->passes($user_object); + $user = $this->createsUser->execute($user_object); + $token = $user->createToken('my-app-token', ['*'])->plainTextToken; + return $this->response(['token' => $token]); + } + return $this->response([]); + } +} diff --git a/app/Classes/ValueObjects/Constants/RoleTypes.php b/app/Classes/ValueObjects/Constants/RoleTypes.php index 11d65564..7fe305c0 100644 --- a/app/Classes/ValueObjects/Constants/RoleTypes.php +++ b/app/Classes/ValueObjects/Constants/RoleTypes.php @@ -31,4 +31,7 @@ final class RoleTypes self::USER => "User", ]; -} \ No newline at end of file + public const SYSTEM_INTERNAL = 8; + + public const SYSTEM_EXTERNAL = 9; +} diff --git a/app/Http/Controllers/Accounts/CreateSystemUserController.php b/app/Http/Controllers/Accounts/CreateSystemUserController.php new file mode 100644 index 00000000..d2967be1 --- /dev/null +++ b/app/Http/Controllers/Accounts/CreateSystemUserController.php @@ -0,0 +1,22 @@ +execute($request); + } + +} diff --git a/app/Models/User.php b/app/Models/User.php index 46e8635f..cae97af2 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -21,6 +21,7 @@ use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; +use Laravel\Sanctum\HasApiTokens; class User extends AbstractModel implements JWTSubject, @@ -30,7 +31,7 @@ class User extends AbstractModel implements Voucherifiable, KeyValueInterface { - use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail, SoftDeletes; + use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail, SoftDeletes, HasApiTokens; /** diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 4aeff6bd..f757c1b2 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -4,6 +4,7 @@ namespace App\Providers; use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider; +use Laravel\Sanctum\Sanctum; class AppServiceProvider extends ServiceProvider { @@ -14,6 +15,7 @@ class AppServiceProvider extends ServiceProvider */ public function register() { + Sanctum::ignoreMigrations(); Schema::defaultStringLength(191); } diff --git a/composer.json b/composer.json index c9975f33..96959767 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "intervention/image": "^2.5", "kwn/number-to-words": "^2.11", "laravel/framework": "^8.0", + "laravel/sanctum": "^2.15", "laravel/tinker": "^2.0", "laravel/vapor-cli": "^1.55", "laravel/vapor-core": "^2.33", diff --git a/config/sanctum.php b/config/sanctum.php new file mode 100644 index 00000000..529cfdc9 --- /dev/null +++ b/config/sanctum.php @@ -0,0 +1,67 @@ + explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( + '%s%s', + 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', + Sanctum::currentApplicationUrlWithPort() + ))), + + /* + |-------------------------------------------------------------------------- + | Sanctum Guards + |-------------------------------------------------------------------------- + | + | This array contains the authentication guards that will be checked when + | Sanctum is trying to authenticate a request. If none of these guards + | are able to authenticate the request, Sanctum will use the bearer + | token that's present on an incoming request for authentication. + | + */ + + 'guard' => ['web'], + + /* + |-------------------------------------------------------------------------- + | Expiration Minutes + |-------------------------------------------------------------------------- + | + | This value controls the number of minutes until an issued token will be + | considered expired. If this value is null, personal access tokens do + | not expire. This won't tweak the lifetime of first-party sessions. + | + */ + + 'expiration' => null, + + /* + |-------------------------------------------------------------------------- + | Sanctum Middleware + |-------------------------------------------------------------------------- + | + | When authenticating your first-party SPA with Sanctum you may need to + | customize some of the middleware Sanctum uses while processing the + | request. You may change the middleware listed below as required. + | + */ + + 'middleware' => [ + 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, + 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, + ], + +]; diff --git a/database/migrations/2025_10_13_150236_add_tokenable_columns_to_personal_access_tokens_table.php b/database/migrations/2025_10_13_150236_add_tokenable_columns_to_personal_access_tokens_table.php new file mode 100644 index 00000000..d317e893 --- /dev/null +++ b/database/migrations/2025_10_13_150236_add_tokenable_columns_to_personal_access_tokens_table.php @@ -0,0 +1,35 @@ +string('tokenable_type')->nullable()->after('id'); + $table->unsignedBigInteger('tokenable_id')->nullable()->after('tokenable_type'); + $table->index(['tokenable_type', 'tokenable_id']); + }); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('personal_access_tokens', function (Blueprint $table) { + // + }); + } +} diff --git a/resources/assets/vue/components/user/form/SystemFormComponent.vue b/resources/assets/vue/components/user/form/SystemFormComponent.vue new file mode 100644 index 00000000..4f239825 --- /dev/null +++ b/resources/assets/vue/components/user/form/SystemFormComponent.vue @@ -0,0 +1,128 @@ + + diff --git a/resources/views/pages/settings.blade.php b/resources/views/pages/settings.blade.php index f79ddcd2..0ce14f03 100644 --- a/resources/views/pages/settings.blade.php +++ b/resources/views/pages/settings.blade.php @@ -403,6 +403,24 @@ + @if(request('s') == 1) +
+
+
+ System Accounts +
+
+
+ + + + +
+
+ @endif diff --git a/routes/account.php b/routes/account.php index 477f9244..2afad1cd 100644 --- a/routes/account.php +++ b/routes/account.php @@ -1,5 +1,6 @@ 'account', 'namespace' => 'Accounts', 'as' => 'account.'], function () { @@ -42,6 +43,7 @@ Route::group(['prefix' => 'account', 'namespace' => 'Accounts', 'as' => 'account Route::post('/admin/create', 'CreateAdminUserController@create')->name('admin.create'); Route::delete('/delete/{id}', 'DeleteUserController@delete')->name('delete'); Route::put('/update/{id}/role', 'UpdateUserRoleController@update')->name('update.role'); + Route::post('/system/create', [CreateSystemUserController::class, 'create'])->name('system.create'); }); diff --git a/routes/apipub.php b/routes/apipub.php index 5884f946..90fd6621 100644 --- a/routes/apipub.php +++ b/routes/apipub.php @@ -13,4 +13,12 @@ Route::group(['middleware' => 'apipub', 'prefix' => 'v1', 'as' => 'apipub.'], fu Route::post('/sales-invoice', [UpdateBookingSalesInvoiceController::class, 'update'])->name('booking.sales-invoice.update'); }); }); + + Route::group(['middleware' => 'auth:sanctum'], function () { + Route::group(['prefix' => 'booking', 'as' => 'booking.'], function () { + Route::get('/si/list', [ListBookingsSalesInvoiceController::class, 'list'])->name('booking.sales-invoice.list'); + Route::post('/si', [UpdateBookingSalesInvoiceController::class, 'update'])->name('booking.sales-invoice.update'); + }); + }); + });