-
Notifications
You must be signed in to change notification settings - Fork 2
Feat/issue55 profile photo #394
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
Conversation
…leaking of s3 secrets
… update s3 module to use aws-sdk v3 syntax, remove unused file s3.ts
Added AWS S3 config to .env.sample Changed AWS config and secret names in .env.test Added example time stamp to s3.service.ts Defined RecnetError for S3 upload and delete errors and throw RecnetError in s3.service.ts
…edesign API endpoints to meet RESTful requirements Rename s3.service.ts to photo-storage.service.ts Rename s3.controller.ts to photo-storage.controller.ts Rename s3.module.ts to photo-storage.module.ts Updated app.module.ts to import the PhotoStorageModule correctly Modified getUploadUrl router to generateUploadUrl and use the POST method instead, because this request results in the creation of a new resource -the S3 URL which will be used later to upload a new photo. Hence POST is the appropriate method. Updated the corresponding method generateS3UploadUrl in the backend photo-storage.service.ts and photo-storage.controller.ts, update to POST method.
…oading large file
… document the request and response schema for photo-storage API endpoints
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
… Image component in ProfileEditForm.tsx to main square ratio
swh00tw
left a comment
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.
LGTM
| import { Controller, Delete, Post, Query } from "@nestjs/common"; | ||
| import { ApiOperation } from "@nestjs/swagger"; | ||
|
|
||
| import { PhotoStorageService } from "./photo-storage.service"; | ||
|
|
||
| @Controller("photo-storage") | ||
| export class PhotoStorageController { | ||
| constructor(private readonly photoStorageService: PhotoStorageService) {} | ||
| @ApiOperation({ | ||
| summary: "Generate S3 Upload URL", | ||
| description: | ||
| "Generate a secure signed Url to upload profile photo to S3 bucket", | ||
| }) | ||
| @Post("upload-url") | ||
| generateUploadUrl(): Promise<{ url: string }> { | ||
| return this.photoStorageService.generateS3UploadUrl(); | ||
| } | ||
|
|
||
| @ApiOperation({ | ||
| summary: "Delete S3 Object", | ||
| description: "Delete S3 Object (profile photo)", | ||
| }) | ||
| @Delete("photo") | ||
| async deleteS3Object(@Query("fileUrl") fileUrl: string): Promise<void> { | ||
| return this.photoStorageService.deleteS3Object(fileUrl); | ||
| } | ||
| } |
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.
It would be better if we add access control for these APIs, for example, only authenticated user can hit these endpoints, otherwise, return error. You can simply add @Auth() decorator to achieve this.
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.
Btw, you can use @UsePipes(new ZodValidationBodyPipe(theSchemaYouDefinedUnderRecnetAPIModel)) to check if the request fulfill the requirement (params, request body), if not, this decorator can help you handle the error throwing part.
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.
Although missing some decorators won't affect functionality, you can read files like user.controller.ts to know more about our decorators.
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.
I just saw these comments now! I'll try to make those edits after I set the env vars correctly and fix the conflicts.
|
Btw, before merge into |
## RecNet auto-release action This is an auto-generated PR by recnet-release-action 🤖 Please make sure to test your changes in staging before merging. ## Related Issues - #392 - #371 ## Related PRs - #394 - #391 ## Staging links recnet-web: [https://vercel.live/link/recnet-git-dev-recnet-542617e7.vercel.app](https://vercel.live/link/recnet-git-dev-recnet-542617e7.vercel.app) recnet-api: [https://dev-api.recnet.io/api](https://dev-api.recnet.io/api)
## RecNet auto-release action This is an auto-generated PR by recnet-release-action 🤖 Please make sure to test your changes in staging before merging. Recnet-api version bump for deployment. Related to PR#390. ## Related Issues - #379 - #55 - #371 ## Related PRs - #382 - #391 - #392 - #394 - #390 ## Staging links recnet-web: [https://vercel.live/link/recnet-git-dev-recnet-542617e7.vercel.app](https://vercel.live/link/recnet-git-dev-recnet-542617e7.vercel.app) recnet-api: [https://dev-api.recnet.io/api](https://dev-api.recnet.io/api)
Description
This PR adds a new edit profile photo feature. Prior to this, RecNet displays a user's Google account profile photo and does not allow changes. This feature allows any RecNet user to upload a profile photo, which is stored in an AWS S3 bucket and make updates to the user profile information in the database.
Related Issue
devbeforemaster.Frontend Changes
/apps/recnet/src/components/setting/profile/ProfileEditForm.tsxadding new form element and function:<input>element with a photo preview image to accept and display the selected photo.handleUploadS3function to get a secure uploadUrl from the backend, put objects to the S3 bucket, and update the form data.onSubmitfunction to call thehandleUploadS3function when a user saves the form.ProfileEditSchema,useFormhook to include the photoUrl field.generateUploadUrlMutationhook to send a request to the backend to get a secure S3 upload URL.[isUploading, setIsUploading],[selectedFile, setSelectedFile],[photoPreviewUrl, setPhotoPreviewUrl],[fileError, setFileError]to manage the selected photo and upload status.generateS3UploadUrlin the/apps/recnet/src/server/routers/user.tsupdateUserin/apps/recnet/src/server/routers/user.tsto fetch the original photoUrl and delete the corresponding S3 file if a new profile photo is uploaded.Backend Changes
photo-storageunder/apps/recnet-api/src/modulesphoto-storage.controler.tsto handle requests to thephoto-storageendpoint.photo-storage.service.ts. Included agenerateS3UploadUrlmethod and adeleteS3Objectmethod.photo-storage.module.tsto package and export the s3 class.common.config.tsunder/apps/recnet-api/src/configto register AWS S3 configuration.env.schema.tsunder/apps/recnet-api/src/configto include the s3 environment variable data types.app.module.tsunder/apps/recnet-api/srcto include and import thePhotoStorageModule.Other Changes
photo-storage.tsunder/libs/recnet-api-model/src/lib/apito document the new APIs related tophoto-storage.package.jsonto includeaws-sdk/client-s3andaws-sdk/s3-request-presigner.@aws-sdk/client-s3 @aws-sdk/s3-request-presigner. Make sure to use aws-sdk v3.How To Test
Screenshots (if appropriate):
TODO
.envfile under/apps/recnet-apifor the dev and prod environment for deployment