rename permissions and add admin image list

This commit is contained in:
rubikscraft
2022-05-04 21:25:52 +02:00
parent dce72d0680
commit 80b60595fe
22 changed files with 258 additions and 218 deletions

View File

@@ -3,22 +3,22 @@ import { InjectRepository } from '@nestjs/typeorm';
import * as bcrypt from 'bcrypt';
import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.dto';
import {
AsyncFailable,
Fail,
HasFailed,
HasSuccess
AsyncFailable,
Fail,
HasFailed,
HasSuccess
} from 'picsur-shared/dist/types';
import { makeUnique } from 'picsur-shared/dist/util/unique';
import { Repository } from 'typeorm';
import { Permissions } from '../../models/constants/permissions.const';
import {
DefaultRolesList,
SoulBoundRolesList
DefaultRolesList,
SoulBoundRolesList
} from '../../models/constants/roles.const';
import {
ImmutableUsersList,
LockedLoginUsersList,
UndeletableUsersList
ImmutableUsersList,
LockedLoginUsersList,
UndeletableUsersList
} from '../../models/constants/special-users.const';
import { EUserBackend } from '../../models/entities/user.entity';
import { GetCols } from '../../models/util/collection';

View File

@@ -1,7 +1,13 @@
import { SetMetadata, UseGuards } from '@nestjs/common';
import {
createParamDecorator,
ExecutionContext,
SetMetadata,
UseGuards
} from '@nestjs/common';
import { CombineFCDecorators } from 'picsur-shared/dist/util/decorator';
import { LocalAuthGuard } from '../managers/auth/guards/local-auth.guard';
import { Permissions } from '../models/constants/permissions.const';
import { Permission, Permissions } from '../models/constants/permissions.const';
import AuthFasityRequest from '../models/interfaces/authrequest.dto';
export const RequiredPermissions = (...permissions: Permissions) => {
return SetMetadata('permissions', permissions);
@@ -16,3 +22,27 @@ export const UseLocalAuth = (...permissions: Permissions) =>
RequiredPermissions(...permissions),
UseGuards(LocalAuthGuard),
);
export const HasPermission = createParamDecorator(
(data: Permission, ctx: ExecutionContext) => {
const req: AuthFasityRequest = ctx.switchToHttp().getRequest();
const permissions = req.userPermissions;
if (!permissions) {
throw new Error('Permissions are missing from request');
}
return permissions.includes(data);
},
);
export const GetPermissions = createParamDecorator(
(data: Permission, ctx: ExecutionContext) => {
const req: AuthFasityRequest = ctx.switchToHttp().getRequest();
const permissions = req.userPermissions;
if (!permissions) {
throw new Error('Permissions are missing from request');
}
return permissions;
},
);

View File

@@ -58,6 +58,8 @@ export class MainAuthGuard extends AuthGuard(['jwt', 'guest']) {
throw new InternalServerErrorException();
}
context.switchToHttp().getRequest().userPermissions = userPermissions;
if (permissions.every((permission) => userPermissions.includes(permission)))
return true;
else throw new ForbiddenException('Permission denied');

View File

@@ -1,7 +1,9 @@
import { FastifyRequest } from 'fastify';
import { EUser } from 'picsur-shared/dist/entities/user.entity';
import { Permissions } from '../constants/permissions.const';
// Add typing to FastifyRequest to make using the user object easier
export default interface AuthFasityRequest extends FastifyRequest {
user: EUser;
userPermissions?: Permissions;
}

View File

@@ -1,17 +1,17 @@
import {
Body,
Controller,
Get,
InternalServerErrorException,
Logger,
Param,
Post
Body,
Controller,
Get,
InternalServerErrorException,
Logger,
Param,
Post
} from '@nestjs/common';
import {
GetPreferenceResponse,
MultiplePreferencesResponse,
UpdatePreferenceRequest,
UpdatePreferenceResponse
GetPreferenceResponse,
MultiplePreferencesResponse,
UpdatePreferenceRequest,
UpdatePreferenceResponse
} from 'picsur-shared/dist/dto/api/pref.dto';
import { HasFailed } from 'picsur-shared/dist/types';
import { SysPreferenceService } from '../../../collections/preference-db/sys-preference-db.service';
@@ -20,7 +20,7 @@ import { Returns } from '../../../decorators/returns.decorator';
import { Permission } from '../../../models/constants/permissions.const';
@Controller('api/pref/sys')
@RequiredPermissions(Permission.SysPrefManage)
@RequiredPermissions(Permission.SysPrefAdmin)
export class SysPrefController {
private readonly logger = new Logger('SysPrefController');

View File

@@ -1,22 +1,22 @@
import {
Body,
Controller,
Get,
InternalServerErrorException,
Logger,
Post
Body,
Controller,
Get,
InternalServerErrorException,
Logger,
Post
} from '@nestjs/common';
import {
RoleCreateRequest,
RoleCreateResponse,
RoleDeleteRequest,
RoleDeleteResponse,
RoleInfoRequest,
RoleInfoResponse,
RoleListResponse,
RoleUpdateRequest,
RoleUpdateResponse,
SpecialRolesResponse
RoleCreateRequest,
RoleCreateResponse,
RoleDeleteRequest,
RoleDeleteResponse,
RoleInfoRequest,
RoleInfoResponse,
RoleListResponse,
RoleUpdateRequest,
RoleUpdateResponse,
SpecialRolesResponse
} from 'picsur-shared/dist/dto/api/roles.dto';
import { HasFailed } from 'picsur-shared/dist/types';
import { RolesService } from '../../../collections/role-db/role-db.service';
@@ -25,15 +25,15 @@ import { RequiredPermissions } from '../../../decorators/permissions.decorator';
import { Returns } from '../../../decorators/returns.decorator';
import { Permission } from '../../../models/constants/permissions.const';
import {
DefaultRolesList,
ImmutableRolesList,
SoulBoundRolesList,
UndeletableRolesList
DefaultRolesList,
ImmutableRolesList,
SoulBoundRolesList,
UndeletableRolesList
} from '../../../models/constants/roles.const';
import { isPermissionsArray } from '../../../models/validators/permissions.validator';
@Controller('api/roles')
@RequiredPermissions(Permission.RoleManage)
@RequiredPermissions(Permission.RoleAdmin)
export class RolesController {
private readonly logger = new Logger('RolesController');

View File

@@ -6,7 +6,6 @@ import {
Logger,
Post
} from '@nestjs/common';
import { PagedRequest } from 'picsur-shared/dist/dto/api/common.dto';
import {
GetSpecialUsersResponse,
UserCreateRequest,
@@ -15,6 +14,7 @@ import {
UserDeleteResponse,
UserInfoRequest,
UserInfoResponse,
UserListRequest,
UserListResponse,
UserUpdateRequest,
UserUpdateResponse
@@ -32,15 +32,17 @@ import {
import { EUserBackend2EUser } from '../../../models/transformers/user.transformer';
@Controller('api/user')
@RequiredPermissions(Permission.UserManage)
export class UserManageController {
private readonly logger = new Logger('UserManageController');
@RequiredPermissions(Permission.UserAdmin)
export class UserAdminController {
private readonly logger = new Logger('UserAdminController');
constructor(private usersService: UsersService) {}
@Post('list')
@Returns(UserListResponse)
async listUsersPaged(@Body() body: PagedRequest): Promise<UserListResponse> {
async listUsersPaged(
@Body() body: UserListRequest,
): Promise<UserListResponse> {
const users = await this.usersService.findMany(body.count, body.page);
if (HasFailed(users)) {
this.logger.warn(users.getReason());

View File

@@ -1,10 +1,10 @@
import { Module } from '@nestjs/common';
import { AuthManagerModule } from '../../../managers/auth/auth.module';
import { UserManageController } from './user-manage.controller';
import { UserAdminController } from './user-manage.controller';
import { UserController } from './user.controller';
@Module({
imports: [AuthManagerModule],
controllers: [UserController, UserManageController],
controllers: [UserController, UserAdminController],
})
export class UserApiModule {}

View File

@@ -5,12 +5,18 @@ import {
Logger,
Post
} from '@nestjs/common';
import { PagedRequest } from 'picsur-shared/dist/dto/api/common.dto';
import { ImageListResponse, ImageUploadResponse } from 'picsur-shared/dist/dto/api/image-manage.dto';
import {
ImageListRequest,
ImageListResponse,
ImageUploadResponse
} from 'picsur-shared/dist/dto/api/image-manage.dto';
import { Permission } from 'picsur-shared/dist/dto/permissions.dto';
import { HasFailed } from 'picsur-shared/dist/types';
import { MultiPart } from '../../decorators/multipart/multipart.decorator';
import { RequiredPermissions } from '../../decorators/permissions.decorator';
import {
HasPermission,
RequiredPermissions
} from '../../decorators/permissions.decorator';
import { ReqUserID } from '../../decorators/request-user.decorator';
import { Returns } from '../../decorators/returns.decorator';
import { ImageManagerService } from '../../managers/image/image.service';
@@ -41,12 +47,17 @@ export class ImageManageController {
return image;
}
@Post('my/list')
@Post('list')
@Returns(ImageListResponse)
async listUsersPaged(
@Body() body: PagedRequest,
async listMyImagesPaged(
@Body() body: ImageListRequest,
@ReqUserID() userid: string,
@HasPermission(Permission.ImageAdmin) isImageAdmin: boolean,
): Promise<ImageListResponse> {
if (!isImageAdmin) {
body.user_id = userid;
}
const images = await this.imagesService.findMany(
body.count,
body.page,