diff --git a/app/Livewire/AppContainer.php b/app/Livewire/AppContainer.php
index b857dc7..946a090 100644
--- a/app/Livewire/AppContainer.php
+++ b/app/Livewire/AppContainer.php
@@ -15,7 +15,10 @@ class AppContainer extends Component
public function mount()
{
- $this->loadApps();
+ // Only load data if user is authorized to view it
+ if (auth()->user()->can('viewAny', Application::class)) {
+ $this->loadApps();
+ }
}
public function loadApps()
@@ -38,6 +41,8 @@ class AppContainer extends Component
public function deleteApp()
{
+ $this->authorize('delete', $this->confirmDeleteApp);
+
$this->confirmDeleteApp->delete();
$deletedId = $this->confirmDeleteApp->id;
$this->confirmDeleteApp = null;
diff --git a/app/Livewire/Forms/NewApplication.php b/app/Livewire/Forms/NewApplication.php
index 3643652..dc2e65c 100644
--- a/app/Livewire/Forms/NewApplication.php
+++ b/app/Livewire/Forms/NewApplication.php
@@ -16,6 +16,8 @@ class NewApplication extends Component
public function create()
{
+ $this->authorize('create', Application::class);
+
$this->validate();
Application::create([
diff --git a/app/Livewire/ManageUsers.php b/app/Livewire/ManageUsers.php
index ceff231..d4b1746 100644
--- a/app/Livewire/ManageUsers.php
+++ b/app/Livewire/ManageUsers.php
@@ -16,12 +16,17 @@ class ManageUsers extends Component
public function mount()
{
- $this->users = User::all();
- $this->invitations = Invitation::all();
+ // Only load data if user is authorized to view it
+ if (auth()->user()->can('viewAny', User::class)) {
+ $this->users = User::all();
+ $this->invitations = Invitation::all();
+ }
}
public function inviteUser()
{
+ $this->authorize('invite', User::class);
+
$inv = Invitation::create([
'code' => str()->random(50),
'email' => $this->invite_email,
@@ -29,6 +34,20 @@ class ManageUsers extends Component
'expires_at' => now()->addDays(7),
]);
Flux::modal('invite-user')->close();
+
+ // Refresh the data
+ $this->invitations = Invitation::all();
+ $this->invite_email = '';
+ }
+
+ public function deleteUser(User $user)
+ {
+ $this->authorize('delete', $user);
+
+ $user->delete();
+
+ // Refresh the data
+ $this->users = User::all();
}
public function render()
diff --git a/app/Models/User.php b/app/Models/User.php
index 71cafdf..6885e48 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -24,7 +24,8 @@ class User extends Authenticatable
'email',
'password',
'avatar',
- 'preferred_username'
+ 'preferred_username',
+ 'is_admin'
];
/**
@@ -47,6 +48,7 @@ class User extends Authenticatable
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
+ 'is_admin' => 'boolean',
];
}
@@ -71,4 +73,9 @@ class User extends Authenticatable
{
return route('user.avatar', ['path' => $this->avatar]);
}
+
+ public function isAdmin(): bool
+ {
+ return $this->is_admin;
+ }
}
diff --git a/app/Policies/ApplicationPolicy.php b/app/Policies/ApplicationPolicy.php
new file mode 100644
index 0000000..f7bbef5
--- /dev/null
+++ b/app/Policies/ApplicationPolicy.php
@@ -0,0 +1,65 @@
+isAdmin();
+ }
+
+ /**
+ * Determine whether the user can view the model.
+ */
+ public function view(User $user, Application $application): bool
+ {
+ return $user->isAdmin();
+ }
+
+ /**
+ * Determine whether the user can create models.
+ */
+ public function create(User $user): bool
+ {
+ return $user->isAdmin();
+ }
+
+ /**
+ * Determine whether the user can update the model.
+ */
+ public function update(User $user, Application $application): bool
+ {
+ return $user->isAdmin();
+ }
+
+ /**
+ * Determine whether the user can delete the model.
+ */
+ public function delete(User $user, Application $application): bool
+ {
+ return $user->isAdmin();
+ }
+
+ /**
+ * Determine whether the user can restore the model.
+ */
+ public function restore(User $user, Application $application): bool
+ {
+ return $user->isAdmin();
+ }
+
+ /**
+ * Determine whether the user can permanently delete the model.
+ */
+ public function forceDelete(User $user, Application $application): bool
+ {
+ return $user->isAdmin();
+ }
+}
\ No newline at end of file
diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php
new file mode 100644
index 0000000..0df9587
--- /dev/null
+++ b/app/Policies/UserPolicy.php
@@ -0,0 +1,75 @@
+isAdmin();
+ }
+
+ /**
+ * Determine whether the user can view the model.
+ */
+ public function view(User $user, User $model): bool
+ {
+ // Users can view their own profile, or admins can view any user
+ return $user->id === $model->id || $user->isAdmin();
+ }
+
+ /**
+ * Determine whether the user can create models.
+ */
+ public function create(User $user): bool
+ {
+ return $user->isAdmin();
+ }
+
+ /**
+ * Determine whether the user can update the model.
+ */
+ public function update(User $user, User $model): bool
+ {
+ // Users can update their own profile, or admins can update any user
+ return $user->id === $model->id || $user->isAdmin();
+ }
+
+ /**
+ * Determine whether the user can delete the model.
+ */
+ public function delete(User $user, User $model): bool
+ {
+ // Only admins can delete users, and they cannot delete themselves
+ return $user->isAdmin() && $user->id !== $model->id;
+ }
+
+ /**
+ * Determine whether the user can restore the model.
+ */
+ public function restore(User $user, User $model): bool
+ {
+ return $user->isAdmin();
+ }
+
+ /**
+ * Determine whether the user can permanently delete the model.
+ */
+ public function forceDelete(User $user, User $model): bool
+ {
+ return $user->isAdmin() && $user->id !== $model->id;
+ }
+
+ /**
+ * Determine whether the user can invite new users.
+ */
+ public function invite(User $user): bool
+ {
+ return $user->isAdmin();
+ }
+}
\ No newline at end of file
diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php
index 584104c..0c99fba 100644
--- a/database/factories/UserFactory.php
+++ b/database/factories/UserFactory.php
@@ -29,6 +29,7 @@ class UserFactory extends Factory
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
+ 'is_admin' => false,
];
}
@@ -41,4 +42,14 @@ class UserFactory extends Factory
'email_verified_at' => null,
]);
}
+
+ /**
+ * Indicate that the user should be an admin.
+ */
+ public function admin(): static
+ {
+ return $this->state(fn (array $attributes) => [
+ 'is_admin' => true,
+ ]);
+ }
}
diff --git a/database/migrations/2025_08_02_013524_add_is_admin_to_users_table.php b/database/migrations/2025_08_02_013524_add_is_admin_to_users_table.php
new file mode 100644
index 0000000..0b3c749
--- /dev/null
+++ b/database/migrations/2025_08_02_013524_add_is_admin_to_users_table.php
@@ -0,0 +1,28 @@
+boolean('is_admin')->default(false);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('users', function (Blueprint $table) {
+ $table->dropColumn('is_admin');
+ });
+ }
+};
diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php
index 98acb56..1a1893d 100644
--- a/database/seeders/UserSeeder.php
+++ b/database/seeders/UserSeeder.php
@@ -12,5 +12,24 @@ class UserSeeder extends Seeder
/**
* Run the database seeds.
*/
- public function run(): void {}
+ public function run(): void
+ {
+ // Create an admin user
+ User::create([
+ 'name' => 'Admin User',
+ 'email' => 'admin@example.com',
+ 'password' => Hash::make('password'),
+ 'email_verified_at' => now(),
+ 'is_admin' => true,
+ ]);
+
+ // Create a regular user
+ User::create([
+ 'name' => 'Regular User',
+ 'email' => 'user@example.com',
+ 'password' => Hash::make('password'),
+ 'email_verified_at' => now(),
+ 'is_admin' => false,
+ ]);
+ }
}
diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php
index bffac9d..002ebb9 100644
--- a/resources/views/dashboard.blade.php
+++ b/resources/views/dashboard.blade.php
@@ -1,16 +1,36 @@
+ You can manage your profile and view your authentication tokens above.
+ Welcome to AuthentiKate
+