Skip to content

Create users controllers#6

Open
boiboi796 wants to merge 4 commits into
mainfrom
Create-Users-Controllers
Open

Create users controllers#6
boiboi796 wants to merge 4 commits into
mainfrom
Create-Users-Controllers

Conversation

@boiboi796
Copy link
Copy Markdown
Collaborator

##What I did:
I created the users controllers in the users folder.

Comment thread src/users/users.controller.ts Outdated
@Get()
async findAll(@Query('adminId', ParseIntPipe) adminId: number) {
const isAdmin = await this.usersService.isAdmin(adminId);
if (!isAdmin) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should a role guard

Comment thread src/users/users.controller.ts Outdated

@Get(':id')
async findById(@Query('adminId', ParseIntPipe) adminId: number, @Param('id', ParseIntPipe) id: number) {
const isAdmin = await this.usersService.isAdmin(adminId);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Role Guard

Copilot AI review requested due to automatic review settings February 18, 2026 11:58
@boiboi796 boiboi796 force-pushed the Create-Users-Controllers branch from c1b1b2f to 246a9f2 Compare February 18, 2026 11:58
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new Users module (controller/service/repository + DTOs and basic tests) and wires it into the existing NestJS application, alongside a small schema tightening for the users table.

Changes:

  • Added UsersController, UsersService, UsersRepository, and UsersModule under src/users/.
  • Added CreateUserDto validation for user creation.
  • Updated DB schema to make several user columns non-null and added jsonwebtoken dependency.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/users/users.service.ts Implements basic user operations and admin check.
src/users/users.service.spec.ts Adds a minimal UsersService test scaffold.
src/users/users.repository.ts Adds Drizzle repository methods for users CRUD reads/inserts.
src/users/users.module.ts Declares Users module with controller/service and DB import.
src/users/users.controller.ts Exposes /users endpoints including “admin-only” reads.
src/users/users.controller.spec.ts Adds a minimal UsersController test scaffold.
src/users/dto/users-dto.ts Introduces DTO + validation rules for user creation.
src/transactions/dto/create-transaction.dto.ts Removes an unused validator import.
src/db/schema.ts Makes user fields non-null and reformats schema definition.
src/app.module.ts Minor formatting-only change.
package.json Adds jsonwebtoken dependency.
package-lock.json Locks jsonwebtoken and transitive dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +16 to +22
@Get()
async findAll(@Query('adminId', ParseIntPipe) adminId: number) {
const isAdmin = await this.usersService.isAdmin(adminId);
if (!isAdmin) {
throw new ForbiddenException('Only admins can access this resource');
}
return this.usersService.findAll();
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Authorization is based on a client-supplied adminId query param, which can be trivially spoofed (any user can pass an admin's id). Replace this with server-validated authentication (e.g., derive the caller identity from an auth token / session) and a role check, rather than trusting request parameters.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +11

@Injectable()
export class UsersService {
constructor(private readonly usersRepository: UsersRepository) {}

async create(createUserDto: CreateUserDto) {
return this.usersRepository.create(createUserDto);
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CreateUserDto uses the property name passwordHash, but it is validated as a strong password and is passed straight into the password_hash DB column. This strongly suggests the API is accepting a plaintext password but storing it as-is; rename the field to password, hash it in the service, and only persist the hash.

Suggested change
@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.passwordHash, 10);
const userToCreate = { ...createUserDto, passwordHash: hashedPassword };
return this.usersRepository.create(userToCreate);

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +28
.select()
.from(users);
}

//for admin use only
async findById(id: number) {
return this.dbClient.select()
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findAll() selects and returns all user columns, including passwordHash. Even for admin-only endpoints, returning password hashes is unsafe and unnecessary. Select only non-sensitive fields (e.g., id, name, email, userType) or map results to omit passwordHash before returning.

Suggested change
.select()
.from(users);
}
//for admin use only
async findById(id: number) {
return this.dbClient.select()
.select({
id: users.id,
name: users.name,
email: users.email,
userType: users.userType,
})
.from(users);
}
//for admin use only
async findById(id: number) {
return this.dbClient
.select({
id: users.id,
name: users.name,
email: users.email,
userType: users.userType,
})

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +30
return this.dbClient
.select()
.from(users);
}

//for admin use only
async findById(id: number) {
return this.dbClient.select()
.from(users)
.where(eq(users.id, id));
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findById() selects and returns all user columns, including passwordHash, which should never be exposed via API responses. Restrict the selected columns or strip passwordHash from the returned object(s).

Suggested change
return this.dbClient
.select()
.from(users);
}
//for admin use only
async findById(id: number) {
return this.dbClient.select()
.from(users)
.where(eq(users.id, id));
const results = await this.dbClient
.select()
.from(users);
return results.map(({ passwordHash, ...userWithoutPasswordHash }) => userWithoutPasswordHash);
}
//for admin use only
async findById(id: number) {
const results = await this.dbClient
.select()
.from(users)
.where(eq(users.id, id));
return results.map(({ passwordHash, ...userWithoutPasswordHash }) => userWithoutPasswordHash);

Copilot uses AI. Check for mistakes.
Comment thread src/db/schema.ts
passwordHash: text('password_hash'),

userType: mysqlEnum('user_type', UserType).notNull()
.default(UserType.USER), // ADMIN or USER sert to user by default
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says "sert"; correct the typo to "set" ("... set to user by default").

Suggested change
.default(UserType.USER), // ADMIN or USER sert to user by default
.default(UserType.USER), // ADMIN or USER set to user by default

Copilot uses AI. Check for mistakes.
Comment thread src/users/users.module.ts Outdated
Comment on lines +5 to +8


@Module({
providers: [UsersService],
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UsersService injects UsersRepository, but UsersRepository is not registered in UsersModule providers. This will cause Nest to fail to resolve the dependency at runtime; add UsersRepository to the module's providers (and export it if other modules need it).

Suggested change
@Module({
providers: [UsersService],
import { UsersRepository } from './users.repository';
@Module({
providers: [UsersService, UsersRepository],

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +10
const module: TestingModule = await Test.createTestingModule({
controllers: [UsersController],
}).compile();
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This controller test registers UsersController without providing its UsersService dependency, so Nest will fail to instantiate the controller. Add UsersService to providers (and mock its dependencies) or override the provider with a mock.

Copilot uses AI. Check for mistakes.
Comment thread package.json
"class-validator": "^0.14.3",
"dotenv": "^17.2.3",
"drizzle-orm": "^0.45.1",
"jsonwebtoken": "^9.0.3",
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jsonwebtoken was added as a dependency but isn't used anywhere in the repository. If this PR doesn't introduce JWT usage yet, consider removing it to avoid extra supply-chain surface area and keep dependencies minimal.

Suggested change
"jsonwebtoken": "^9.0.3",

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +9

describe('UsersService', () => {
let service: UsersService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UsersService],
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This unit test module only provides UsersService, but UsersService requires UsersRepository. The test will fail to compile unless you provide UsersRepository (and its DB dependency) or mock UsersRepository in the providers array.

Suggested change
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;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UsersService,
{
provide: UsersRepository,
useValue: {},
},
],

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants