Skip to content

Commit

Permalink
Feat(User): Edit user details route
Browse files Browse the repository at this point in the history
  • Loading branch information
Artur-Poffo committed Feb 19, 2024
1 parent 8a74ea8 commit 501c963
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 15 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@
### Users
- [x] GET /users/:userId - Get user details
- [x] POST /users - Register user
- [ ] PUT /users/:userId - Update user
- [x] PUT /users/:userId - Update user
- [ ] DELETE /users/:userId - Delete user

### Sessions
Expand Down Expand Up @@ -272,4 +272,5 @@
- [x] Introduce domain events for Prisma repositories.
- [ ] Implement mappers for mapping domain entities to DTOs.
- [ ] Implement pagination.
- [ ] Implement E2E tests.
- [ ] Implement E2E tests.
- [ ] Implement register user validations, like: email and cpf.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"prisma:init": "prisma migrate deploy && prisma generate",
"test:unit": "vitest run",
"test:unit:watch": "vitest",
"test:e2e": "vitest run --config ./vitest.config.e2e.ts",
"test:e2e:watch": "vitest --config ./vitest.config.e2e.ts",
"test:e2e": "vitest run --config ./vitest.config.e2e.mts",
"test:e2e:watch": "vitest --config ./vitest.config.e2e.mts",
"test:cov": "vitest run --coverage",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix"
},
Expand Down Expand Up @@ -50,4 +50,4 @@
"vite-tsconfig-paths": "^4.3.1",
"vitest": "^1.2.1"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { left, right, type Either } from '@/core/either'
import { type UseCase } from '@/core/use-cases/use-case'
import { type Instructor } from '../../enterprise/entities/instructor'
import { Student } from '../../enterprise/entities/student'
import { Instructor } from '../../enterprise/entities/instructor'
import { type HashGenerator } from '../cryptography/hash-generator'
import { type InstructorsRepository } from '../repositories/instructors-repository'
import { InstructorAlreadyExistsError } from './errors/instructor-already-exists-error'
Expand Down Expand Up @@ -48,7 +47,7 @@ export class RegisterInstructorUseCase implements UseCase<RegisterInstructorUseC

const hashedPassword = await this.hashGenerator.hash(password)

const instructor = Student.create({
const instructor = Instructor.create({
name,
email,
passwordHash: hashedPassword,
Expand Down
7 changes: 5 additions & 2 deletions src/infra/database/prisma/mappers/user-mapper.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { UniqueEntityID } from '@/core/entities/unique-entity-id'
import { type CoursesRepository } from '@/domain/course-management/application/repositories/courses-repository'
import { type EnrollmentsRepository } from '@/domain/course-management/application/repositories/enrollments-repository'
import { type EvaluationsRepository } from '@/domain/course-management/application/repositories/evaluations-repository'
Expand Down Expand Up @@ -31,7 +32,8 @@ export class UserMapper {
bannerImageKey: raw.bannerImageKey,
profileImageKey: raw.profileImageKey,
registeredAt: raw.registeredAt
})
},
new UniqueEntityID(raw.id))
}

return Student.create({
Expand All @@ -44,7 +46,8 @@ export class UserMapper {
bannerImageKey: raw.bannerImageKey,
profileImageKey: raw.profileImageKey,
registeredAt: raw.registeredAt
})
},
new UniqueEntityID(raw.id))
}

async toPrisma(user: User<StudentProps | InstructorProps>): Promise<Prisma.UserUncheckedCreateInput> {
Expand Down
6 changes: 3 additions & 3 deletions src/infra/http/controllers/authenticate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { makeAuthenticateUserUseCase } from '@/infra/use-cases/factories/make-au
import { type FastifyReply, type FastifyRequest } from 'fastify'
import { z } from 'zod'

const authenticateBodySchema = z.object({
const authenticateUserBodySchema = z.object({
email: z.string().email(),
password: z.string()
})

export async function authenticateController(request: FastifyRequest, reply: FastifyReply) {
const { email, password } = authenticateBodySchema.parse(request.body)
export async function authenticateUserController(request: FastifyRequest, reply: FastifyReply) {
const { email, password } = authenticateUserBodySchema.parse(request.body)

const authenticateUserUseCase = makeAuthenticateUserUseCase(reply)

Expand Down
85 changes: 85 additions & 0 deletions src/infra/http/controllers/edit-user-details.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { ResourceNotFoundError } from '@/core/errors/errors/resource-not-found-error'
import { makeInstructorMapper } from '@/infra/database/prisma/mappers/factories/make-instructor-mapper'
import { makeStudentMapper } from '@/infra/database/prisma/mappers/factories/make-student-mapper'
import { makeEditInstructorDetailsUseCase } from '@/infra/use-cases/factories/make-edit-instructor-details-use-case'
import { makeEditStudentDetailsUseCase } from '@/infra/use-cases/factories/make-edit-student-details-use-case'
import { type FastifyReply, type FastifyRequest } from 'fastify'
import { z } from 'zod'
import { UserPresenter } from '../presenters/user-presenter'

const editUserDetailsBodySchema = z.object({
email: z.string().email().optional(),
age: z.number().optional(),
summary: z.string().optional(),
profileImageKey: z.string().optional(),
bannerImageKey: z.string().optional()
})

export async function editUserDetailsController(request: FastifyRequest, reply: FastifyReply) {
const { email, age, summary, bannerImageKey, profileImageKey } = editUserDetailsBodySchema.parse(request.body)
const { role } = request.user

if (role === 'STUDENT') {
const editStudentDetailsUseCase = makeEditStudentDetailsUseCase()

console.log(request.user)

const result = await editStudentDetailsUseCase.exec({
email,
age,
summary,
bannerImageKey,
profileImageKey,
studentId: request.user.sub
})

if (result.isLeft()) {
const error = result.value

switch (error.constructor) {
case ResourceNotFoundError:
return await reply.status(404).send({ message: error.message })
default:
return await reply.status(500).send({ message: error.message })
}
}

const studentMapper = makeStudentMapper()
const user = await studentMapper.toPrisma(result.value.student)

return await reply.status(200).send({
user: UserPresenter.toHTTP(user)
})
}

if (role === 'INSTRUCTOR') {
const EditInstructorDetailsUseCase = makeEditInstructorDetailsUseCase()

const result = await EditInstructorDetailsUseCase.exec({
email,
age,
summary,
bannerImageKey,
profileImageKey,
instructorId: request.user.sub
})

if (result.isLeft()) {
const error = result.value

switch (error.constructor) {
case ResourceNotFoundError:
return await reply.status(404).send({ message: error.message })
default:
return await reply.status(500).send({ message: error.message })
}
}

const instructorMapper = makeInstructorMapper()
const user = await instructorMapper.toPrisma(result.value.instructor)

return await reply.status(200).send({
user: UserPresenter.toHTTP(user)
})
}
}
8 changes: 6 additions & 2 deletions src/infra/http/routes/user.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { type FastifyInstance } from 'fastify'
import { authenticateController } from '../controllers/authenticate'
import { authenticateUserController } from '../controllers/authenticate'
import { editUserDetailsController } from '../controllers/edit-user-details'
import { getUserDetailsController } from '../controllers/get-user-details'
import { registerUserController } from '../controllers/register-user'
import { verifyJwt } from '../middlewares/verify-jwt'

export async function userRoutes(app: FastifyInstance) {
app.post('/users', registerUserController)
app.post('/sessions', authenticateController)
app.post('/sessions', authenticateUserController)

app.put('/users', { onRequest: verifyJwt }, editUserDetailsController)

app.get('/users/:userId', getUserDetailsController)
}
File renamed without changes.

0 comments on commit 501c963

Please sign in to comment.