mirror of
https://github.com/hknsh/project-knedita.git
synced 2024-11-28 17:41:15 +00:00
Created like-post and follow-user routes, changed file names
This commit is contained in:
parent
b6be9d6755
commit
11d74d846b
33 changed files with 280 additions and 41 deletions
|
@ -19,8 +19,8 @@ An open-source social media.
|
|||
- Able to choose a profile picture✅
|
||||
- Probably gonna use LocalStack to mock Amazon S3✅
|
||||
- Image compression ✅
|
||||
- Following/unfollowing features
|
||||
- Like posts
|
||||
- Following/unfollowing features ✅
|
||||
- Like posts ✅
|
||||
- Probably pinned posts
|
||||
- Authentication ✅
|
||||
- Add more verification (like, if the password is too short) ✅
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "Like" (
|
||||
"id" TEXT NOT NULL,
|
||||
"postId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "Like_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Like" ADD CONSTRAINT "Like_postId_fkey" FOREIGN KEY ("postId") REFERENCES "Post"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Like" ADD CONSTRAINT "Like_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -0,0 +1,22 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "Follower" (
|
||||
"id" TEXT NOT NULL,
|
||||
"followerId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "Follower_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Following" (
|
||||
"id" TEXT NOT NULL,
|
||||
"followingId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "Following_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Follower" ADD CONSTRAINT "Follower_followerId_fkey" FOREIGN KEY ("followerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Following" ADD CONSTRAINT "Following_followingId_fkey" FOREIGN KEY ("followingId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the `Follower` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `Following` table. If the table is not empty, all the data it contains will be lost.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "Follower" DROP CONSTRAINT "Follower_followerId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "Following" DROP CONSTRAINT "Following_followingId_fkey";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "Follower";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "Following";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Follows" (
|
||||
"followerId" TEXT NOT NULL,
|
||||
"followingId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "Follows_pkey" PRIMARY KEY ("followerId","followingId")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Follows" ADD CONSTRAINT "Follows_followerId_fkey" FOREIGN KEY ("followerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Follows" ADD CONSTRAINT "Follows_followingId_fkey" FOREIGN KEY ("followingId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -1,6 +1,3 @@
|
|||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
@ -18,6 +15,9 @@ model User {
|
|||
password String
|
||||
posts Post[]
|
||||
profileImage String?
|
||||
likedPosts Like[]
|
||||
followers Follows[] @relation("following")
|
||||
following Follows[] @relation("follower")
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,24 @@ model Post {
|
|||
content String
|
||||
authorId String
|
||||
author User @relation(fields: [authorId], references: [id])
|
||||
likes Like[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
}
|
||||
|
||||
model Like {
|
||||
id String @id @default(uuid())
|
||||
postId String
|
||||
post Post @relation(fields: [postId], references: [id])
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
model Follows {
|
||||
follower User @relation("follower", fields: [followerId], references: [id])
|
||||
followerId String
|
||||
following User @relation("following", fields: [followingId], references: [id])
|
||||
followingId String
|
||||
|
||||
@@id([followerId, followingId])
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
import { Router } from 'express'
|
||||
|
||||
// Controllers
|
||||
import postCreateController from './posts/post-create'
|
||||
import postDeleteController from './posts/post-delete'
|
||||
import postInfoController from './posts/post-info'
|
||||
import postUpdateController from './posts/post-update'
|
||||
import postCreateController from './posts/create'
|
||||
import postDeleteController from './posts/delete'
|
||||
import postInfoController from './posts/get-info'
|
||||
import postUpdateController from './posts/update'
|
||||
|
||||
// Middlewares
|
||||
import ensureAuthenticated from '../middlewares/ensure-authenticated'
|
||||
|
|
|
@ -3,12 +3,14 @@
|
|||
import { Router } from 'express'
|
||||
|
||||
// Controllers
|
||||
import userAuthController from './users/user-auth'
|
||||
import userDeleteController from './users/user-delete'
|
||||
import userInfoController from './users/user-info'
|
||||
import userSignupController from './users/user-signup'
|
||||
import userUpdateController from './users/user-update'
|
||||
import userUploadPictureController from './users/user-upload-picture'
|
||||
import userAuthController from './users/auth'
|
||||
import userDeleteController from './users/delete'
|
||||
import userFollowController from './users/follow-user'
|
||||
import userInfoController from './users/get-info'
|
||||
import userLikePostController from './users/like-post'
|
||||
import userSignupController from './users/signup'
|
||||
import userUpdateController from './users/update'
|
||||
import userUploadPictureController from './users/upload-picture'
|
||||
|
||||
// Middlewares
|
||||
import ensureAuthenticated from '../middlewares/ensure-authenticated'
|
||||
|
@ -23,5 +25,7 @@ usersRouter.get('/info', userInfoController)
|
|||
usersRouter.post('/signup', userSignupController)
|
||||
usersRouter.put('/update', ensureAuthenticated, userUpdateController)
|
||||
usersRouter.put('/profile-picture/upload', ensureAuthenticated, uploadFile, userUploadPictureController)
|
||||
usersRouter.post('/like-post', ensureAuthenticated, userLikePostController)
|
||||
usersRouter.post('/follow-user', ensureAuthenticated, userFollowController)
|
||||
|
||||
export default usersRouter
|
||||
|
|
18
src/controllers/users/follow-user.ts
Normal file
18
src/controllers/users/follow-user.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { user } from '../../services'
|
||||
import type { Request, Response } from 'express'
|
||||
import { badRequest } from '../../lib/http-errors'
|
||||
|
||||
async function userFollowController (req: Request, res: Response): Promise<void> {
|
||||
const userId = req.user?.id ?? ''
|
||||
const { userToFollow } = req.body
|
||||
|
||||
const result = await user.follow(userId, userToFollow)
|
||||
|
||||
if (result instanceof Error) {
|
||||
return badRequest(res, result.message)
|
||||
}
|
||||
|
||||
res.json(result)
|
||||
}
|
||||
|
||||
export default userFollowController
|
18
src/controllers/users/like-post.ts
Normal file
18
src/controllers/users/like-post.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { user } from '../../services'
|
||||
import type { Request, Response } from 'express'
|
||||
import { badRequest } from '../../lib/http-errors'
|
||||
|
||||
async function userLikePostController (req: Request, res: Response): Promise<void> {
|
||||
const userId = req.user?.id ?? ''
|
||||
const { postId } = req.body
|
||||
|
||||
const result = await user.likePost(postId, userId)
|
||||
|
||||
if (result instanceof Error) {
|
||||
return badRequest(res, result.message)
|
||||
}
|
||||
|
||||
res.json(result)
|
||||
}
|
||||
|
||||
export default userLikePostController
|
|
@ -1,14 +1,16 @@
|
|||
import userAuthService from './users/user-auth'
|
||||
import userDeleteService from './users/user-delete'
|
||||
import userInfoService from './users/user-info'
|
||||
import userSignupService from './users/user-signup'
|
||||
import userUpdateService from './users/user-update'
|
||||
import userUploadPictureService from './users/user-upload-picture'
|
||||
import userAuthService from './users/auth'
|
||||
import userDeleteService from './users/delete'
|
||||
import userFollowService from './users/follow-user'
|
||||
import userInfoService from './users/get-info'
|
||||
import userLikePostService from './users/like-post'
|
||||
import userSignupService from './users/signup'
|
||||
import userUpdateService from './users/update'
|
||||
import userUploadPictureService from './users/upload-picture'
|
||||
|
||||
import postCreateService from './posts/post-create'
|
||||
import postDeleteService from './posts/post-delete'
|
||||
import postInfoService from './posts/post-info'
|
||||
import postUpdateService from './posts/post-update'
|
||||
import postCreateService from './posts/create'
|
||||
import postDeleteService from './posts/delete'
|
||||
import postInfoService from './posts/get-info'
|
||||
import postUpdateService from './posts/update'
|
||||
|
||||
// User services
|
||||
const user = {
|
||||
|
@ -17,7 +19,9 @@ const user = {
|
|||
info: userInfoService,
|
||||
signup: userSignupService,
|
||||
update: userUpdateService,
|
||||
uploadPicture: userUploadPictureService
|
||||
uploadPicture: userUploadPictureService,
|
||||
likePost: userLikePostService,
|
||||
follow: userFollowService
|
||||
}
|
||||
|
||||
// Post services
|
||||
|
|
|
@ -15,7 +15,8 @@ async function postInfoService (id: string): Promise<Object | Error> {
|
|||
displayName: true,
|
||||
username: true
|
||||
}
|
||||
}
|
||||
},
|
||||
likes: true
|
||||
}
|
||||
})
|
||||
|
0
src/services/posts/get-likes.ts
Normal file
0
src/services/posts/get-likes.ts
Normal file
|
@ -10,7 +10,7 @@ async function userAuthService (email: string, password: string): Promise<Object
|
|||
})
|
||||
|
||||
if (user == null) {
|
||||
return new Error('User does not exists')
|
||||
return new Error('Invalid email or password')
|
||||
}
|
||||
|
||||
if (email === undefined || password === undefined) {
|
55
src/services/users/follow-user.ts
Normal file
55
src/services/users/follow-user.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
import prisma from '../../clients/prisma-client'
|
||||
|
||||
async function userFollowService (userId: string, followingUsername: string): Promise<Object | Error> {
|
||||
if (userId === undefined || followingUsername === undefined) {
|
||||
return new Error('Missing fields')
|
||||
}
|
||||
|
||||
const user = await prisma.user.findFirst({
|
||||
where: {
|
||||
username: followingUsername
|
||||
}
|
||||
})
|
||||
|
||||
if (user === null) {
|
||||
return new Error('User not found')
|
||||
}
|
||||
|
||||
const userToFollow = await prisma.user.findFirst({
|
||||
where: {
|
||||
id: userId
|
||||
}
|
||||
})
|
||||
|
||||
if (userToFollow === null) {
|
||||
return new Error('User to follow not found')
|
||||
}
|
||||
|
||||
const alreadyFollow = await prisma.follows.findFirst({
|
||||
where: {
|
||||
followerId: user.id,
|
||||
followingId: userToFollow.id
|
||||
}
|
||||
})
|
||||
|
||||
if (alreadyFollow !== null) {
|
||||
await prisma.follows.deleteMany({
|
||||
where: {
|
||||
followerId: user.id,
|
||||
followingId: userToFollow.id
|
||||
}
|
||||
})
|
||||
return {}
|
||||
}
|
||||
|
||||
const follow = await prisma.follows.create({
|
||||
data: {
|
||||
followerId: user.id,
|
||||
followingId: userToFollow.id
|
||||
}
|
||||
})
|
||||
|
||||
return follow
|
||||
}
|
||||
|
||||
export default userFollowService
|
|
@ -17,6 +17,11 @@ async function userInfoService (username: string): Promise<Object> {
|
|||
createdAt: true,
|
||||
updatedAt: true
|
||||
}
|
||||
},
|
||||
likedPosts: {
|
||||
select: {
|
||||
postId: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
55
src/services/users/like-post.ts
Normal file
55
src/services/users/like-post.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
import prisma from '../../clients/prisma-client'
|
||||
|
||||
async function userLikePostService (postId: string, userId: string): Promise<Object | Error> {
|
||||
if (postId === undefined || userId === undefined) {
|
||||
return new Error('Missing fields')
|
||||
}
|
||||
|
||||
const post = await prisma.post.findFirst({
|
||||
where: {
|
||||
id: postId
|
||||
}
|
||||
})
|
||||
|
||||
if (post === null) {
|
||||
return new Error('Post not found')
|
||||
}
|
||||
|
||||
const user = await prisma.user.findFirst({
|
||||
where: {
|
||||
id: userId
|
||||
}
|
||||
})
|
||||
|
||||
if (user === null) {
|
||||
return new Error('User not found')
|
||||
}
|
||||
|
||||
const alreadyLiked = await prisma.like.findFirst({
|
||||
where: {
|
||||
postId: post.id,
|
||||
userId: user.id
|
||||
}
|
||||
})
|
||||
|
||||
if (alreadyLiked !== null) {
|
||||
await prisma.like.deleteMany({
|
||||
where: {
|
||||
postId: post.id,
|
||||
userId: user.id
|
||||
}
|
||||
})
|
||||
return {}
|
||||
}
|
||||
|
||||
const like = await prisma.like.create({
|
||||
data: {
|
||||
postId: post.id,
|
||||
userId: user.id
|
||||
}
|
||||
})
|
||||
|
||||
return like
|
||||
}
|
||||
|
||||
export default userLikePostService
|
|
@ -8,6 +8,9 @@ async function userUpdateService ({ id, email, displayName, username }: userPayl
|
|||
return new Error('User not found')
|
||||
}
|
||||
|
||||
// Check if the provided email or username is different from the current user's data
|
||||
// if they are different, additional queries are made to check if the new email or username is already in use.
|
||||
|
||||
if (email !== undefined && email.trim() !== user.email) {
|
||||
const existingUser = await prisma.user.findFirst({ where: { email } })
|
||||
if ((existingUser != null) && existingUser.email !== user.email) {
|
|
@ -15,18 +15,7 @@ async function userUploadPictureService (authorId: string, url: string): Promise
|
|||
profileImage: url
|
||||
},
|
||||
select: {
|
||||
profileImage: true,
|
||||
displayName: true,
|
||||
username: true,
|
||||
createdAt: true,
|
||||
posts: {
|
||||
select: {
|
||||
id: true,
|
||||
content: true,
|
||||
createdAt: true,
|
||||
updatedAt: true
|
||||
}
|
||||
}
|
||||
profileImage: true
|
||||
}
|
||||
})
|
||||
|
Loading…
Reference in a new issue