Update the user module

master
Mahdi 2 weeks ago
parent fc37b598ec
commit 5c14ac394c
  1. 67
      package-lock.json
  2. 3
      package.json
  3. 9
      src/app.module.ts
  4. 9
      src/modules/users/dto/create-user.dto.ts
  5. 2
      src/modules/users/dto/index.ts
  6. 4
      src/modules/users/dto/update-user.dto.ts
  7. 6
      src/modules/users/dto/user.dto.ts
  8. 31
      src/modules/users/user.entity.ts
  9. 42
      src/modules/users/users.controller.ts
  10. 2
      src/modules/users/users.module.ts
  11. 46
      src/modules/users/users.service.ts

67
package-lock.json generated

@ -12,8 +12,11 @@
"@nestjs/common": "^10.0.0", "@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.3.0", "@nestjs/config": "^3.3.0",
"@nestjs/core": "^10.0.0", "@nestjs/core": "^10.0.0",
"@nestjs/mapped-types": "*",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"argon2": "^0.41.1",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"lodash": "^4.17.21",
"pg": "^8.13.1", "pg": "^8.13.1",
"pg-hstore": "^2.3.4", "pg-hstore": "^2.3.4",
"reflect-metadata": "^0.2.0", "reflect-metadata": "^0.2.0",
@ -1708,6 +1711,26 @@
} }
} }
}, },
"node_modules/@nestjs/mapped-types": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.6.tgz",
"integrity": "sha512-84ze+CPfp1OWdpRi1/lOu59hOhTz38eVzJvRKrg9ykRFwDz+XleKfMsG0gUqNZYFa6v53XYzeD+xItt8uDW7NQ==",
"license": "MIT",
"peerDependencies": {
"@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0",
"class-transformer": "^0.4.0 || ^0.5.0",
"class-validator": "^0.13.0 || ^0.14.0",
"reflect-metadata": "^0.1.12 || ^0.2.0"
},
"peerDependenciesMeta": {
"class-transformer": {
"optional": true
},
"class-validator": {
"optional": true
}
}
},
"node_modules/@nestjs/platform-express": { "node_modules/@nestjs/platform-express": {
"version": "10.4.15", "version": "10.4.15",
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.15.tgz", "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.15.tgz",
@ -1837,6 +1860,15 @@
"npm": ">=5.0.0" "npm": ">=5.0.0"
} }
}, },
"node_modules/@phc/format": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz",
"integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/@pkgjs/parseargs": { "node_modules/@pkgjs/parseargs": {
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@ -2848,6 +2880,21 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/argon2": {
"version": "0.41.1",
"resolved": "https://registry.npmjs.org/argon2/-/argon2-0.41.1.tgz",
"integrity": "sha512-dqCW8kJXke8Ik+McUcMDltrbuAWETPyU6iq+4AhxqKphWi7pChB/Zgd/Tp/o8xRLbg8ksMj46F/vph9wnxpTzQ==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@phc/format": "^1.0.0",
"node-addon-api": "^8.1.0",
"node-gyp-build": "^4.8.1"
},
"engines": {
"node": ">=16.17.0"
}
},
"node_modules/argparse": { "node_modules/argparse": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@ -6903,6 +6950,15 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/node-addon-api": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.0.tgz",
"integrity": "sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==",
"license": "MIT",
"engines": {
"node": "^18 || ^20 || >= 21"
}
},
"node_modules/node-emoji": { "node_modules/node-emoji": {
"version": "1.11.0", "version": "1.11.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
@ -6933,6 +6989,17 @@
} }
} }
}, },
"node_modules/node-gyp-build": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
"license": "MIT",
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
"node-gyp-build-test": "build-test.js"
}
},
"node_modules/node-int64": { "node_modules/node-int64": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",

@ -23,8 +23,11 @@
"@nestjs/common": "^10.0.0", "@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.3.0", "@nestjs/config": "^3.3.0",
"@nestjs/core": "^10.0.0", "@nestjs/core": "^10.0.0",
"@nestjs/mapped-types": "*",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"argon2": "^0.41.1",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"lodash": "^4.17.21",
"pg": "^8.13.1", "pg": "^8.13.1",
"pg-hstore": "^2.3.4", "pg-hstore": "^2.3.4",
"reflect-metadata": "^0.2.0", "reflect-metadata": "^0.2.0",

@ -4,10 +4,15 @@ import { AppService } from './app.service';
import { DatabaseModule } from './core/database/database.module'; import { DatabaseModule } from './core/database/database.module';
import { ConfigModule } from '@nestjs/config'; import { ConfigModule } from '@nestjs/config';
import { UsersModule } from './modules/users/users.module'; import { UsersModule } from './modules/users/users.module';
import { UsersController } from './modules/users/users.controller';
@Module({ @Module({
imports: [DatabaseModule, ConfigModule.forRoot({ isGlobal: true }), UsersModule], imports: [
controllers: [AppController], DatabaseModule,
ConfigModule.forRoot({ isGlobal: true }),
UsersModule,
],
controllers: [AppController, UsersController],
providers: [AppService], providers: [AppService],
}) })
export class AppModule {} export class AppModule {}

@ -0,0 +1,9 @@
export class CreateUserDto {
firstName: string;
lastName: string;
email: string;
password: string;
phoneNumber: string;
gender: string;
city: string;
}

@ -0,0 +1,2 @@
export * from './create-user.dto';
export * from './update-user.dto';

@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateUserDto } from './create-user.dto';
export class UpdateUserDto extends PartialType(CreateUserDto) {}

@ -1,6 +0,0 @@
export class UserDto {
readonly name: string;
readonly email: string;
readonly password: string;
readonly gender: string;
}

@ -1,12 +1,25 @@
import { Table, Column, Model, DataType } from 'sequelize-typescript'; import { Table, Column, Model, DataType } from 'sequelize-typescript';
@Table @Table({ tableName: 'users' })
export class User extends Model<User> { export class User extends Model<User> {
@Column({
type: DataType.UUID,
allowNull: false,
defaultValue: DataType.UUIDV4,
})
uuid: string;
@Column({
type: DataType.STRING,
allowNull: false,
})
firstName: string;
@Column({ @Column({
type: DataType.STRING, type: DataType.STRING,
allowNull: false, allowNull: false,
}) })
name: string; lastName: string;
@Column({ @Column({
type: DataType.STRING, type: DataType.STRING,
@ -21,10 +34,22 @@ export class User extends Model<User> {
}) })
password: string; password: string;
@Column({
type: DataType.STRING,
allowNull: true,
})
phoneNumber: string;
@Column({
type: DataType.STRING,
allowNull: true,
})
city: string;
@Column({ @Column({
type: DataType.ENUM, type: DataType.ENUM,
values: ['male', 'female'], values: ['male', 'female'],
allowNull: false, allowNull: true,
}) })
gender: string; gender: string;
} }

@ -0,0 +1,42 @@
import {
Body,
Controller,
Delete,
Get,
Param,
Patch,
Post,
} from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto, UpdateUserDto } from './dto';
import { UUID } from 'crypto';
@Controller('users')
export class UsersController {
constructor(private usersService: UsersService) {}
@Get()
findAll() {
return this.usersService.findAll();
}
@Get(':id')
findOne(@Param('id') id: UUID) {
return this.usersService.findOne(id);
}
@Post()
create(@Body() user: CreateUserDto) {
return this.usersService.create(user);
}
@Patch()
update(@Param('id') id: UUID, @Body() user: UpdateUserDto) {
return this.usersService.update(id, user);
}
@Delete(':id')
remove(@Param('id') id: UUID) {
return this.usersService.remove(id);
}
}

@ -1,9 +1,11 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { UsersService } from './users.service'; import { UsersService } from './users.service';
import { usersProviders } from './users.providers'; import { usersProviders } from './users.providers';
import { UsersController } from './users.controller';
@Module({ @Module({
providers: [UsersService, ...usersProviders], providers: [UsersService, ...usersProviders],
exports: [UsersService], exports: [UsersService],
controllers: [UsersController],
}) })
export class UsersModule {} export class UsersModule {}

@ -1,7 +1,10 @@
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { User } from './user.entity'; import { User } from './user.entity';
import { UserDto } from './dto/user.dto'; import { CreateUserDto, UpdateUserDto } from './dto';
import { USER_REPOSITORY } from '../../core/constants'; import { USER_REPOSITORY } from '../../core/constants';
import * as argon from 'argon2';
import * as _ from 'lodash';
import { UUID } from 'crypto';
@Injectable() @Injectable()
export class UsersService { export class UsersService {
@ -9,15 +12,44 @@ export class UsersService {
@Inject(USER_REPOSITORY) private readonly userRepository: typeof User, @Inject(USER_REPOSITORY) private readonly userRepository: typeof User,
) {} ) {}
async create(user: UserDto): Promise<User> { async findAll() {
return await this.userRepository.create<User>(user); return await this.userRepository.findAll();
} }
async findOneByEmail(email: string): Promise<User> { async findOne(id: UUID) {
return await this.userRepository.findOne<User>({ where: { email } }); return await this.userRepository.findAll({ where: { uuid: id } });
} }
async findOneById(id: number): Promise<User> { async create(user: CreateUserDto) {
return await this.userRepository.findOne<User>({ where: { id } }); const hashedPassword = await argon.hash(user.password);
user.password = hashedPassword;
const newUser = await this.userRepository.create(user);
return _.pick(newUser, [
'firstName',
'lastName',
'email',
'uuid',
'createdAt',
'updatedAt',
]);
}
async update(id: UUID, user: UpdateUserDto) {
const [numberOfAffectedRows, [updatedUser]] =
await this.userRepository.update(
{ ...user },
{ where: { uuid: id }, returning: true },
);
return { numberOfAffectedRows, updatedUser };
}
async remove(id: UUID) {
const deletedUser = await this.findOne(id);
await this.userRepository.destroy({ where: { uuid: id } });
return deletedUser;
} }
} }

Loading…
Cancel
Save