Skip to content

Commit

Permalink
Merge branch 'master' into edit-user
Browse files Browse the repository at this point in the history
  • Loading branch information
MatheusSanchez authored Feb 3, 2024
2 parents 29f8c23 + 88670e2 commit 8f22a14
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/controller/user/addImageToUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { FastifyReply, FastifyRequest } from 'fastify'
import { z } from 'zod'
import { ResourceNotFoundError } from '../../use-cases/errors/ResourceNotFoundError'
import { AwsS3Error } from '../../use-cases/errors/AwsS3Error'
import { PrismaUsersRepository } from '../../repositories/prisma/prisma-users-repository'
import { AddImageToUserUseCase } from '../../use-cases/user/addImageToUserUseCase'

export async function addImageUser(
request: FastifyRequest,
response: FastifyReply,
) {
const userRepository = new PrismaUsersRepository()
const addImageToUserUseCase = new AddImageToUserUseCase(userRepository)
const addImageUserParamsSchema = z.object({
userId: z.string().uuid(),
})

const { userId } = addImageUserParamsSchema.parse(request.params)
const photo = await request.file()

if (photo === undefined) {
return response.status(400).send({ error: 'Fail load a photo!' })
}

try {
const { user } = await addImageToUserUseCase.execute({ userId, photo })
return response.status(200).send({ user })
} catch (error) {
if (error instanceof ResourceNotFoundError) {
return response.status(400).send({ error: 'User was not found !' })
} else if (error instanceof AwsS3Error) {
return response.status(400).send({ error: error.message })
}
throw error
}
}
9 changes: 9 additions & 0 deletions src/controller/user/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@ import { getUserById } from './getUserById'
import { getUserByEmail } from './getUserByEmail'
import { registerUser } from './registerUser'
import { editUserById } from './editUserById'
import { addImageUser } from './addImageToUser'
import FastifyMultipart from '@fastify/multipart'

export async function userRoutes(app: FastifyInstance) {
app.register(FastifyMultipart, {
limits: {
files: 1,
fileSize: 1000000, // the max file size in bytes
},
})
app.post('/user', registerUser)
app.get('/user/:id', getUserById)
app.get('/user', getUserByEmail)
app.put('/user/:userId/edit', editUserById)
app.post('/user/:userId/photo', addImageUser)
}
4 changes: 4 additions & 0 deletions src/repositories/in-memory-db/inMemoryUserRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export class InMemoryUserRepository implements UserRepository {
return user
}


async edit({
name,
surname,
Expand All @@ -69,4 +70,7 @@ export class InMemoryUserRepository implements UserRepository {

return this.db[indexToUpdate]
}
async addPhotoUrl(projectId: string, photoUrl: string): Promise<Project> {
throw new Error('Method not implemented.')
}
}
15 changes: 15 additions & 0 deletions src/repositories/prisma/prisma-users-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class PrismaUsersRepository implements UserRepository {
return user
}


async edit({
name,
surname,
Expand All @@ -44,4 +45,18 @@ export class PrismaUsersRepository implements UserRepository {

return user
}


async addPhotoUrl(userId: string, photoUrl: string): Promise<User> {
const user = await prisma.user.update({
where: {
id: userId,
},
data: {
avatar_url: photoUrl,
},
})

return user
}
}
1 change: 1 addition & 0 deletions src/repositories/user-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export interface UserRepository {
findByEmail(email: string): Promise<User | null>
findById(id: string): Promise<User | null>
edit({ name, surname, country, userId }: editUserRequestPrisma): Promise<User>
addPhotoUrl(userId: string, photoUrl: string): Promise<User>
}
74 changes: 74 additions & 0 deletions src/use-cases/user/addImageToUserUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { User } from '@prisma/client'

import { ResourceNotFoundError } from '../errors/ResourceNotFoundError'
import { MultipartFile } from '@fastify/multipart'
import { randomUUID } from 'node:crypto'
import { env } from '../../env'
import path from 'node:path'
import fs from 'node:fs'
import { PutObjectCommand, S3Client, S3ClientConfig } from '@aws-sdk/client-s3'
import pump from 'pump'
import { AwsS3Error } from '../errors/AwsS3Error'
import { UserRepository } from '../../repositories/user-repository'

interface AddImageToUserUseCaseRequest {
userId: string
photo: MultipartFile
}

interface AddImageToUserUseCaseResponse {
user: User
}

export class AddImageToUserUseCase {
constructor(private userRepository: UserRepository) {}

async execute({
userId,
photo,
}: AddImageToUserUseCaseRequest): Promise<AddImageToUserUseCaseResponse> {
const userToBeUpdated = await this.userRepository.findById(userId)

if (!userToBeUpdated) {
throw new ResourceNotFoundError()
}

const newFileName = randomUUID() + photo.filename.replace(/\s/g, '')
let photoUrl = ''

if (env.STORAGE_TYPE === 'local') {
const uploadPath = path.resolve(__dirname, '..', 'tmp', 'uploads')
const writeSteam = fs.createWriteStream(`${uploadPath}/${newFileName}`)
await pump(photo.file, writeSteam)
photoUrl = `${uploadPath}/${newFileName}`
} else {
const s3bucket = new S3Client({
region: env.REGION,

credentials: {
accessKeyId: env.ACCESS_KEY_ID,
secretAccessKey: env.SECRET_ACCESS_KEY,
},
} as S3ClientConfig)

const putObjectCommand = new PutObjectCommand({
Bucket: env.BUCKET_NAME,
Key: newFileName,
Body: await photo.toBuffer(),
ContentType: photo.mimetype,
ACL: 'public-read',
})

const publishs3Result = await s3bucket.send(putObjectCommand)

if (publishs3Result.$metadata.httpStatusCode !== 200) {
throw new AwsS3Error()
}
photoUrl = env.AWS_S3_URL + newFileName
}

const user = await this.userRepository.addPhotoUrl(userId, photoUrl)

return { user }
}
}

0 comments on commit 8f22a14

Please sign in to comment.