-
Notifications
You must be signed in to change notification settings - Fork 71
Feat/remove disabled files #189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,105 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Request, Response } from "express"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { CreateUserUseCase } from "../../use-cases/userUseCase"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { GetUserByIdUseCase } from "../../use-cases/userUseCase"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { GetUserByEmailUseCase } from "../../use-cases/userUseCase"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { UpdateUserUseCase } from "../../use-cases/userUseCase"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { DeleteUserUseCase } from "../../use-cases/userUseCase"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { PrismaUserRepository } from "../../repositories/PrismaUserRepository"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { CreateUserDto } from "../../dto/CreateUserDto"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { UpdateUserDto } from "../../dto/UpdateUserDto"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| export default class UserController { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| private userRepository: PrismaUserRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| private createUserUseCase: CreateUserUseCase; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| private getUserByIdUseCase: GetUserByIdUseCase; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| private getUserByEmailUseCase: GetUserByEmailUseCase; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| private updateUserUseCase: UpdateUserUseCase; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| private deleteUserUseCase: DeleteUserUseCase; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| constructor() { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| this.userRepository = new PrismaUserRepository(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| this.createUserUseCase = new CreateUserUseCase(this.userRepository); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| this.getUserByIdUseCase = new GetUserByIdUseCase(this.userRepository); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| this.getUserByEmailUseCase = new GetUserByEmailUseCase(this.userRepository); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| this.updateUserUseCase = new UpdateUserUseCase(this.userRepository); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| this.deleteUserUseCase = new DeleteUserUseCase(this.userRepository); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| async createUser(req: Request, res: Response): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const userDto = new CreateUserDto(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Object.assign(userDto, req.body); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| const user = await this.createUserUseCase.execute(userDto); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(201).json(user); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error: unknown) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(400).json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| error: error instanceof Error ? error.message : "Unknown error", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+28
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Prevent leaking sensitive fields in create response; add DTO validation and consistent error mapping. Currently, Apply this diff in async createUser(req: Request, res: Response): Promise<void> {
try {
- const userDto = new CreateUserDto();
- Object.assign(userDto, req.body);
-
- const user = await this.createUserUseCase.execute(userDto);
- res.status(201).json(user);
+ const userDto = Object.assign(new CreateUserDto(), req.body);
+ if (!(await this.validateOr400(userDto, res))) return;
+ const user = await this.createUserUseCase.execute(userDto);
+ res.status(201).json(this.toSafeUser(user));
} catch (error: unknown) {
- res.status(400).json({
- error: error instanceof Error ? error.message : "Unknown error",
- });
+ this.handleError(res, error);
}
}Add the helper methods shown in a later comment to support
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| async getUserById(req: Request, res: Response): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const { id } = req.params; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const user = await this.getUserByIdUseCase.execute(id); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!user) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(404).json({ error: "User not found" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(200).json(user); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error: unknown) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(400).json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| error: error instanceof Error ? error.message : "Unknown error", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+42
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Fix unreachable 404 branch; validate
async getUserById(req: Request, res: Response): Promise<void> {
try {
- const { id } = req.params;
- const user = await this.getUserByIdUseCase.execute(id);
- if (!user) {
- res.status(404).json({ error: "User not found" });
- return;
- }
- res.status(200).json(user);
+ const { id } = req.params;
+ if (!id) {
+ res.status(400).json({ error: "User ID is required" });
+ return;
+ }
+ const user = await this.getUserByIdUseCase.execute(id);
+ res.status(200).json(this.toSafeUser(user));
} catch (error: unknown) {
- res.status(400).json({
- error: error instanceof Error ? error.message : "Unknown error",
- });
+ this.handleError(res, error);
}
}
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| async getUserByEmail(req: Request, res: Response): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const { email } = req.query; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!email) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(400).json({ error: "Email is required" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const user = await this.getUserByEmailUseCase.execute(email as string); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!user) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(404).json({ error: "User not found" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(200).json(user); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error: unknown) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(400).json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| error: error instanceof Error ? error.message : "Unknown error", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+58
to
+76
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Harden query param parsing; remove unreachable 404; return safe payload; unify error handling.
async getUserByEmail(req: Request, res: Response): Promise<void> {
try {
- const { email } = req.query;
- if (!email) {
- res.status(400).json({ error: "Email is required" });
- return;
- }
- const user = await this.getUserByEmailUseCase.execute(email as string);
- if (!user) {
- res.status(404).json({ error: "User not found" });
- return;
- }
- res.status(200).json(user);
+ const raw = req.query.email;
+ const email =
+ typeof raw === "string" ? raw : Array.isArray(raw) ? raw[0] : "";
+ if (!email) {
+ res.status(400).json({ error: "Email is required" });
+ return;
+ }
+ const user = await this.getUserByEmailUseCase.execute(email);
+ res.status(200).json(this.toSafeUser(user));
} catch (error: unknown) {
- res.status(400).json({
- error: error instanceof Error ? error.message : "Unknown error",
- });
+ this.handleError(res, error);
}
}
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| async updateUser(req: Request, res: Response): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const { id } = req.params; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const userDto = new UpdateUserDto(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Object.assign(userDto, req.body); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| userDto.id = id; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| await this.updateUserUseCase.execute(userDto); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(200).json({ message: "User updated successfully" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error: unknown) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(400).json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| error: error instanceof Error ? error.message : "Unknown error", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+78
to
+92
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Validate update DTO; guard missing Without explicit validation, DTO decorators don’t run. Also, Prisma will throw on missing/invalid async updateUser(req: Request, res: Response): Promise<void> {
try {
- const { id } = req.params;
- const userDto = new UpdateUserDto();
- Object.assign(userDto, req.body);
- userDto.id = id;
-
- await this.updateUserUseCase.execute(userDto);
+ const { id } = req.params;
+ if (!id) {
+ res.status(400).json({ error: "User ID is required" });
+ return;
+ }
+ const userDto = Object.assign(new UpdateUserDto(), req.body);
+ userDto.id = id;
+ if (!(await this.validateOr400(userDto, res))) return;
+ await this.updateUserUseCase.execute(userDto);
res.status(200).json({ message: "User updated successfully" });
} catch (error: unknown) {
- res.status(400).json({
- error: error instanceof Error ? error.message : "Unknown error",
- });
+ this.handleError(res, error);
}
}
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| async deleteUser(req: Request, res: Response): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const { id } = req.params; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| await this.deleteUserUseCase.execute(id); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(200).json({ message: "User deleted successfully" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error: unknown) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(400).json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| error: error instanceof Error ? error.message : "Unknown error", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+94
to
+104
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Guard missing Keep 200 for compatibility, but ensure param validation and consistent error mapping. async deleteUser(req: Request, res: Response): Promise<void> {
try {
- const { id } = req.params;
- await this.deleteUserUseCase.execute(id);
+ const { id } = req.params;
+ if (!id) {
+ res.status(400).json({ error: "User ID is required" });
+ return;
+ }
+ await this.deleteUserUseCase.execute(id);
res.status(200).json({ message: "User deleted successfully" });
} catch (error: unknown) {
- res.status(400).json({
- error: error instanceof Error ? error.message : "Unknown error",
- });
+ this.handleError(res, error);
}
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+94
to
+105
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add centralized helpers for safe responses, validation, and error mapping (P2002 → 409, P2025/not found → 404). Reduces duplication and enforces consistent status codes aligned with the intended API. async deleteUser(req: Request, res: Response): Promise<void> {
try {
const { id } = req.params;
if (!id) {
res.status(400).json({ error: "User ID is required" });
return;
}
await this.deleteUserUseCase.execute(id);
res.status(200).json({ message: "User deleted successfully" });
} catch (error: unknown) {
- res.status(400).json({
- error: error instanceof Error ? error.message : "Unknown error",
- });
+ this.handleError(res, error);
}
}
+
+ // Centralized helpers
+ private toSafeUser(user: any) {
+ if (!user) return user;
+ const { password, verificationToken, verificationTokenExpires, ...safe } = user;
+ return safe;
+ }
+
+ private async validateOr400(dto: object, res: Response): Promise<boolean> {
+ const errors = await validate(dto as any);
+ if (errors.length > 0) {
+ res.status(400).json({
+ errors: errors.map((e: any) => ({
+ field: e.property,
+ constraints: e.constraints ?? {},
+ })),
+ });
+ return false;
+ }
+ return true;
+ }
+
+ private handleError(res: Response, error: unknown): void {
+ if (error && typeof error === "object" && "code" in (error as any)) {
+ const code = (error as any).code;
+ if (code === "P2002") {
+ res.status(409).json({ error: "Email already in use" });
+ return;
+ }
+ if (code === "P2025") {
+ res.status(404).json({ error: "User not found" });
+ return;
+ }
+ }
+ if (error instanceof Error && /not found/i.test(error.message)) {
+ res.status(404).json({ error: error.message });
+ return;
+ }
+ res.status(400).json({
+ error: error instanceof Error ? error.message : "Unknown error",
+ });
+ }
}
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Wallet made optional: contract change looks good; confirm downstream assumptions
Aligns with the entity change. Please verify no service/mapper still treats
walletas required and that a DB migration exists to makeusers.walletnullable in all environments.Run:
🏁 Script executed:
Length of output: 5604
🏁 Script executed:
Length of output: 1013
Add missing DB migration and update code to handle optional wallet
users.walletto nullable; add a migration (e.g. via Prisma) to alter the column in all environments.user.wallet = data.walletwallet: stringand default""walletparameter still required__tests__still expectwalletto always be present🤖 Prompt for AI Agents