diff --git a/attendance-api/app/Http/Controllers/AttendanceEventController.php b/attendance-api/app/Http/Controllers/AttendanceEventController.php index e62a857..a469f93 100644 --- a/attendance-api/app/Http/Controllers/AttendanceEventController.php +++ b/attendance-api/app/Http/Controllers/AttendanceEventController.php @@ -17,6 +17,10 @@ class AttendanceEventController extends Controller { + public function __construct() { + $this->middleware('can:list attendance events')->only(['index', 'show']); + } + public function index(Request $request) { $request->validate([ 'student_id' => 'exists:students,id', diff --git a/attendance-api/app/Http/Controllers/StudentController.php b/attendance-api/app/Http/Controllers/StudentController.php index 4034866..1362d73 100644 --- a/attendance-api/app/Http/Controllers/StudentController.php +++ b/attendance-api/app/Http/Controllers/StudentController.php @@ -18,6 +18,7 @@ class StudentController extends Controller { public function __construct() { + $this->middleware('can:list students')->only(['index', 'show']); $this->middleware('can:add students')->only('store'); $this->middleware('can:modify students')->only('update'); $this->middleware('can:remove students')->only('destroy'); diff --git a/attendance-api/database/seeders/RolesSeeder.php b/attendance-api/database/seeders/RolesSeeder.php index 8c7dbd1..01a470a 100644 --- a/attendance-api/database/seeders/RolesSeeder.php +++ b/attendance-api/database/seeders/RolesSeeder.php @@ -21,12 +21,14 @@ public function run() app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions(); + Permission::create(['name' => 'list students']); Permission::create(['name' => 'add students']); Permission::create(['name' => 'modify students']); Permission::create(['name' => 'remove students']); Permission::create(['name' => 'view student images']); Permission::create(['name' => 'modify student images']); + Permission::create(['name' => 'list attendance events']); Permission::create(['name' => 'student check in']); Permission::create(['name' => 'student check out']); Permission::create(['name' => 'undo attendance event']); @@ -44,11 +46,13 @@ public function run() Role::create(['name' => 'mentor']) ->givePermissionTo([ + 'list students', 'add students', 'view student images', 'modify students', 'modify student images', 'remove students', + 'list attendance events', 'student check in', 'student check out', 'undo attendance event', @@ -64,6 +68,8 @@ public function run() Role::create(['name' => 'student-lead']) ->givePermissionTo([ + 'list students', + 'list attendance events', 'student check in', 'view student images', 'undo attendance event', @@ -74,6 +80,17 @@ public function run() 'view stats' ]); + Role::create(['name' => 'read-only']) + ->givePermissionTo([ + 'list students', + 'list attendance events', + 'view student images', + 'list users', + 'list roles', + 'list meeting events', + 'view stats' + ]); + // Here I hard-code the initial admin user (who will then add the rest of the admins) // It'd probably be best to get this from the app config or the .env environment if(config('app.debug', false)) { diff --git a/attendance-api/routes/api.php b/attendance-api/routes/api.php index cb8bb2f..3eeffb0 100644 --- a/attendance-api/routes/api.php +++ b/attendance-api/routes/api.php @@ -12,6 +12,7 @@ use App\Http\Controllers\PollController; use App\Http\Controllers\StudentProfileImageController; use Spatie\Permission\Models\Role; +use Spatie\Permission\Models\Permission; /* |-------------------------------------------------------------------------- @@ -47,14 +48,14 @@ 'index', 'show', 'update' ]); - Route::middleware('can:list roles')->get('roles', function() { - return Role::all()->pluck('name'); - }); - Route::get('reports/list-meetings', [ReportController::class, 'listMeetings']); Route::get('reports/meeting-attendance', [ReportController::class, 'meetingAttendance']); Route::get('poll', [PollController::class, 'poll']); + Route::get('roles', fn () => collect([ + "roles" => Role::all()->map(fn ($role) => ['name'=>$role->name, 'permissions'=>$role->permissions->pluck("name")]), + "permissions" => Permission::all()->pluck("name") + ])); }); Route::get('info', fn () => ['git_hash' => config('app.git_hash')]); diff --git a/attendance-web/src/app/app-routing.module.ts b/attendance-web/src/app/app-routing.module.ts index 891383b..4eeafa8 100644 --- a/attendance-web/src/app/app-routing.module.ts +++ b/attendance-web/src/app/app-routing.module.ts @@ -6,7 +6,7 @@ import { LoginComponent } from './components/login/login.component'; import { UpdateOrCreateStudentComponent } from './components/students/update-or-create-student/update-or-create-student.component'; import { MustBeLoggedInGuard } from './guards/must-be-logged-in.guard'; import { MustNotBeLoggedInGuard } from './guards/must-not-be-logged-in.guard'; -import { MustHaveRoleGuard } from './guards/must-have-role.guard'; +import { MustHavePermissionGuard } from './guards/must-have-role.guard'; import { StudentsComponent } from './components/students/students.component'; import { ListStudentsComponent } from './components/students/list-students/list-students.component'; import { ImportStudentsComponent } from './components/students/import-students/import-students.component'; @@ -22,24 +22,27 @@ import { MeetingAttendanceReportComponent } from './components/reports/meeting-a const routes: Routes = [ { path: 'students', component: StudentsComponent, - canActivate: [MustBeLoggedInGuard, MustHaveRoleGuard], - data: { roleOptions: ['mentor', 'student-lead']}, + canActivate: [MustBeLoggedInGuard, MustHavePermissionGuard], + data: { permissions: ['list students', 'view student images']}, children: [ {path: '', redirectTo: 'list', pathMatch: 'full'}, {path: 'detail/:studentId', component: ShowStudentComponent}, { path: 'edit/:studentId', component: UpdateOrCreateStudentComponent, - canActivate: [MustHaveRoleGuard], - data: { roleOptions: ['mentor'] }}, + canActivate: [MustHavePermissionGuard], + data: { permissions: ['modify students', 'modify student images', 'remove students'] }}, {path: 'list', component: ListStudentsComponent}, {path: 'add', component: UpdateOrCreateStudentComponent, - canActivate: [MustHaveRoleGuard], - data: { roleOptions: ['mentor'] }}, - {path: 'import', component: ImportStudentsComponent} + canActivate: [MustHavePermissionGuard], + data: { permissions: ['add students', 'modify student images'] }}, + {path: 'import', component: ImportStudentsComponent, + canActivate: [MustHavePermissionGuard], + data: { permissions: ['add students', 'modify student images'] } + } ] }, { path: 'reports', component: ReportsComponent, - canActivate: [MustBeLoggedInGuard, MustHaveRoleGuard], - data: { roleOptions: ['mentor', 'student-lead']}, + canActivate: [MustBeLoggedInGuard, MustHavePermissionGuard], + data: { permissions: ['list students', 'view stats'] }, children: [ { path: '', redirectTo: 'meetings', pathMatch: 'full' }, { path: 'meetings', component: MeetingsReportComponent }, @@ -50,19 +53,19 @@ const routes: Routes = [ ] }, { path: 'meetings', component: MeetingEventsComponent, - canActivate: [MustBeLoggedInGuard, MustHaveRoleGuard], - data: { roleOptions: ['mentor', 'student-lead']} + canActivate: [MustBeLoggedInGuard, MustHavePermissionGuard], + data: { permissions: ['list meeting events', 'add meeting events']} }, - { path: 'users', component: ElevateUsersComponent, canActivate: [MustBeLoggedInGuard, MustHaveRoleGuard], - data: { roleOptions: ['mentor'] }}, + { path: 'users', component: ElevateUsersComponent, canActivate: [MustBeLoggedInGuard, MustHavePermissionGuard], + data: { permissions: ['elevate users'] }}, { path: 'login', component: LoginComponent, canActivate: [MustNotBeLoggedInGuard] }, { path: '', component: HomeComponent, canActivate: [MustBeLoggedInGuard], children: [ { path: 'check-in', component: AddAttendanceEventListComponent, - canActivate: [MustHaveRoleGuard], data: { roleOptions: [ 'mentor', 'student-lead' ]}}, + canActivate: [MustHavePermissionGuard], data: { permissions: [ 'list attendance events' ]}}, { path: 'check-out', component: AddAttendanceEventListComponent, - canActivate: [MustHaveRoleGuard], data: { roleOptions: [ 'mentor', 'student-lead' ]}} + canActivate: [MustHavePermissionGuard], data: { permissions: [ 'list attendance events' ]}} ] }, { path: 'error', component: ErrorComponent }, diff --git a/attendance-web/src/app/app.component.html b/attendance-web/src/app/app.component.html index 94c70ba..343db0a 100644 --- a/attendance-web/src/app/app.component.html +++ b/attendance-web/src/app/app.component.html @@ -5,7 +5,7 @@ - Attendance Manager + Attendance Manager Welcome, {{name}} @@ -15,30 +15,30 @@