Add User admin flag

This commit is contained in:
Christopher C. Wells 2021-04-20 16:04:32 -07:00
parent d18247e68d
commit ef719c9175
14 changed files with 83 additions and 7 deletions

View File

@ -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');

View File

@ -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'];

View File

@ -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.
*/

View File

@ -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;
}
}

View File

@ -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]);
}
}

View File

@ -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',

View File

@ -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();
});

View File

@ -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>

View File

@ -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>

View File

@ -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">&nbsp;</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">

View File

@ -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');
});

View File

@ -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();
}
}

View File

@ -9,7 +9,7 @@ abstract class LoggedInTestCase extends TestCase
public function setUp(): void
{
parent::setUp();
$this->loginUser();
$this->loginAdmin();
}
}

View File

@ -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');
}
}