mirror of https://github.com/kcal-app/kcal.git
Add User admin flag
This commit is contained in:
parent
d18247e68d
commit
ef719c9175
|
@ -53,6 +53,7 @@ class UserController extends Controller
|
|||
$attributes = $request->validated();
|
||||
$attributes['remember_token'] = Str::random(10);
|
||||
$attributes['password'] = Hash::make($attributes['password']);
|
||||
$attributes['admin'] = $attributes['admin'] ?? false;
|
||||
$user->fill($attributes)->save();
|
||||
session()->flash('message', "User {$user->name} updated!");
|
||||
return redirect()->route('users.index');
|
||||
|
|
|
@ -18,6 +18,7 @@ class UpdateUserRequest extends FormRequest
|
|||
'name' => ['nullable', 'string'],
|
||||
'password' => ['nullable', 'string', 'confirmed'],
|
||||
'password_confirmation' => ['nullable', 'string'],
|
||||
'admin' => ['nullable', 'boolean'],
|
||||
];
|
||||
if (!$this->user) {
|
||||
$rules['password'] = ['required', 'string', 'confirmed'];
|
||||
|
|
|
@ -15,9 +15,11 @@ use Illuminate\Support\Facades\Auth;
|
|||
* App\Models\User
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $slug
|
||||
* @property string $name
|
||||
* @property string $username
|
||||
* @property string $password
|
||||
* @property bool $admin
|
||||
* @property string|null $remember_token
|
||||
* @property Carbon|null $created_at
|
||||
* @property Carbon|null $updated_at
|
||||
|
@ -38,6 +40,10 @@ use Illuminate\Support\Facades\Auth;
|
|||
* @method static \Illuminate\Database\Eloquent\Builder|User whereRememberToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereUsername($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User findSimilarSlugs(string $attribute, array $config, string $slug)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereAdmin($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereSlug($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User withUniqueSlugConstraints(\Illuminate\Database\Eloquent\Model $model, string $attribute, array $config, string $slug)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
final class User extends Authenticatable
|
||||
|
@ -51,6 +57,7 @@ final class User extends Authenticatable
|
|||
'username',
|
||||
'password',
|
||||
'name',
|
||||
'admin',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -61,6 +68,13 @@ final class User extends Authenticatable
|
|||
'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected $casts = [
|
||||
'admin' => 'bool',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the User's goals.
|
||||
*/
|
||||
|
|
|
@ -9,11 +9,18 @@ class UserPolicy
|
|||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can administer (the application).
|
||||
*/
|
||||
public function administer(User $user): bool {
|
||||
return $user->admin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, User $model): bool
|
||||
{
|
||||
return $user->id !== $model->id;
|
||||
return $this->administer($user) && $user->id !== $model->id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,16 @@ class UserFactory extends Factory
|
|||
'username' => $this->faker->unique()->userName,
|
||||
'password' => Hash::make('password'),
|
||||
'name' => $this->faker->name,
|
||||
'admin' => $this->faker->boolean,
|
||||
'remember_token' => Str::random(10),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an admin user.
|
||||
*/
|
||||
public function admin(): static
|
||||
{
|
||||
return $this->state(['admin' => true]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class DatabaseSeeder extends Seeder
|
|||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$user = User::factory()->create([
|
||||
$user = User::factory()->admin()->create([
|
||||
'username' => 'kcal',
|
||||
'password' => Hash::make('kcal'),
|
||||
'name' => 'Admin',
|
||||
|
|
|
@ -19,6 +19,7 @@ class CreateUsersTable extends Migration
|
|||
$table->string('username')->unique();
|
||||
$table->string('password');
|
||||
$table->string('name');
|
||||
$table->boolean('admin')->default(false);
|
||||
$table->rememberToken();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
|
|
@ -34,7 +34,9 @@
|
|||
<x-slot name="content">
|
||||
<div class="space-y-2">
|
||||
<x-dropdown-link :href="route('goals.index')">Goals</x-dropdown-link>
|
||||
<x-dropdown-link :href="route('users.index')">Users</x-dropdown-link>
|
||||
@can('administer', \App\Models\User::class)
|
||||
<x-dropdown-link :href="route('users.index')">Users</x-dropdown-link>
|
||||
@endcan
|
||||
<form method="POST" action="{{ route('logout') }}" x-data>
|
||||
@csrf
|
||||
<x-dropdown-link :href="route('logout')" @click.prevent="$el.closest('form').submit();">Logout</x-dropdown-link>
|
||||
|
|
|
@ -53,6 +53,17 @@
|
|||
:hasError="$errors->has('password')"
|
||||
:required="!$user->exists"/>
|
||||
</div>
|
||||
|
||||
<!-- Admin -->
|
||||
<div>
|
||||
<x-inputs.label for="admin" value="Site Admin"/>
|
||||
|
||||
<x-inputs.input name="admin"
|
||||
type="checkbox"
|
||||
value="1"
|
||||
:checked="old('admin', $user->admin)" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<tr class="bg-gray-200 text-gray-600 uppercase text-sm leading-normal">
|
||||
<th class="py-3 px-6 text-left">Username</th>
|
||||
<th class="py-3 px-6 text-left">Name</th>
|
||||
<th class="py-3 px-6 text-left">Admin</th>
|
||||
<th class="py-3 px-6 text-left">Created</th>
|
||||
<th class="py-3 px-6 text-left">Updated</th>
|
||||
<th class="py-3 px-6 text-left"> </th>
|
||||
|
@ -23,6 +24,7 @@
|
|||
<tr class="border-b border-gray-200">
|
||||
<td class="py-3 px-6">{{ $user->username }}</td>
|
||||
<td class="py-3 px-6">{{ $user->name }}</td>
|
||||
<td class="py-3 px-6">@if($user->admin) Yes @else No @endif</td>
|
||||
<td class="py-3 px-6">{{ $user->created_at }}</td>
|
||||
<td class="py-3 px-6">{{ $user->updated_at }}</td>
|
||||
<td class="py-3 px-6">
|
||||
|
|
|
@ -9,7 +9,7 @@ use Illuminate\Support\Facades\Route;
|
|||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Route::middleware(['auth', 'can:administer'])->group(function () {
|
||||
Route::middleware(['auth', 'can:administer,\App\Models\User'])->group(function () {
|
||||
Route::resource('users', UserController::class);
|
||||
Route::get('/users/{user}/delete', [UserController::class, 'delete'])->name('users.delete');
|
||||
});
|
||||
|
|
|
@ -66,4 +66,12 @@ class UserControllerTest extends HttpControllerTestCase
|
|||
$response->assertForbidden();
|
||||
}
|
||||
|
||||
public function testCanNotAccessIndexAsNonAdmin(): void {
|
||||
$this->logout();
|
||||
$this->loginUser();
|
||||
$index_url = action([$this->class(), 'index']);
|
||||
$response = $this->get($index_url);
|
||||
$response->assertForbidden();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ abstract class LoggedInTestCase extends TestCase
|
|||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->loginUser();
|
||||
$this->loginAdmin();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,11 +9,12 @@ trait LogsIn
|
|||
protected User $user;
|
||||
|
||||
/**
|
||||
* Creates a user and logs the user in.
|
||||
* Creates an admin and logs in.
|
||||
*/
|
||||
public function loginUser(): void
|
||||
public function loginAdmin(): void
|
||||
{
|
||||
$this->user = User::factory()
|
||||
->admin()
|
||||
->hasGoals(2)
|
||||
->hasJournalEntries(5)
|
||||
->create();
|
||||
|
@ -22,4 +23,23 @@ trait LogsIn
|
|||
'password' => 'password',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a regular user and logs in.
|
||||
*/
|
||||
public function loginUser(): void
|
||||
{
|
||||
$this->user = User::factory()
|
||||
->hasGoals(2)
|
||||
->hasJournalEntries(5)
|
||||
->create(['admin' => false]);
|
||||
$this->post('/login', [
|
||||
'username' => $this->user->username,
|
||||
'password' => 'password',
|
||||
]);
|
||||
}
|
||||
|
||||
public function logout(): void {
|
||||
$this->post('/logout');
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue