part of frontend permission guard
This commit is contained in:
parent
7026c8cb67
commit
ac72035f76
|
@ -8,13 +8,12 @@ import {
|
||||||
import { Reflector } from '@nestjs/core';
|
import { Reflector } from '@nestjs/core';
|
||||||
import { AuthGuard } from '@nestjs/passport';
|
import { AuthGuard } from '@nestjs/passport';
|
||||||
import { plainToClass } from 'class-transformer';
|
import { plainToClass } from 'class-transformer';
|
||||||
import { isArray, isEnum, isString, validate } from 'class-validator';
|
import { validate } from 'class-validator';
|
||||||
import {
|
import {
|
||||||
Permissions,
|
Permissions
|
||||||
PermissionsList
|
|
||||||
} from 'picsur-shared/dist/dto/permissions';
|
} from 'picsur-shared/dist/dto/permissions';
|
||||||
import { Roles } from 'picsur-shared/dist/dto/roles.dto';
|
|
||||||
import { Fail, Failable, HasFailed } from 'picsur-shared/dist/types';
|
import { Fail, Failable, HasFailed } from 'picsur-shared/dist/types';
|
||||||
|
import { isPermissionsArray } from 'picsur-shared/dist/util/permissions';
|
||||||
import { UsersService } from '../../../collections/userdb/userdb.service';
|
import { UsersService } from '../../../collections/userdb/userdb.service';
|
||||||
import { EUserBackend } from '../../../models/entities/user.entity';
|
import { EUserBackend } from '../../../models/entities/user.entity';
|
||||||
|
|
||||||
|
@ -42,13 +41,13 @@ export class MainAuthGuard extends AuthGuard(['jwt', 'guest']) {
|
||||||
|
|
||||||
const permissions = this.extractPermissions(context);
|
const permissions = this.extractPermissions(context);
|
||||||
if (HasFailed(permissions)) {
|
if (HasFailed(permissions)) {
|
||||||
this.logger.warn("222"+permissions.getReason());
|
this.logger.warn('222' + permissions.getReason());
|
||||||
throw new InternalServerErrorException();
|
throw new InternalServerErrorException();
|
||||||
}
|
}
|
||||||
|
|
||||||
const userPermissions = await this.usersService.getPermissions(user);
|
const userPermissions = await this.usersService.getPermissions(user);
|
||||||
if (HasFailed(userPermissions)) {
|
if (HasFailed(userPermissions)) {
|
||||||
this.logger.warn("111"+userPermissions.getReason());
|
this.logger.warn('111' + userPermissions.getReason());
|
||||||
throw new InternalServerErrorException();
|
throw new InternalServerErrorException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,21 +68,13 @@ export class MainAuthGuard extends AuthGuard(['jwt', 'guest']) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isPermissionsArray(permissions)) {
|
if (!isPermissionsArray(permissions)) {
|
||||||
return Fail(`Permissions for ${handlerName} is not a string array`);
|
return Fail(`Permissions for ${handlerName} is not a string array`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return permissions;
|
return permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private isPermissionsArray(value: any): value is Roles {
|
|
||||||
if (!isArray(value)) return false;
|
|
||||||
if (!value.every((item: unknown) => isString(item))) return false;
|
|
||||||
if (!value.every((item: string) => isEnum(item, PermissionsList)))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async validateUser(user: EUserBackend): Promise<EUserBackend> {
|
private async validateUser(user: EUserBackend): Promise<EUserBackend> {
|
||||||
const userClass = plainToClass(EUserBackend, user);
|
const userClass = plainToClass(EUserBackend, user);
|
||||||
const errors = await validate(userClass, {
|
const errors = await validate(userClass, {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { Permission } from 'picsur-shared/dist/dto/permissions';
|
||||||
import { ImageDBService } from '../../collections/imagedb/imagedb.service';
|
import { ImageDBService } from '../../collections/imagedb/imagedb.service';
|
||||||
import { RolesService } from '../../collections/roledb/roledb.service';
|
import { RolesService } from '../../collections/roledb/roledb.service';
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ export class DemoManagerService {
|
||||||
this.logger.warn(
|
this.logger.warn(
|
||||||
'Modifying roles for demo mode, this will not be reverted automatically',
|
'Modifying roles for demo mode, this will not be reverted automatically',
|
||||||
);
|
);
|
||||||
this.rolesService.addPermissions('guest', ['image-upload']);
|
this.rolesService.addPermissions('guest', [Permission.ImageUpload]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public execute() {
|
public execute() {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
UserUpdateRolesRequest,
|
UserUpdateRolesRequest,
|
||||||
UserUpdateRolesResponse
|
UserUpdateRolesResponse
|
||||||
} from 'picsur-shared/dist/dto/api/user.dto';
|
} from 'picsur-shared/dist/dto/api/user.dto';
|
||||||
|
import { Permission } from 'picsur-shared/dist/dto/permissions';
|
||||||
import { HasFailed } from 'picsur-shared/dist/types';
|
import { HasFailed } from 'picsur-shared/dist/types';
|
||||||
import { UsersService } from '../../../collections/userdb/userdb.service';
|
import { UsersService } from '../../../collections/userdb/userdb.service';
|
||||||
import {
|
import {
|
||||||
|
@ -41,7 +42,7 @@ export class UserController {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Post('login')
|
@Post('login')
|
||||||
@UseLocalAuth('user-login')
|
@UseLocalAuth(Permission.UserLogin)
|
||||||
async login(@Request() req: AuthFasityRequest): Promise<UserLoginResponse> {
|
async login(@Request() req: AuthFasityRequest): Promise<UserLoginResponse> {
|
||||||
return {
|
return {
|
||||||
jwt_token: await this.authService.createToken(req.user),
|
jwt_token: await this.authService.createToken(req.user),
|
||||||
|
@ -49,7 +50,7 @@ export class UserController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('register')
|
@Post('register')
|
||||||
@RequiredPermissions('user-register')
|
@RequiredPermissions(Permission.UserRegister)
|
||||||
async register(
|
async register(
|
||||||
@Body() register: UserRegisterRequest,
|
@Body() register: UserRegisterRequest,
|
||||||
): Promise<UserRegisterResponse> {
|
): Promise<UserRegisterResponse> {
|
||||||
|
@ -74,7 +75,7 @@ export class UserController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('delete')
|
@Post('delete')
|
||||||
@RequiredPermissions('user-manage')
|
@RequiredPermissions(Permission.UserManage)
|
||||||
async delete(
|
async delete(
|
||||||
@Body() deleteData: UserDeleteRequest,
|
@Body() deleteData: UserDeleteRequest,
|
||||||
): Promise<UserDeleteResponse> {
|
): Promise<UserDeleteResponse> {
|
||||||
|
@ -88,7 +89,7 @@ export class UserController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('roles')
|
@Post('roles')
|
||||||
@RequiredPermissions('user-manage')
|
@RequiredPermissions(Permission.UserManage)
|
||||||
async setPermissions(
|
async setPermissions(
|
||||||
@Body() body: UserUpdateRolesRequest,
|
@Body() body: UserUpdateRolesRequest,
|
||||||
): Promise<UserUpdateRolesResponse> {
|
): Promise<UserUpdateRolesResponse> {
|
||||||
|
@ -106,7 +107,7 @@ export class UserController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('info')
|
@Post('info')
|
||||||
@RequiredPermissions('user-manage')
|
@RequiredPermissions(Permission.UserManage)
|
||||||
async getUser(@Body() body: UserInfoRequest): Promise<UserInfoResponse> {
|
async getUser(@Body() body: UserInfoRequest): Promise<UserInfoResponse> {
|
||||||
const user = await this.usersService.findOne(body.username);
|
const user = await this.usersService.findOne(body.username);
|
||||||
if (HasFailed(user)) {
|
if (HasFailed(user)) {
|
||||||
|
@ -118,7 +119,7 @@ export class UserController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('list')
|
@Get('list')
|
||||||
@RequiredPermissions('user-manage')
|
@RequiredPermissions(Permission.UserManage)
|
||||||
async listUsers(): Promise<UserListResponse> {
|
async listUsers(): Promise<UserListResponse> {
|
||||||
const users = await this.usersService.findAll();
|
const users = await this.usersService.findAll();
|
||||||
if (HasFailed(users)) {
|
if (HasFailed(users)) {
|
||||||
|
@ -133,7 +134,7 @@ export class UserController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('me')
|
@Get('me')
|
||||||
@RequiredPermissions('user-view')
|
@RequiredPermissions(Permission.UserView)
|
||||||
async me(@Request() req: AuthFasityRequest): Promise<UserMeResponse> {
|
async me(@Request() req: AuthFasityRequest): Promise<UserMeResponse> {
|
||||||
return {
|
return {
|
||||||
user: req.user,
|
user: req.user,
|
||||||
|
|
|
@ -11,13 +11,14 @@ import {
|
||||||
SysPreferenceResponse,
|
SysPreferenceResponse,
|
||||||
UpdateSysPreferenceRequest
|
UpdateSysPreferenceRequest
|
||||||
} from 'picsur-shared/dist/dto/api/pref.dto';
|
} from 'picsur-shared/dist/dto/api/pref.dto';
|
||||||
|
import { Permission } from 'picsur-shared/dist/dto/permissions';
|
||||||
import { SysPreferences } from 'picsur-shared/dist/dto/syspreferences.dto';
|
import { SysPreferences } from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||||
import { HasFailed } from 'picsur-shared/dist/types';
|
import { HasFailed } from 'picsur-shared/dist/types';
|
||||||
import { SysPreferenceService } from '../../../collections/syspreferencesdb/syspreferencedb.service';
|
import { SysPreferenceService } from '../../../collections/syspreferencesdb/syspreferencedb.service';
|
||||||
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
|
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
|
||||||
|
|
||||||
@Controller('api/pref')
|
@Controller('api/pref')
|
||||||
@RequiredPermissions('syspref-manage')
|
@RequiredPermissions(Permission.SysPrefManage)
|
||||||
export class PrefController {
|
export class PrefController {
|
||||||
private readonly logger = new Logger('PrefController');
|
private readonly logger = new Logger('PrefController');
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,13 @@ import {
|
||||||
RoleUpdateRequest,
|
RoleUpdateRequest,
|
||||||
RoleUpdateResponse
|
RoleUpdateResponse
|
||||||
} from 'picsur-shared/dist/dto/api/roles.dto';
|
} from 'picsur-shared/dist/dto/api/roles.dto';
|
||||||
|
import { Permission } from 'picsur-shared/dist/dto/permissions';
|
||||||
import { HasFailed } from 'picsur-shared/dist/types';
|
import { HasFailed } from 'picsur-shared/dist/types';
|
||||||
import { RolesService } from '../../../collections/roledb/roledb.service';
|
import { RolesService } from '../../../collections/roledb/roledb.service';
|
||||||
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
|
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
|
||||||
|
|
||||||
@Controller('api/roles')
|
@Controller('api/roles')
|
||||||
@RequiredPermissions('role-manage')
|
@RequiredPermissions(Permission.RoleManage)
|
||||||
export class RolesController {
|
export class RolesController {
|
||||||
private readonly logger = new Logger('RolesController');
|
private readonly logger = new Logger('RolesController');
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
import { isHash } from 'class-validator';
|
import { isHash } from 'class-validator';
|
||||||
import { FastifyReply, FastifyRequest } from 'fastify';
|
import { FastifyReply, FastifyRequest } from 'fastify';
|
||||||
import { ImageMetaResponse } from 'picsur-shared/dist/dto/api/image.dto';
|
import { ImageMetaResponse } from 'picsur-shared/dist/dto/api/image.dto';
|
||||||
|
import { Permission } from 'picsur-shared/dist/dto/permissions';
|
||||||
import { HasFailed } from 'picsur-shared/dist/types';
|
import { HasFailed } from 'picsur-shared/dist/types';
|
||||||
import { MultiPart } from '../../decorators/multipart.decorator';
|
import { MultiPart } from '../../decorators/multipart.decorator';
|
||||||
import { RequiredPermissions } from '../../decorators/permissions.decorator';
|
import { RequiredPermissions } from '../../decorators/permissions.decorator';
|
||||||
|
@ -20,7 +21,7 @@ import { ImageManagerService } from '../../managers/imagemanager/imagemanager.se
|
||||||
import { ImageUploadDto } from '../../models/dto/imageroute.dto';
|
import { ImageUploadDto } from '../../models/dto/imageroute.dto';
|
||||||
|
|
||||||
@Controller('i')
|
@Controller('i')
|
||||||
@RequiredPermissions('image-view')
|
@RequiredPermissions(Permission.ImageView)
|
||||||
export class ImageController {
|
export class ImageController {
|
||||||
private readonly logger = new Logger('ImageController');
|
private readonly logger = new Logger('ImageController');
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ export class ImageController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@RequiredPermissions('image-upload')
|
@RequiredPermissions(Permission.ImageUpload)
|
||||||
async uploadImage(
|
async uploadImage(
|
||||||
@Req() req: FastifyRequest,
|
@Req() req: FastifyRequest,
|
||||||
@MultiPart(ImageUploadDto) multipart: ImageUploadDto,
|
@MultiPart(ImageUploadDto) multipart: ImageUploadDto,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
|
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
|
||||||
import { Permissions } from 'picsur-shared/dist/dto/permissions';
|
import { Permission, Permissions } from 'picsur-shared/dist/dto/permissions';
|
||||||
import { EUser } from 'picsur-shared/dist/entities/user.entity';
|
import { EUser } from 'picsur-shared/dist/entities/user.entity';
|
||||||
import { HasFailed } from 'picsur-shared/dist/types';
|
import { HasFailed } from 'picsur-shared/dist/types';
|
||||||
import { PermissionService } from 'src/app/api/permission.service';
|
import { PermissionService } from 'src/app/api/permission.service';
|
||||||
|
@ -29,7 +29,7 @@ export class HeaderComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public get canLogIn() {
|
public get canLogIn() {
|
||||||
return this.permissions.includes('user-login');
|
return this.permissions.includes(Permission.UserLogin);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
11
frontend/src/app/guards/guards.module.ts
Normal file
11
frontend/src/app/guards/guards.module.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { ApiModule } from '../api/api.module';
|
||||||
|
import { PermissionGuard } from './permission.guard';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [CommonModule, ApiModule],
|
||||||
|
providers: [PermissionGuard],
|
||||||
|
exports: [],
|
||||||
|
})
|
||||||
|
export class GuardsModule {}
|
37
frontend/src/app/guards/permission.guard.ts
Normal file
37
frontend/src/app/guards/permission.guard.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import {
|
||||||
|
ActivatedRouteSnapshot,
|
||||||
|
CanActivate,
|
||||||
|
RouterStateSnapshot
|
||||||
|
} from '@angular/router';
|
||||||
|
import { Permissions } from 'picsur-shared/dist/dto/permissions';
|
||||||
|
import { isPermissionsArray } from 'picsur-shared/dist/util/permissions';
|
||||||
|
import { PermissionService } from '../api/permission.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class PermissionGuard implements CanActivate {
|
||||||
|
constructor(private permissionService: PermissionService) {}
|
||||||
|
|
||||||
|
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
|
const requiredPermissions: Permissions = route.data['permissions'];
|
||||||
|
if (!isPermissionsArray(requiredPermissions)) {
|
||||||
|
throw new Error(
|
||||||
|
`PermissionGuard: route data 'permissions' must be an array of Permission values`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ourPermissions = this.permissionService.snapshot;
|
||||||
|
|
||||||
|
const isOk = requiredPermissions.every((permission) =>
|
||||||
|
ourPermissions.includes(permission)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`PermissionGuard: requiredPermissions=${requiredPermissions} ourPermissions=${ourPermissions} isOk=${isOk}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return isOk;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,10 +6,13 @@ import { MatInputModule } from '@angular/material/input';
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { NgxDropzoneModule } from 'ngx-dropzone';
|
import { NgxDropzoneModule } from 'ngx-dropzone';
|
||||||
|
import { Permission } from 'picsur-shared/dist/dto/permissions';
|
||||||
import { ApiModule } from '../api/api.module';
|
import { ApiModule } from '../api/api.module';
|
||||||
import { CopyFieldModule } from '../components/copyfield/copyfield.module';
|
import { CopyFieldModule } from '../components/copyfield/copyfield.module';
|
||||||
import { PageNotFoundComponent } from '../components/pagenotfound/pagenotfound.component';
|
import { PageNotFoundComponent } from '../components/pagenotfound/pagenotfound.component';
|
||||||
import { PageNotFoundModule } from '../components/pagenotfound/pagenotfound.module';
|
import { PageNotFoundModule } from '../components/pagenotfound/pagenotfound.module';
|
||||||
|
import { GuardsModule } from '../guards/guards.module';
|
||||||
|
import { PermissionGuard } from '../guards/permission.guard';
|
||||||
import { LoginComponent } from '../routes/login/login.component';
|
import { LoginComponent } from '../routes/login/login.component';
|
||||||
import { ProcessingComponent } from '../routes/processing/processing.component';
|
import { ProcessingComponent } from '../routes/processing/processing.component';
|
||||||
import { UploadComponent } from '../routes/upload/upload.component';
|
import { UploadComponent } from '../routes/upload/upload.component';
|
||||||
|
@ -25,13 +28,19 @@ const routes: Routes = [
|
||||||
component: ProcessingComponent,
|
component: ProcessingComponent,
|
||||||
},
|
},
|
||||||
{ path: 'view/:hash', component: ViewComponent },
|
{ path: 'view/:hash', component: ViewComponent },
|
||||||
{ path: 'login', component: LoginComponent },
|
{
|
||||||
|
path: 'login',
|
||||||
|
component: LoginComponent,
|
||||||
|
canActivate: [PermissionGuard],
|
||||||
|
data: { permissions: [Permission.UserLogin] },
|
||||||
|
},
|
||||||
{ path: '**', component: PageNotFoundComponent },
|
{ path: '**', component: PageNotFoundComponent },
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
GuardsModule,
|
||||||
NgxDropzoneModule,
|
NgxDropzoneModule,
|
||||||
UtilModule,
|
UtilModule,
|
||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
|
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
|
||||||
import { Permissions } from 'picsur-shared/dist/dto/permissions';
|
import { Permission, Permissions } from 'picsur-shared/dist/dto/permissions';
|
||||||
import { HasFailed } from 'picsur-shared/dist/types';
|
import { HasFailed } from 'picsur-shared/dist/types';
|
||||||
import { PermissionService } from 'src/app/api/permission.service';
|
import { PermissionService } from 'src/app/api/permission.service';
|
||||||
import { UserService } from 'src/app/api/user.service';
|
import { UserService } from 'src/app/api/user.service';
|
||||||
|
@ -20,7 +20,7 @@ export class LoginComponent implements OnInit {
|
||||||
private permissions: Permissions = [];
|
private permissions: Permissions = [];
|
||||||
|
|
||||||
public get showRegister() {
|
public get showRegister() {
|
||||||
return this.permissions.includes('user-register');
|
return this.permissions.includes(Permission.UserRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
model = new LoginControl();
|
model = new LoginControl();
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
|
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
|
||||||
import { NgxDropzoneChangeEvent } from 'ngx-dropzone';
|
import { NgxDropzoneChangeEvent } from 'ngx-dropzone';
|
||||||
import { Permissions } from 'picsur-shared/dist/dto/permissions';
|
import { Permission, Permissions } from 'picsur-shared/dist/dto/permissions';
|
||||||
import { PermissionService } from 'src/app/api/permission.service';
|
import { PermissionService } from 'src/app/api/permission.service';
|
||||||
import { UtilService } from 'src/app/util/util.service';
|
import { UtilService } from 'src/app/util/util.service';
|
||||||
import { ProcessingViewMetadata } from '../../models/processing-view-metadata';
|
import { ProcessingViewMetadata } from '../../models/processing-view-metadata';
|
||||||
|
@ -16,7 +16,7 @@ export class UploadComponent implements OnInit {
|
||||||
|
|
||||||
// Lets be optimistic here, this makes for a better ux
|
// Lets be optimistic here, this makes for a better ux
|
||||||
public get hasUploadPermission() {
|
public get hasUploadPermission() {
|
||||||
return this.permissions.includes('image-upload');
|
return this.permissions.includes(Permission.ImageUpload);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
import tuple from '../types/tuple';
|
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
|
|
||||||
const PermissionsTuple = tuple(
|
export enum Permission {
|
||||||
'image-view',
|
ImageView = 'image-view',
|
||||||
'image-upload',
|
ImageUpload = 'image-upload',
|
||||||
'user-login', // Ability to log in
|
UserLogin = 'user-login', // Ability to log in
|
||||||
'user-register', // Ability to register
|
UserRegister = 'user-register', // Ability to register
|
||||||
'user-manage',
|
UserManage = 'user-manage',
|
||||||
'user-view', // Ability to view user details and refresh token
|
UserView = 'user-view', // Ability to view user details and refresh token
|
||||||
'role-manage',
|
RoleManage = 'role-manage',
|
||||||
'syspref-manage',
|
SysPrefManage = 'syspref-manage',
|
||||||
);
|
}
|
||||||
|
|
||||||
// Derivatives
|
// Derivatives
|
||||||
|
|
||||||
export const PermissionsList: string[] = PermissionsTuple;
|
export const PermissionsList: Permission[] = Object.values(Permission);
|
||||||
|
|
||||||
export type Permission = typeof PermissionsTuple[number];
|
|
||||||
export type Permissions = Permission[];
|
export type Permissions = Permission[];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import tuple from '../types/tuple';
|
import tuple from '../types/tuple';
|
||||||
import { Permissions, PermissionsList } from './permissions';
|
import { Permission, Permissions, PermissionsList } from './permissions';
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
|
|
||||||
|
@ -24,10 +24,15 @@ export type SystemRoles = SystemRole[];
|
||||||
export const SystemRoleDefaults: {
|
export const SystemRoleDefaults: {
|
||||||
[key in SystemRole]: Permissions;
|
[key in SystemRole]: Permissions;
|
||||||
} = {
|
} = {
|
||||||
guest: ['image-view', 'user-login'],
|
guest: [Permission.ImageView, Permission.UserLogin],
|
||||||
user: ['image-view', 'user-view', 'user-login', 'image-upload'],
|
user: [
|
||||||
|
Permission.ImageView,
|
||||||
|
Permission.UserView,
|
||||||
|
Permission.UserLogin,
|
||||||
|
Permission.ImageUpload,
|
||||||
|
],
|
||||||
// Grant all permissions to admin
|
// Grant all permissions to admin
|
||||||
admin: PermissionsList as Permissions,
|
admin: PermissionsList,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Normal roles types
|
// Normal roles types
|
||||||
|
|
10
shared/src/util/permissions.ts
Normal file
10
shared/src/util/permissions.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { isArray, isEnum, isString } from 'class-validator';
|
||||||
|
import { Permissions, PermissionsList } from '../dto/permissions';
|
||||||
|
|
||||||
|
export function isPermissionsArray(value: any): value is Permissions {
|
||||||
|
if (!isArray(value)) return false;
|
||||||
|
if (!value.every((item: unknown) => isString(item))) return false;
|
||||||
|
if (!value.every((item: string) => isEnum(item, PermissionsList)))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
Loading…
Reference in a new issue