Added Backend for User Profile
This commit is contained in:
parent
1f714b5b50
commit
06fffbee2f
@ -34,3 +34,13 @@ export class TfaSetup extends BaseRequest {
|
|||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
mail: boolean;
|
mail: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ChangePasswordRequest extends BaseRequest {
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
oldPassword: string;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
newPassword: string;
|
||||||
|
}
|
||||||
|
@ -35,4 +35,5 @@ export class RemoveTfaResponse extends SuccessResponse {}
|
|||||||
export class RequestEmailTfaResponse extends SuccessResponse {}
|
export class RequestEmailTfaResponse extends SuccessResponse {}
|
||||||
export class TfaCompletedResponse extends SuccessResponse {}
|
export class TfaCompletedResponse extends SuccessResponse {}
|
||||||
export class SignupResponse extends SuccessResponse {}
|
export class SignupResponse extends SuccessResponse {}
|
||||||
|
export class ChangePasswordResponse extends SuccessResponse {}
|
||||||
export class RefreshResponse extends LoginResponse {}
|
export class RefreshResponse extends LoginResponse {}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from './base';
|
export * from './base';
|
||||||
export * as Auth from './auth';
|
export * as Auth from './auth';
|
||||||
export * as FS from './fs';
|
export * as FS from './fs';
|
||||||
|
export * as User from './user';
|
||||||
|
27
dto/src/responses/user.ts
Normal file
27
dto/src/responses/user.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { SuccessResponse } from './base';
|
||||||
|
import { ValidateConstructor } from '../utils';
|
||||||
|
import { IsBoolean, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
@ValidateConstructor
|
||||||
|
export class UserInfoResponse extends SuccessResponse {
|
||||||
|
constructor(name: string, gitlab: boolean, tfaEnabled: boolean) {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
this.gitlab = gitlab;
|
||||||
|
this.tfaEnabled = tfaEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@IsBoolean()
|
||||||
|
gitlab: boolean;
|
||||||
|
|
||||||
|
@IsBoolean()
|
||||||
|
tfaEnabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DeleteUserResponse extends SuccessResponse {}
|
||||||
|
export class ChangePasswordResponse extends SuccessResponse {}
|
||||||
|
export class LogoutAllResponse extends SuccessResponse {}
|
@ -18,7 +18,8 @@
|
|||||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||||
"test:e2e": "jest --config ./test/jest-e2e.json",
|
"test:e2e": "jest --config ./test/jest-e2e.json",
|
||||||
"webpack": "webpack --config webpack.config.ts",
|
"webpack": "webpack --config webpack.config.ts",
|
||||||
"genapi": "ts-node tools/apigen.ts"
|
"genapi": "ts-node tools/apigen.ts",
|
||||||
|
"updateDto": "cd dto && yarn build && cd .. && yarn add ./dto && cd frontend && yarn add ../dto"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/multipart": "^7.1.0",
|
"@fastify/multipart": "^7.1.0",
|
||||||
|
@ -134,4 +134,17 @@ export default class AuthController {
|
|||||||
url: `/set_token?token=${token}`
|
url: `/set_token?token=${token}`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('change_password')
|
||||||
|
async changePassword(
|
||||||
|
@Request() req,
|
||||||
|
@Body(new ValidationPipe()) data: Requests.Auth.ChangePasswordRequest
|
||||||
|
): Promise<Responses.Auth.ChangePasswordResponse> {
|
||||||
|
await this.authService.changePassword(
|
||||||
|
req.user,
|
||||||
|
data.oldPassword,
|
||||||
|
data.newPassword
|
||||||
|
);
|
||||||
|
return new Responses.Auth.ChangePasswordResponse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
27
src/controller/user.ts
Normal file
27
src/controller/user.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { Controller, Get, Post, Request } from '@nestjs/common';
|
||||||
|
import { AuthService } from '../services/auth';
|
||||||
|
import { Responses } from 'dto';
|
||||||
|
|
||||||
|
@Controller('api/user')
|
||||||
|
export default class UserController {
|
||||||
|
constructor(private authService: AuthService) {}
|
||||||
|
|
||||||
|
@Get('info')
|
||||||
|
async getUserInfo(
|
||||||
|
@Request() req
|
||||||
|
): Promise<Responses.User.UserInfoResponse> {
|
||||||
|
return new Responses.User.UserInfoResponse(
|
||||||
|
req.user.name,
|
||||||
|
req.user.isGitlabUser,
|
||||||
|
this.authService.requiresTfa(req.user)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('delete')
|
||||||
|
async deleteUser(
|
||||||
|
@Request() req
|
||||||
|
): Promise<Responses.User.DeleteUserResponse> {
|
||||||
|
await this.authService.deleteUser(req.user);
|
||||||
|
return new Responses.User.DeleteUserResponse();
|
||||||
|
}
|
||||||
|
}
|
@ -6,8 +6,9 @@ import {
|
|||||||
AuthLocalService,
|
AuthLocalService,
|
||||||
AuthJwtService
|
AuthJwtService
|
||||||
} from '../services/auth';
|
} from '../services/auth';
|
||||||
import AuthController from '../controller/auth';
|
|
||||||
import FileSystemService from '../services/filesystem';
|
import FileSystemService from '../services/filesystem';
|
||||||
|
import AuthController from '../controller/auth';
|
||||||
|
import UserController from '../controller/user';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([User, INode, JWTToken])],
|
imports: [TypeOrmModule.forFeature([User, INode, JWTToken])],
|
||||||
@ -17,6 +18,6 @@ import FileSystemService from '../services/filesystem';
|
|||||||
AuthJwtService,
|
AuthJwtService,
|
||||||
FileSystemService
|
FileSystemService
|
||||||
],
|
],
|
||||||
controllers: [AuthController]
|
controllers: [AuthController, UserController]
|
||||||
})
|
})
|
||||||
export default class AuthModule {}
|
export default class AuthModule {}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
BadRequestException,
|
BadRequestException,
|
||||||
|
ForbiddenException,
|
||||||
Injectable,
|
Injectable,
|
||||||
UnauthorizedException
|
UnauthorizedException
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
@ -312,6 +313,23 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
return info && info.username == user.name;
|
return info && info.username == user.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async deleteUser(user: User): Promise<void> {
|
||||||
|
await this.revokeAll(user);
|
||||||
|
await this.fsService.delete(await user.root, true);
|
||||||
|
await this.userRepo.remove(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
async changePassword(
|
||||||
|
user: User,
|
||||||
|
oldPW: string,
|
||||||
|
newPw: string
|
||||||
|
): Promise<void> {
|
||||||
|
if (!(await argon2.verify(user.password, oldPW)))
|
||||||
|
throw new ForbiddenException('Old password is wrong');
|
||||||
|
user.password = await argon2.hash(newPw);
|
||||||
|
await this.revokeAll(await this.userRepo.save(user));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -51,12 +51,12 @@ export default class FileSystemService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(node: INode): Promise<void> {
|
async delete(node: INode, force = false): Promise<void> {
|
||||||
if (node.parentId == null)
|
if (node.parentId == null || force)
|
||||||
throw new BadRequestException("Can't delete root");
|
throw new BadRequestException("Can't delete root");
|
||||||
if (!node.isFile)
|
if (!node.isFile)
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
(await node.children).map((child) => this.delete(child))
|
(await node.children).map((child) => this.delete(child, force))
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
unlink(`files/${node.id}`, (err) => {
|
unlink(`files/${node.id}`, (err) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user