apps/api: rename users module -> account

This commit is contained in:
vchikalkin 2023-11-01 12:50:38 +03:00
parent 724d8ccf28
commit 5d99d2bbbc
9 changed files with 52 additions and 92 deletions

View File

@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
/* eslint-disable class-methods-use-this */
/* eslint-disable import/no-extraneous-dependencies */
import { CreateUserDto } from './dto/create-user.dto';
import { UsersService } from './users.service';
import { AccountService } from './account.service';
import { CreateAccountDto } from './dto/create-account.dto';
import {
Body,
Controller,
@ -20,9 +20,9 @@ import { cookieOptions } from 'src/config/cookie';
import { env } from 'src/config/env';
import { Credentials } from 'src/dto/credentials';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Controller('account')
export class AccountController {
constructor(private readonly accountService: AccountService) {}
private clearCookies(req, reply) {
if (req.cookies) {
@ -35,11 +35,11 @@ export class UsersController {
}
@Post('/create')
async create(@Body() createUserDto: CreateUserDto, @Res() reply: FastifyReply) {
async create(@Body() createAccountDto: CreateAccountDto, @Res() reply: FastifyReply) {
try {
const createdUser = await this.usersService.create(createUserDto);
const createdAccount = await this.accountService.create(createAccountDto);
return reply.send(createdUser);
return reply.send(createdAccount);
} catch (error) {
throw new HttpException(error, HttpStatus.BAD_REQUEST);
}
@ -47,18 +47,18 @@ export class UsersController {
@Get()
async findAll() {
return this.usersService.findAll();
return this.accountService.findAll();
}
@Delete('/delete/:login')
async delete(@Param('login') username: CreateUserDto['username']) {
return this.usersService.delete(username);
async delete(@Param('login') username: CreateAccountDto['username']) {
return this.accountService.delete(username);
}
@Post('/signin')
async login(@Body() credentials: Credentials, @Res() reply: FastifyReply) {
try {
const token = await this.usersService.login(credentials);
const token = await this.accountService.login(credentials);
return reply.setCookie(env.COOKIE_TOKEN_NAME, token, cookieOptions).status(200).send();
} catch {
@ -77,8 +77,8 @@ export class UsersController {
async getUser(@Req() req: FastifyRequest, @Res() reply: FastifyReply) {
const token = req.cookies[env.COOKIE_TOKEN_NAME];
const user = await this.usersService.getUser(token);
const account = await this.accountService.getUser(token);
return reply.send(user);
return reply.send(account);
}
}

View File

@ -0,0 +1,14 @@
import { AccountController } from './account.controller';
import { AccountService } from './account.service';
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { Account, AccountSchema } from 'src/schemas/account.schema';
@Module({
controllers: [AccountController],
exports: [],
imports: [MongooseModule.forFeature([{ name: Account.name, schema: AccountSchema }])],
providers: [AccountService],
})
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class AccountModule {}

View File

@ -1,4 +1,4 @@
import type { CreateUserDto } from './dto/create-user.dto';
import type { CreateAccountDto } from './dto/create-account.dto';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { InjectModel } from '@nestjs/mongoose';
@ -7,48 +7,48 @@ import { Model } from 'mongoose';
import { omit } from 'radash';
import type { Credentials } from 'src/dto/credentials';
import type { TokenPayload } from 'src/ldap/types/jwt';
import { User } from 'src/schemas/user.schema';
import { Account } from 'src/schemas/account.schema';
import { generatePassword } from 'src/utils/password';
@Injectable()
export class UsersService {
export class AccountService {
constructor(
private readonly jwtService: JwtService,
@InjectModel(User.name) private userModel: Model<User>
@InjectModel(Account.name) private accountModel: Model<Account>
) {}
public async create(createUserDto: CreateUserDto): Promise<User> {
const password = createUserDto.password || generatePassword();
public async create(createAccountDto: CreateAccountDto): Promise<Account> {
const password = createAccountDto.password || generatePassword();
const createdUser = new this.userModel({ ...createUserDto, password });
const createdAccount = new this.accountModel({ ...createAccountDto, password });
createdUser.save();
createdAccount.save();
return { ...createdUser.toJSON(), password };
return { ...createdAccount.toJSON(), password };
}
public async findAll(): Promise<User[]> {
return this.userModel.find().exec();
public async findAll(): Promise<Account[]> {
return this.accountModel.find().exec();
}
public async delete(username: string) {
return this.userModel.findOneAndDelete({ username }).exec();
return this.accountModel.findOneAndDelete({ username }).exec();
}
public async login({ login, password }: Credentials) {
try {
const user = await this.userModel.findOne({ username: login });
if (!user) {
throw new UnauthorizedException('User not found');
const account = await this.accountModel.findOne({ username: login });
if (!account) {
throw new UnauthorizedException('Account not found');
}
const passwordMatch = await bcrypt.compare(password, user.password);
const passwordMatch = await bcrypt.compare(password, account.password);
if (!passwordMatch) {
throw new UnauthorizedException('Invalid login credentials');
}
const payload: TokenPayload = {
username: login,
...omit(user.toJSON(), ['password']),
...omit(account.toJSON(), ['password']),
};
return this.jwtService.sign(payload);

View File

@ -1,6 +1,6 @@
import { IsNotEmpty, IsOptional, IsString, MinLength } from 'class-validator';
export class CreateUserDto {
export class CreateAccountDto {
@IsString()
@IsNotEmpty()
readonly username: string;

View File

@ -1,8 +1,8 @@
import { AccountModule } from './account/account.module';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { env } from './config/env';
import { LdapModule } from './ldap/ldap.module';
import { UsersModule } from './users/users.module';
import { Global, Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
@ -23,7 +23,7 @@ import { MongooseModule } from '@nestjs/mongoose';
},
}),
LdapModule,
UsersModule,
AccountModule,
MongooseModule.forRoot(`mongodb://${env.MONGO_HOST}`),
],
providers: [AppService],

View File

@ -3,10 +3,10 @@ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import * as bcrypt from 'bcrypt';
import type { HydratedDocument } from 'mongoose';
export type UserDocument = HydratedDocument<User>;
export type UserDocument = HydratedDocument<Account>;
@Schema({ strict: false })
export class User {
export class Account {
@Prop({ index: { unique: true }, required: true })
username: string;
@ -14,9 +14,9 @@ export class User {
password: string;
}
export const UserSchema = SchemaFactory.createForClass(User);
export const AccountSchema = SchemaFactory.createForClass(Account);
UserSchema.pre('save', async function (next) {
AccountSchema.pre('save', async function (next) {
try {
if (!this.isModified('password')) return next();

View File

@ -1,21 +0,0 @@
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import type { TestingModule } from '@nestjs/testing';
import { Test } from '@nestjs/testing';
describe('UsersController', () => {
let controller: UsersController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [UsersController],
providers: [UsersService],
}).compile();
controller = module.get<UsersController>(UsersController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

View File

@ -1,14 +0,0 @@
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { User, UserSchema } from 'src/schemas/user.schema';
@Module({
controllers: [UsersController],
exports: [],
imports: [MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])],
providers: [UsersService],
})
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class UsersModule {}

View File

@ -1,19 +0,0 @@
import { UsersService } from './users.service';
import type { TestingModule } from '@nestjs/testing';
import { Test } from '@nestjs/testing';
describe('UsersService', () => {
let service: UsersService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UsersService],
}).compile();
service = module.get<UsersService>(UsersService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});