mirror of
https://github.com/Shadowfita/docmost.git
synced 2025-11-18 10:41:04 +10:00
Implement password change endpoint
* move email templates to server
This commit is contained in:
@ -14,6 +14,11 @@ import { CreateUserDto } from './dto/create-user.dto';
|
||||
import { SetupGuard } from './guards/setup.guard';
|
||||
import { EnvironmentService } from '../../integrations/environment/environment.service';
|
||||
import { CreateAdminUserDto } from './dto/create-admin-user.dto';
|
||||
import { ChangePasswordDto } from './dto/change-password.dto';
|
||||
import { AuthUser } from '../../decorators/auth-user.decorator';
|
||||
import { User, Workspace } from '@docmost/db/types/entity.types';
|
||||
import { AuthWorkspace } from '../../decorators/auth-workspace.decorator';
|
||||
import { JwtAuthGuard } from '../../guards/jwt-auth.guard';
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
@ -44,4 +49,15 @@ export class AuthController {
|
||||
if (this.environmentService.isCloud()) throw new NotFoundException();
|
||||
return this.authService.setup(createAdminUserDto);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('change-password')
|
||||
async changePassword(
|
||||
@Body() dto: ChangePasswordDto,
|
||||
@AuthUser() user: User,
|
||||
@AuthWorkspace() workspace: Workspace,
|
||||
) {
|
||||
return this.authService.changePassword(dto, user.id, workspace.id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,8 +7,6 @@ import { TokenService } from './services/token.service';
|
||||
import { JwtStrategy } from './strategies/jwt.strategy';
|
||||
import { WorkspaceModule } from '../workspace/workspace.module';
|
||||
import { SignupService } from './services/signup.service';
|
||||
import { UserModule } from '../user/user.module';
|
||||
import { SpaceModule } from '../space/space.module';
|
||||
import { GroupModule } from '../group/group.module';
|
||||
|
||||
@Module({
|
||||
@ -23,10 +21,8 @@ import { GroupModule } from '../group/group.module';
|
||||
};
|
||||
},
|
||||
inject: [EnvironmentService],
|
||||
} as any),
|
||||
UserModule,
|
||||
}),
|
||||
WorkspaceModule,
|
||||
SpaceModule,
|
||||
GroupModule,
|
||||
],
|
||||
controllers: [AuthController],
|
||||
|
||||
13
apps/server/src/core/auth/dto/change-password.dto.ts
Normal file
13
apps/server/src/core/auth/dto/change-password.dto.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { IsNotEmpty, IsString, MinLength } from 'class-validator';
|
||||
|
||||
export class ChangePasswordDto {
|
||||
@IsNotEmpty()
|
||||
@MinLength(8)
|
||||
@IsString()
|
||||
oldPassword: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@MinLength(8)
|
||||
@IsString()
|
||||
newPassword: string;
|
||||
}
|
||||
@ -1,4 +1,9 @@
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import {
|
||||
BadRequestException,
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { LoginDto } from '../dto/login.dto';
|
||||
import { CreateUserDto } from '../dto/create-user.dto';
|
||||
import { TokenService } from './token.service';
|
||||
@ -6,7 +11,10 @@ import { TokensDto } from '../dto/tokens.dto';
|
||||
import { SignupService } from './signup.service';
|
||||
import { CreateAdminUserDto } from '../dto/create-admin-user.dto';
|
||||
import { UserRepo } from '@docmost/db/repos/user/user.repo';
|
||||
import { comparePasswordHash } from '../../../helpers/utils';
|
||||
import { comparePasswordHash, hashPassword } from '../../../helpers';
|
||||
import { ChangePasswordDto } from '../dto/change-password.dto';
|
||||
import { MailService } from '../../../integrations/mail/mail.service';
|
||||
import ChangePasswordEmail from '@docmost/transactional/emails/change-password-email';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
@ -14,6 +22,7 @@ export class AuthService {
|
||||
private signupService: SignupService,
|
||||
private tokenService: TokenService,
|
||||
private userRepo: UserRepo,
|
||||
private mailService: MailService,
|
||||
) {}
|
||||
|
||||
async login(loginDto: LoginDto, workspaceId: string) {
|
||||
@ -52,4 +61,43 @@ export class AuthService {
|
||||
|
||||
return { tokens };
|
||||
}
|
||||
|
||||
async changePassword(
|
||||
dto: ChangePasswordDto,
|
||||
userId: string,
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
const user = await this.userRepo.findById(userId, workspaceId, {
|
||||
includePassword: true,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new NotFoundException('User not found');
|
||||
}
|
||||
|
||||
const comparePasswords = await comparePasswordHash(
|
||||
dto.oldPassword,
|
||||
user.password,
|
||||
);
|
||||
|
||||
if (!comparePasswords) {
|
||||
throw new BadRequestException('Current password is incorrect');
|
||||
}
|
||||
|
||||
const newPasswordHash = await hashPassword(dto.newPassword);
|
||||
await this.userRepo.updateUser(
|
||||
{
|
||||
password: newPasswordHash,
|
||||
},
|
||||
userId,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
const emailTemplate = ChangePasswordEmail({ username: user.name });
|
||||
await this.mailService.sendToQueue({
|
||||
to: user.email,
|
||||
subject: 'Your password has been changed',
|
||||
template: emailTemplate,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,12 +100,9 @@ export class GroupUserService {
|
||||
this.db,
|
||||
async (trx) => {
|
||||
await this.groupService.findAndValidateGroup(groupId, workspaceId);
|
||||
const user = await this.userRepo.findById(
|
||||
userId,
|
||||
workspaceId,
|
||||
false,
|
||||
trx,
|
||||
);
|
||||
const user = await this.userRepo.findById(userId, workspaceId, {
|
||||
trx: trx,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new NotFoundException('User not found');
|
||||
|
||||
Reference in New Issue
Block a user