created users module service and repository, also modified the schema to accept users credentials compulsorily#5
created users module service and repository, also modified the schema to accept users credentials compulsorily#5boiboi796 wants to merge 2 commits into
Conversation
… to accept users credentials compulsorily
|
|
||
| @IsString() | ||
| @IsNotEmpty() | ||
| @Length(8, 20) |
There was a problem hiding this comment.
A strong password should contain atleast 8 characters, contain one lower letter, one upper case letter, one number and one special character, you can create a validation rule for this.
Look into how to do it using class validator
There was a problem hiding this comment.
Pull request overview
This PR creates the foundational users module infrastructure for the application, including a service, repository, and DTO for user management. It also updates the database schema to make user credentials (name, email, passwordHash) required fields instead of optional.
Changes:
- Created users module with service, repository, and DTO structure
- Modified database schema to enforce non-null constraints on user credentials
- Added jsonwebtoken package dependency for future authentication features
- Cleaned up unused Length import from transaction DTO
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/users/users.service.ts | New service implementing user CRUD operations and admin role checking |
| src/users/users.service.spec.ts | Basic test scaffold for UsersService |
| src/users/users.repository.ts | New repository for database operations on users table |
| src/users/users.module.ts | Module configuration for users feature |
| src/users/dto/users-dto.ts | DTO for user creation with validation rules for name, email, and password |
| src/transactions/dto/create-transaction.dto.ts | Removed unused Length import |
| src/db/schema.ts | Made user credentials non-nullable and added formatting improvements |
| src/app.module.ts | Minor whitespace change |
| package.json | Added jsonwebtoken dependency |
| package-lock.json | Dependency lockfile updates for jsonwebtoken and its transitive dependencies |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| @Injectable() | ||
| export class UsersService { | ||
| constructor(private readonly usersRepository: UsersRepository) {} | ||
|
|
||
| async create(createUserDto: CreateUserDto) { | ||
| return this.usersRepository.create(createUserDto); |
There was a problem hiding this comment.
The create method should hash the password before storing it in the database. Currently, it's passing the DTO directly to the repository, which would store the plain text password. This is a critical security vulnerability. Consider using a library like bcrypt to hash the password before insertion.
| @Injectable() | |
| export class UsersService { | |
| constructor(private readonly usersRepository: UsersRepository) {} | |
| async create(createUserDto: CreateUserDto) { | |
| return this.usersRepository.create(createUserDto); | |
| import * as bcrypt from 'bcrypt'; | |
| @Injectable() | |
| export class UsersService { | |
| constructor(private readonly usersRepository: UsersRepository) {} | |
| async create(createUserDto: CreateUserDto) { | |
| const hashedPassword = await bcrypt.hash(createUserDto.password, 10); | |
| const userToCreate = { ...createUserDto, password: hashedPassword }; | |
| return this.usersRepository.create(userToCreate); |
|
|
||
| @IsString() | ||
| @IsNotEmpty() | ||
| @Length(8, 20) |
There was a problem hiding this comment.
The @Length decorator is redundant here since @IsStrongPassword already validates that minLength is 8. The @Length decorator with a maximum of 20 characters could conflict with security best practices, as it arbitrarily limits password strength. Consider removing the @Length decorator and relying solely on @IsStrongPassword, or if a maximum length is needed for database constraints, increase it significantly (e.g., 128 characters).
|
|
||
| describe('UsersService', () => { | ||
| let service: UsersService; | ||
|
|
||
| beforeEach(async () => { | ||
| const module: TestingModule = await Test.createTestingModule({ | ||
| providers: [UsersService], |
There was a problem hiding this comment.
The UsersRepository dependency is missing from the test module providers. The test will fail because UsersService requires UsersRepository to be injected. Add UsersRepository to the providers array or create a mock for it.
| describe('UsersService', () => { | |
| let service: UsersService; | |
| beforeEach(async () => { | |
| const module: TestingModule = await Test.createTestingModule({ | |
| providers: [UsersService], | |
| import { UsersRepository } from './users.repository'; | |
| describe('UsersService', () => { | |
| let service: UsersService; | |
| const mockUsersRepository = {}; | |
| beforeEach(async () => { | |
| const module: TestingModule = await Test.createTestingModule({ | |
| providers: [ | |
| UsersService, | |
| { | |
| provide: UsersRepository, | |
| useValue: mockUsersRepository, | |
| }, | |
| ], |
| passwordHash: text('password_hash'), | ||
|
|
||
| userType: mysqlEnum('user_type', UserType).notNull() | ||
| .default(UserType.USER), // ADMIN or USER sert to user by default |
There was a problem hiding this comment.
Typo in comment: 'sert' should be 'set'.
| .default(UserType.USER), // ADMIN or USER sert to user by default | |
| .default(UserType.USER), // ADMIN or USER set to user by default |
|
|
||
|
|
||
| @Module({ | ||
| providers: [UsersService], |
There was a problem hiding this comment.
The UsersRepository is used by UsersService but is not included in the providers array. This will cause a dependency injection error at runtime when UsersService tries to inject UsersRepository in its constructor.
| @Module({ | |
| providers: [UsersService], | |
| import { UsersRepository } from './users.repository'; | |
| @Module({ | |
| providers: [UsersService, UsersRepository], |
| {message: 'Password must be at least 8 characters long and include uppercase letters, lowercase letters, numbers, and symbols.', | ||
| } | ||
| ) | ||
| passwordHash: string; |
There was a problem hiding this comment.
The field is named 'passwordHash' but this DTO will receive the plain text password from the user, not a hashed password. The field should be named 'password', and the password hashing should happen in the service layer before passing it to the repository. Receiving a pre-hashed password from the client would be a security vulnerability.
| passwordHash: string; | |
| password: string; |
##What I did:
I used CLI tools to generate the user module, service, and repository
Updated the schema so that users' credentials will not be optional