diff --git a/DevSpaceOApi.json b/DevSpaceOApi.json index d8856a9..251138e 100644 --- a/DevSpaceOApi.json +++ b/DevSpaceOApi.json @@ -76,6 +76,27 @@ } } }, + "Notification": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Notification ID" + }, + "message": { + "type": "string", + "description": "Notification message" + }, + "timeStamp": { + "type": "string", + "description": "Notification creation date" + }, + "seen": { + "type": "boolean", + "description": "Notification seen status" + } + } + }, "User": { "type": "object", "properties": { @@ -128,6 +149,24 @@ } } ] + }, + "UserWithRelationsAndNotifications": { + "allOf": [ + { + "$ref": "#/components/schemas/UserWithRelations" + }, + { + "type": "object", + "properties": { + "notifications": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Notification" + } + } + } + } + ] } } }, @@ -745,7 +784,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UserWithRelations" + "$ref": "#/components/schemas/UserWithRelationsAndNotifications" } } } @@ -837,4 +876,4 @@ } }, "tags": [] -} +} \ No newline at end of file diff --git a/client/openapitools.json b/client/openapitools.json new file mode 100644 index 0000000..9841a49 --- /dev/null +++ b/client/openapitools.json @@ -0,0 +1,7 @@ +{ + "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json", + "spaces": 2, + "generator-cli": { + "version": "7.3.0" + } +} diff --git a/client/src/api/.openapi-generator/VERSION b/client/src/api/.openapi-generator/VERSION index 4b49d9b..8b23b8d 100644 --- a/client/src/api/.openapi-generator/VERSION +++ b/client/src/api/.openapi-generator/VERSION @@ -1 +1 @@ -7.2.0 \ No newline at end of file +7.3.0 \ No newline at end of file diff --git a/client/src/api/api.ts b/client/src/api/api.ts index f1435d0..4c5df5b 100644 --- a/client/src/api/api.ts +++ b/client/src/api/api.ts @@ -186,6 +186,37 @@ export interface CreatePostRequest { */ 'content'?: string; } +/** + * + * @export + * @interface Notification + */ +export interface Notification { + /** + * Notification ID + * @type {number} + * @memberof Notification + */ + 'id'?: number; + /** + * Notification message + * @type {string} + * @memberof Notification + */ + 'message'?: string; + /** + * Notification creation date + * @type {string} + * @memberof Notification + */ + 'timeStamp'?: string; + /** + * Notification seen status + * @type {boolean} + * @memberof Notification + */ + 'seen'?: boolean; +} /** * * @export @@ -309,6 +340,61 @@ export interface UserWithRelations { */ 'followers'?: Array; } +/** + * + * @export + * @interface UserWithRelationsAndNotifications + */ +export interface UserWithRelationsAndNotifications { + /** + * User ID + * @type {number} + * @memberof UserWithRelationsAndNotifications + */ + 'id'?: number; + /** + * User first name + * @type {string} + * @memberof UserWithRelationsAndNotifications + */ + 'firstName'?: string; + /** + * User last name + * @type {string} + * @memberof UserWithRelationsAndNotifications + */ + 'lastName'?: string; + /** + * + * @type {Array} + * @memberof UserWithRelationsAndNotifications + */ + 'posts'?: Array; + /** + * + * @type {Array} + * @memberof UserWithRelationsAndNotifications + */ + 'comments'?: Array; + /** + * + * @type {Array} + * @memberof UserWithRelationsAndNotifications + */ + 'followed'?: Array; + /** + * + * @type {Array} + * @memberof UserWithRelationsAndNotifications + */ + 'followers'?: Array; + /** + * + * @type {Array} + * @memberof UserWithRelationsAndNotifications + */ + 'notifications'?: Array; +} /** * AuthenticationApi - axios parameter creator @@ -441,9 +527,9 @@ export const AuthenticationApiFp = function(configuration?: Configuration) { */ async authLoginPost(authLoginPostRequest: AuthLoginPostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.authLoginPost(authLoginPostRequest, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['AuthenticationApi.authLoginPost']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['AuthenticationApi.authLoginPost']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -453,9 +539,9 @@ export const AuthenticationApiFp = function(configuration?: Configuration) { */ async authLogoutGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.authLogoutGet(options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['AuthenticationApi.authLogoutGet']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['AuthenticationApi.authLogoutGet']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -466,9 +552,9 @@ export const AuthenticationApiFp = function(configuration?: Configuration) { */ async authSignupPost(authSignupPostRequest: AuthSignupPostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.authSignupPost(authSignupPostRequest, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['AuthenticationApi.authSignupPost']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['AuthenticationApi.authSignupPost']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, } }; @@ -931,9 +1017,9 @@ export const PostsApiFp = function(configuration?: Configuration) { */ async commentPost(id: number, commentPostRequest: CommentPostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.commentPost(id, commentPostRequest, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['PostsApi.commentPost']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['PostsApi.commentPost']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -944,9 +1030,9 @@ export const PostsApiFp = function(configuration?: Configuration) { */ async createPost(createPostRequest: CreatePostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.createPost(createPostRequest, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['PostsApi.createPost']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['PostsApi.createPost']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -957,9 +1043,9 @@ export const PostsApiFp = function(configuration?: Configuration) { */ async deletePost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.deletePost(id, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['PostsApi.deletePost']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['PostsApi.deletePost']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -969,9 +1055,9 @@ export const PostsApiFp = function(configuration?: Configuration) { */ async getAllPosts(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { const localVarAxiosArgs = await localVarAxiosParamCreator.getAllPosts(options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['PostsApi.getAllPosts']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['PostsApi.getAllPosts']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -981,9 +1067,9 @@ export const PostsApiFp = function(configuration?: Configuration) { */ async getFollowedPosts(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { const localVarAxiosArgs = await localVarAxiosParamCreator.getFollowedPosts(options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['PostsApi.getFollowedPosts']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['PostsApi.getFollowedPosts']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -994,9 +1080,9 @@ export const PostsApiFp = function(configuration?: Configuration) { */ async getPost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.getPost(id, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['PostsApi.getPost']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['PostsApi.getPost']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -1007,9 +1093,9 @@ export const PostsApiFp = function(configuration?: Configuration) { */ async likePost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.likePost(id, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['PostsApi.likePost']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['PostsApi.likePost']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -1020,9 +1106,9 @@ export const PostsApiFp = function(configuration?: Configuration) { */ async unlikePost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.unlikePost(id, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['PostsApi.unlikePost']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['PostsApi.unlikePost']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -1034,9 +1120,9 @@ export const PostsApiFp = function(configuration?: Configuration) { */ async updatePost(id: number, createPostRequest: CreatePostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.updatePost(id, createPostRequest, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['PostsApi.updatePost']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['PostsApi.updatePost']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, } }; @@ -1465,9 +1551,9 @@ export const UsersApiFp = function(configuration?: Configuration) { */ async usersGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { const localVarAxiosArgs = await localVarAxiosParamCreator.usersGet(options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['UsersApi.usersGet']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['UsersApi.usersGet']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -1478,9 +1564,9 @@ export const UsersApiFp = function(configuration?: Configuration) { */ async usersIdFollowDelete(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.usersIdFollowDelete(id, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['UsersApi.usersIdFollowDelete']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['UsersApi.usersIdFollowDelete']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -1491,9 +1577,9 @@ export const UsersApiFp = function(configuration?: Configuration) { */ async usersIdFollowPost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.usersIdFollowPost(id, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['UsersApi.usersIdFollowPost']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['UsersApi.usersIdFollowPost']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -1504,9 +1590,9 @@ export const UsersApiFp = function(configuration?: Configuration) { */ async usersIdGet(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.usersIdGet(id, options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['UsersApi.usersIdGet']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['UsersApi.usersIdGet']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * @@ -1514,11 +1600,11 @@ export const UsersApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async usersMeGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async usersMeGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.usersMeGet(options); - const index = configuration?.serverIndex ?? 0; - const operationBasePath = operationServerMap['UsersApi.usersMeGet']?.[index]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['UsersApi.usersMeGet']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, } }; @@ -1575,7 +1661,7 @@ export const UsersApiFactory = function (configuration?: Configuration, basePath * @param {*} [options] Override http request option. * @throws {RequiredError} */ - usersMeGet(options?: any): AxiosPromise { + usersMeGet(options?: any): AxiosPromise { return localVarFp.usersMeGet(options).then((request) => request(axios, basePath)); }, }; diff --git a/server/src/controller/UserController.ts b/server/src/controller/UserController.ts index bf1d2dc..0445823 100644 --- a/server/src/controller/UserController.ts +++ b/server/src/controller/UserController.ts @@ -7,10 +7,9 @@ import {Notification} from "../entity/Notification"; import {catchAsync} from "../util/catchAsync"; export class UserController { + private userRepository = AppDataSource.getRepository(User); - private userRepository = AppDataSource.getRepository(User) - - private notificationRepository = AppDataSource.getRepository(Notification) + private notificationRepository = AppDataSource.getRepository(Notification); /** * @swagger * /users: @@ -34,13 +33,14 @@ export class UserController { async (req: Request, res: Response, next: NextFunction) => { const users = await this.userRepository.find(); - // remove sensitive fields - users.forEach(user => { - user.deleteSensitiveFields() - }) + // remove sensitive fields + users.forEach((user) => { + user.deleteSensitiveFields(); + }); - res.status(200).send(users) - }) + res.status(200).send(users); + } + ); /** * @swagger @@ -73,23 +73,28 @@ export class UserController { // Check if ID is a number if (isNaN(parsedId)) return next(new AppError("Invalid ID", 400)); - const user = await this.userRepository.findOne({where: {id: parsedId}, relations:{ - followed: true, - followers: true, - posts: true, - comments: true, - }}) + const user = await this.userRepository.findOne({ + where: { id: parsedId }, + relations: { + followed: true, + followers: true, + posts: true, + comments: true, + }, + }); + if (!user) return next(new AppError("No user found with that ID", 404)); - if(!user) return next(new AppError('No user found with that ID', 404)) + // remove sensitive fields + user.deleteSensitiveFields(); + user.followed.forEach((followedUser) => + followedUser.deleteSensitiveFields() + ); + user.followers.forEach((follower) => follower.deleteSensitiveFields()); - // remove sensitive fields - user.deleteSensitiveFields() - user.followed.forEach(followedUser => followedUser.deleteSensitiveFields()) - user.followers.forEach(follower => follower.deleteSensitiveFields()) - - return res.send(user) - }) + return res.send(user); + } + ); /** * @swagger @@ -106,7 +111,7 @@ export class UserController { * content: * application/json: * schema: - * $ref: '#/components/schemas/UserWithRelations' + * $ref: '#/components/schemas/UserWithRelationsAndNotifications' */ public getMe = catchAsync( async (req: AppRequest, res: Response, next: NextFunction) => { @@ -117,14 +122,18 @@ export class UserController { followers: true, posts: true, comments: true, + notifications: true, }, }); - user.followed.forEach(followedUser => followedUser.deleteSensitiveFields()) - user.followers.forEach(follower => follower.deleteSensitiveFields()) + user.followed.forEach((followedUser) => + followedUser.deleteSensitiveFields() + ); + user.followers.forEach((follower) => follower.deleteSensitiveFields()); - return res.status(200).send(user) - }) + return res.status(200).send(user); + } + ); /** * @swagger @@ -161,69 +170,74 @@ export class UserController { // Check if ID is a number if (isNaN(parsedId)) return next(new AppError("Invalid ID", 400)); - const user = req.user - const userToFollow = await this.userRepository.findOne({ - where: {id: parsedId}, - relations:{followed: true, followers: true, notifications: true}} + const user = req.user; + const userToFollow = await this.userRepository.findOne({ + where: { id: parsedId }, + relations: { followed: true, followers: true, notifications: true }, + }); + + if (!userToFollow) + return next(new AppError("No user found with that ID", 404)); + + // Check if user is already following + if ( + user.followed.some( + (followedUser) => followedUser.id === userToFollow.id ) + ) { + return next(new AppError("You are already following this user", 400)); + } + // Follow the user + user.followed.push(userToFollow); + await this.userRepository.save(user); + // Add the requesting user to the followers of the user being followed + userToFollow.followers.push(user); + // Create a notification for the user being followed + const followNotification = Object.assign(new Notification(), { + seen: false, + message: `${user.firstName} is now following you`, + timeStamp: new Date(), + }); + userToFollow.notifications.push( + await this.notificationRepository.save(followNotification) + ); + await this.userRepository.save(userToFollow); - if(!userToFollow) return next(new AppError('No user found with that ID', 404)) + return res.status(200).send({ + status: "success", + message: `You are now following ${userToFollow.firstName}`, + }); + } + ); - // Check if user is already following - if(user.followed.some(followedUser => followedUser.id === userToFollow.id)){ - return next(new AppError('You are already following this user', 400)) - } - // Follow the user - user.followed.push(userToFollow) - await this.userRepository.save(user) - // Add the requesting user to the followers of the user being followed - userToFollow.followers.push(user) - // Create a notification for the user being followed - const followNotification = Object.assign(new Notification(),{ - seen: false, - message: `${user.firstName} is now following you`, - timeStamp: new Date() - }) - userToFollow.notifications.push( - await this.notificationRepository.save(followNotification) - ) - await this.userRepository.save(userToFollow) - - - return res.status(200).send({ - status: 'success', - message: `You are now following ${userToFollow.firstName}` - }) - }) - - /** - * @swagger - * /users/{id}/follow: - * delete: - * security: - * - bearerAuth: [] - * tags: - * - Users - * summary: Unfollow a user - * parameters: - * - in: path - * name: id - * required: true - * schema: - * type: integer - * description: The ID of the user to unfollow - * responses: - * 200: - * description: Successfully unfollowed the user - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/UserWithRelations' - * 400: - * description: Invalid ID - * 404: - * description: No user found with that ID - */ + /** + * @swagger + * /users/{id}/follow: + * delete: + * security: + * - bearerAuth: [] + * tags: + * - Users + * summary: Unfollow a user + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: The ID of the user to unfollow + * responses: + * 200: + * description: Successfully unfollowed the user + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/UserWithRelations' + * 400: + * description: Invalid ID + * 404: + * description: No user found with that ID + */ public unfollowUser = catchAsync( async (req: AppRequest, res: Response, next: NextFunction) => { const userToUnfollowId = req.params.id; @@ -231,28 +245,37 @@ export class UserController { // Check if ID is a number if (isNaN(parsedId)) return next(new AppError("Invalid ID", 400)); - const user = req.user - const userToUnfollow = await this.userRepository.findOne({ - where: {id: parsedId}, - relations: {followed: true, followers: true} - }) + const user = req.user; + const userToUnfollow = await this.userRepository.findOne({ + where: { id: parsedId }, + relations: { followed: true, followers: true }, + }); - if(!userToUnfollow) return next(new AppError('No user found with that ID', 404)) - // Check if user is following - if(!user.followed.some(followedUser => followedUser.id === userToUnfollow.id)){ - return next(new AppError('You are not following this user', 400)) - } - // Unfollow the user - user.followed = user.followed.filter(followedUser => followedUser.id !== userToUnfollow.id) - await this.userRepository.save(user) + if (!userToUnfollow) + return next(new AppError("No user found with that ID", 404)); + // Check if user is following + if ( + !user.followed.some( + (followedUser) => followedUser.id === userToUnfollow.id + ) + ) { + return next(new AppError("You are not following this user", 400)); + } + // Unfollow the user + user.followed = user.followed.filter( + (followedUser) => followedUser.id !== userToUnfollow.id + ); + await this.userRepository.save(user); - userToUnfollow.followers = userToUnfollow.followers.filter(follower => follower.id !== user.id) - await this.userRepository.save(userToUnfollow) - - return res.status(200).send({ - status: 'success', - message: `You are no longer following ${userToUnfollow.firstName}` - }) - }) + userToUnfollow.followers = userToUnfollow.followers.filter( + (follower) => follower.id !== user.id + ); + await this.userRepository.save(userToUnfollow); + return res.status(200).send({ + status: "success", + message: `You are no longer following ${userToUnfollow.firstName}`, + }); + } + ); } \ No newline at end of file diff --git a/server/src/controller/postController.ts b/server/src/controller/postController.ts index d00de4a..421bc06 100644 --- a/server/src/controller/postController.ts +++ b/server/src/controller/postController.ts @@ -117,8 +117,12 @@ export class PostController { public getFollowedPosts = catchAsync(async (req : AppRequest, res, _next) => { const user = await this.userRepository.findOne({ - where: {id: req.user.id}, - relations: {followed: true, posts: true}}) + where: { id: req.user.id }, + relations: { + followed: true, + posts: { likedBy: true, comments: true }, + }, + }); const followedPosts = user.followed.map(followedUser => followedUser.posts).flat() diff --git a/server/src/routes/swaggerRoutes.ts b/server/src/routes/swaggerRoutes.ts index 65aa979..152055e 100644 --- a/server/src/routes/swaggerRoutes.ts +++ b/server/src/routes/swaggerRoutes.ts @@ -83,6 +83,27 @@ const swaggerOptions = { }, }, }, + Notification: { + type: "object", + properties: { + id: { + type: "integer", + description: "Notification ID", + }, + message: { + type: "string", + description: "Notification message", + }, + timeStamp: { + type: "string", + description: "Notification creation date", + }, + seen: { + type: "boolean", + description: "Notification seen status", + }, + }, + }, User: { type: "object", properties: { @@ -136,10 +157,25 @@ const swaggerOptions = { }, ], }, + UserWithRelationsAndNotifications: { + allOf: [ + { $ref: "#/components/schemas/UserWithRelations" }, + { + type: "object", + properties: { + notifications: { + type: "array", + items: { + $ref: "#/components/schemas/Notification", + }, + }, + }, + }, + ], + }, }, }, }, - apis: ["**/controller/*.ts"], };