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 @@
+
+ Add System User Account
+