-
Notifications
You must be signed in to change notification settings - Fork 4
21 front user profile #55
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?
Conversation
- adapt dev-docker-compose (env, template, other services) - mount upload volume (for avatars) - envalid + react router dom + types - adapt tsconfig for vite - nginx conf fallback on index (spa) - export appenv with envalid
- use app.log as logger
- temporarily move old index as admin.html - folders api, components, pages, styles
- with vite (not tested on prod) - need form, buttons and styling
- add components tested in Stackblitz - add font Quantico - add lint lib for react
- flubber dependency for svg morphing - component PageContainer - adapt Navbar - adjust svg and animation for menu elements - adjust layering for responsiveness
- using i118next and related libs - json for en and fr locales chore: rename core as types - reuse DTOs and schemas from core package
- auth Provider and useAuth() - dev buttons for login with roles and logout - ProfileAuthDTO intersection type
- route /me redirecting to /profile/<username> - isOwner check for display of sensitive fields (no role check) - queries using Axios and ReactQuery - register and login from dev buttons - user info stored in LocalStorage (temporary solution, not secure) - nginx config + add Vite dev port to CORS fix(GATE): types of user chore(UM): change path to GET /username/:username chore(AUTH): less verbose logs for /health
- DELETE - PATCH avatar - update route for doc
- gateway : use fastify/reply-from to transfer multipart body as stream - friends : remove authPlugin and tests for 401 (this is already managed by gateway) - profile : change route to GET /users/username/:username - UM : absolute path for binding volumes - move db to data root folder - bind upload to users and nginx - adapt Makefile + Docker compose to reset permissions on volumes
- proxy in vite config for CORS issue - nginx route for uploads - nginx ensure that cookies are sent back - api clients : auth + profile - authProvider : single source of truth for user - Avatar : better handling of default (yet still buggy) - FileUploader : handle drag-drop events, prevalidation - ProfilePage : handle upload using react-query + basic bar
- fix: copy extra nginx conf file in Dockerfile
- adapt dev compose and nginx Dockerfile.dev
- POST : 201, 400 - PATCH : 200, 400 - DELETE : 200, 404
- update schema with 2 kinds of nicknames
- removed extra container - restored old commands in Makefile misc(NGINX): rename dashboard.html Makefile srcs/docker-compose.yml srcs/gateway/src/utils/constants.ts srcs/nginx/conf.d/default.conf srcs/nginx/src/html/dashboard.html srcs/users/Dockerfile srcs/users/prisma.config.ts srcs/users/src/config/env.ts srcs/users/src/controllers/profiles.controller.ts
- serve dashboard at /dashboard in prod - default route / temporarily serves profile - menu stats instead of profile - navbar avatar redirects to /me on click srcs/nginx/Dockerfile srcs/nginx/conf.d/default.conf srcs/nginx/src/App.tsx srcs/nginx/src/components/atoms/MenuElement.tsx srcs/nginx/src/components/molecules/NavBar.tsx srcs/nginx/src/locales/en/common.json srcs/nginx/src/locales/fr/common.json srcs/nginx/src/pages/ProfilePage.tsx srcs/nginx/src/types/react-types.ts srcs/nginx/tsconfig.json srcs/users/tsconfig.json
- get /users/username returns a ProfileSimpleDTO if x-user-name header differs from requested one - no get /me route in API yet (faked in the client) srcs/nginx/src/api/profile-api.ts srcs/nginx/src/components/atoms/DevLogin.tsx srcs/shared/core/src/index.ts srcs/shared/core/src/schemas/profile.schema.ts srcs/users/src/controllers/profiles.controller.ts srcs/users/src/routes/profiles.routes.ts
- fixed ESLint in PR scope (185 to go) - fixed test
- add default {} to prevent Fastify 400 error
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.
Pull request overview
This pull request introduces a React-based frontend for the user profile page with avatar upload functionality, along with significant backend improvements across multiple microservices.
Changes:
- Implements React frontend with profile page, avatar upload, and reusable components
- Adds PATCH
/users/username/:username/avatarand DELETE/users/username/:usernameendpoints - Enhances gateway to handle multipart form-data streaming using
@fastify/reply-from - Improves test coverage for profiles and friends services
- Updates Nginx configuration for better proxy handling and static file serving
- Migrates from vanilla JS/HTML to React with Vite build system
Reviewed changes
Copilot reviewed 135 out of 142 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
| srcs/users/src/services/profiles.service.ts | Added avatar upload logic with file validation and storage |
| srcs/users/src/controllers/profiles.controller.ts | Added updateProfileAvatar and deleteProfile endpoints |
| srcs/users/src/data/profiles.data.ts | Implemented file storage and avatar URL updates |
| srcs/users/Dockerfile | Modified user permissions (security concern - running as root) |
| srcs/gateway/src/utils/proxy.ts | Added fastStreamProxy for efficient multipart proxying |
| srcs/gateway/src/index.ts | Enhanced multipart and JSON content type parsers |
| srcs/nginx/conf.d/default.conf | Refactored proxy configuration with reusable headers |
| srcs/nginx/src/components/* | New React component library for profile UI |
| srcs/nginx/src/api/profile-api.ts | Client-side API for profile operations |
| Test files | Comprehensive unit tests for profiles and friends services |
Files not reviewed (1)
- srcs/nginx/package-lock.json: Language not supported
| proxy_pass_header Set-Cookie; # laisser passer le cookie du backend au frontend | ||
| proxy_cookie_path / /; # le cookie depose par auth/login sera bien renvoye sur un appel a users/xxx | ||
| proxy_pass_request_body on; | ||
| client_max_body_size 50M; |
Copilot
AI
Jan 20, 2026
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.
The client_max_body_size is set to 50M, which seems excessive for avatar uploads. The multipart plugin is configured with a 5MB limit, creating an inconsistency. Consider aligning both limits to a reasonable value (e.g., 5-10MB) to prevent abuse and ensure consistency.
| # ENV USER_ID=1001 | ||
| # ENV GROUP_ID=204 | ||
|
|
||
| # RUN apk add --no-cache wget python3 make g++ \ | ||
| # && addgroup -g ${GROUP_ID} -S appgroup \ | ||
| # && adduser -u ${USER_ID} -S -G appgroup appuser |
Copilot
AI
Jan 20, 2026
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.
The Docker security settings have been commented out, leaving the service running as root. This is a security risk in production. The commented lines show user/group creation was intentional but disabled.
Consider re-enabling these lines or documenting why they were disabled. Running as root violates the principle of least privilege.
| const allowedMimeTypes = ['image/png', 'image/jpeg', 'image/webp']; | ||
| if (!allowedMimeTypes.includes(file.mimetype)) { | ||
| throw new AppError(ERR_DEFS.RESSOURCE_INVALID_TYPE, { details: 'Invalid file type' }); | ||
| } |
Copilot
AI
Jan 20, 2026
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.
The file validation only checks MIME type from the client, which can be easily spoofed. Consider adding server-side validation by checking file magic numbers (file signature) to ensure the uploaded file is actually an image.
For robust validation, use a library that checks the actual file content, not just the extension or MIME type.
| } | ||
|
|
||
| const fileExtension = path.extname(file.filename); | ||
| const uniqueName = `avatar-${username}-${Date.now()}${fileExtension}`; |
Copilot
AI
Jan 20, 2026
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.
The avatar filename includes the username, which could expose user information through the file system. Additionally, using Date.now() alone for uniqueness can lead to collisions with concurrent uploads.
Consider using a cryptographically secure random identifier (like UUID) instead of username+timestamp for better security and uniqueness.
| const friendProfile = | ||
| friendship.receiver.authId === currentUserId ? friendship.requester : friendship.receiver; | ||
| const friendProfile = f.receiver.authId === currentUserId ? f.requester : f.receiver; | ||
| const nickname = f.receiver.authId == currentUserId ? f.nicknameRequester : f.nicknameReceiver; |
Copilot
AI
Jan 20, 2026
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.
Comparison using loose equality (==) instead of strict equality (===). This can lead to unexpected type coercion behavior. Use === for type-safe comparisons.
| const response = await fetch('/api/redis') | ||
| const data = await response.json() | ||
| const response = await fetch('/api/redis'); | ||
| const data = await response.json(); |
Copilot
AI
Jan 20, 2026
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.
Unused variable data.
| const response = await fetch('/api/health') | ||
| const data = await response.json() | ||
| const response = await fetch('/api/health'); | ||
| const data = await response.json(); |
Copilot
AI
Jan 20, 2026
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.
Unused variable data.
| const response = await fetch('/api/game/health') | ||
| const data = await response.json() | ||
| const response = await fetch('/api/game/health'); | ||
| const data = await response.json(); |
Copilot
AI
Jan 20, 2026
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.
Unused variable data.
| const response = await fetch('/api/block/health') | ||
| const data = await response.json() | ||
| const response = await fetch('/api/block/health'); | ||
| const data = await response.json(); |
Copilot
AI
Jan 20, 2026
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.
Unused variable data.
| @@ -1,4 +1,4 @@ | |||
| import { Scores, GameState, ServerMessage, ClientMessage, Vector2D } from '../core/types.js'; | |||
| import { Scores, GameState, ServerMessage, ClientMessage, Vector2D } from '../types/types.js'; | |||
Copilot
AI
Jan 20, 2026
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.
Unused import Vector2D.
Main changes
React Profile page
Done
cf #21
cf #34 and #39
new dependencies for React
Temporary
Out of scope
How to test
localhost:5173/profile/Toto) => should display 404 if db is emptyOthers
Gateway
@fastify/reply-fromto simply proxy routes for users : useful and quick for multipart body. Can be adapted to other routes if we do GATE Improve with type safety and reorganize into smaller files #36Nginx server config
SameSite: 'strict'in production andlaxin developmentAuth service
logger.config.tsto skip health check logs and serialize customServiceErrortypes. A bit out of scope, but I had to debug register and login calls