From e8a3c9caedf5c70bd764b91fb7ec26f7be29dbaf Mon Sep 17 00:00:00 2001 From: Jonas Simoen Date: Mon, 20 May 2024 16:54:42 +0200 Subject: [PATCH 1/4] feat(news): article management --- src/controllers/News.ts | 37 +++++++++++++++++++++++++++++++++++ src/routers/Main.ts | 6 ++++-- src/routers/News.ts | 42 +++++++++++++++++++++++++++++----------- src/routers/Page.ts | 2 ++ src/types/body-schema.ts | 23 ++++++++++++++++++++++ 5 files changed, 97 insertions(+), 13 deletions(-) diff --git a/src/controllers/News.ts b/src/controllers/News.ts index 2972434..1c8a733 100644 --- a/src/controllers/News.ts +++ b/src/controllers/News.ts @@ -32,6 +32,7 @@ export const GetArticlesHandler = async (req: any, rep: any) => { count: articleCount, }) } + export const GetArticleHandler = async (req: any, rep: any) => { const articles = await prisma.article.findFirst({ select: { @@ -54,4 +55,40 @@ export const GetArticleHandler = async (req: any, rep: any) => { } }); rep.send(articles) +} + +export const PutArticleHandler = async (req: any, rep: any) => { + const articles = await prisma.article.update({ + where: { + id: +req.params.id + }, + data: { + slug: req.body.slug, + title: req.body.title, + description: req.body.description, + imageUrl: req.body.imageUrl, + readMore: req.body.readMore, + timestampUpdated: new Date(), + } + }); + rep.send(articles) +} + +export const PostArticleHandler = async (req: any, rep: any) => { + const articles = await prisma.article.create({ + data: { + slug: req.body.slug, + title: req.body.title, + description: req.body.description, + imageUrl: req.body.imageUrl, + readMore: req.body.readMore, + timestampCreated: new Date(), + author: { + connect: { + id: +req.user.id || 0 + } + }, + } + }); + rep.send(articles) } \ No newline at end of file diff --git a/src/routers/Main.ts b/src/routers/Main.ts index 7e35b59..6395f7f 100644 --- a/src/routers/Main.ts +++ b/src/routers/Main.ts @@ -8,10 +8,10 @@ import { AdminMatchRouter, PublicMatchRouter } from './Match'; import { AdminMatchEventRouter, PublicMatchEventRouter } from './MatchEvent'; import { AdminMatchStatisticRouter, PublicMatchStatisticRouter, PublicPlayerStatisticRouter } from './Statistic'; import { AdminWeekRouter, PublicWeekRouter } from './Week'; -import { PublicPageRouter } from './Page'; +import { AdminPageRouter, PublicPageRouter } from './Page'; import { AdminGeneralRouter } from './Admin'; import { NotificationRouter } from './Notification'; -import { PublicNewsRouter } from './News'; +import { AdminNewsRouter, PublicNewsRouter } from './News'; export const PublicRouter: FastifyPluginAsync = async server => { server.register(NotificationRouter, { prefix: '/notifications' }) @@ -37,4 +37,6 @@ export const AdminRouter: FastifyPluginAsync = async server => { server.register(AdminMatchEventRouter, { prefix: '/matches/:matchId/events' }) server.register(AdminMatchStatisticRouter, { prefix: '/matches/:matchId/stats' }) server.register(AdminWeekRouter, { prefix: '/weeks' }) + server.register(AdminPageRouter, { prefix: '/pages' }) + server.register(AdminNewsRouter, {prefix: '/news'}) } \ No newline at end of file diff --git a/src/routers/News.ts b/src/routers/News.ts index 872d622..fecdbfa 100644 --- a/src/routers/News.ts +++ b/src/routers/News.ts @@ -1,21 +1,41 @@ import { FastifyPluginAsync } from "fastify"; -import { GetArticleHandler, GetArticlesHandler } from "../controllers/News"; +import { GetArticleHandler, GetArticlesHandler, PostArticleHandler, PutArticleHandler } from "../controllers/News"; +import { PostArticleSchema, PutArticleSchema } from "../types/body-schema"; export const PublicNewsRouter: FastifyPluginAsync = async server => { server.route({ - method: 'GET', - url: '', - handler: GetArticlesHandler, - schema: { - querystring: { - page: { type: 'number' } - } + method: 'GET', + url: '', + handler: GetArticlesHandler, + schema: { + querystring: { + page: { type: 'number' } } + } }); server.route({ - method: 'GET', - url: '/:slug', - handler: GetArticleHandler + method: 'GET', + url: '/:slug', + handler: GetArticleHandler + }); +} + +export const AdminNewsRouter: FastifyPluginAsync = async server => { + server.route({ + method: 'POST', + url: '', + handler: PostArticleHandler, + schema: { + body: PostArticleSchema, + } + }); + server.route({ + method: 'PUT', + url: '/:id', + handler: PutArticleHandler, + schema: { + body: PutArticleSchema, + } }); } \ No newline at end of file diff --git a/src/routers/Page.ts b/src/routers/Page.ts index a584d04..63945a8 100644 --- a/src/routers/Page.ts +++ b/src/routers/Page.ts @@ -14,7 +14,9 @@ export const PublicPageRouter: FastifyPluginAsync = async server => { } } }); +} +export const AdminPageRouter: FastifyPluginAsync = async server => { server.route({ method: 'POST', url: '', diff --git a/src/types/body-schema.ts b/src/types/body-schema.ts index f65e47c..0a80054 100644 --- a/src/types/body-schema.ts +++ b/src/types/body-schema.ts @@ -287,3 +287,26 @@ export const PutPageSchema = { }, }, }; + +export const PutArticleSchema = { + type: "object", + properties: { + id: { type: "number" }, + slug: { type: "string" }, + title: { type: "string" }, + description: { type: "string" }, + imageUrl: { type: "string" }, + readMore: { type: "boolean" }, + }, +}; + +export const PostArticleSchema = { + type: "object", + properties: { + slug: { type: "string" }, + title: { type: "string" }, + description: { type: "string" }, + imageUrl: { type: "string" }, + readMore: { type: "boolean" }, + }, +}; From bb8e7fb44041e021ac42ebd95925494290eff7d1 Mon Sep 17 00:00:00 2001 From: Jonas Simoen Date: Mon, 20 May 2024 19:49:42 +0200 Subject: [PATCH 2/4] feat(booster): add new player booster --- prisma/schema.prisma | 4 ++-- src/controllers/General.ts | 4 ++-- src/controllers/Team.ts | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 4e3c0ae..65d62a9 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -29,7 +29,7 @@ enum PlayerBoosterType { HiddenGem GoalRush TripleCaptain - ViceVictory + FanFavourit } model User { @@ -185,7 +185,7 @@ model Team { // Boosters freeHit Int? tripleCaptain Int? - viceVictory Int? + fanFavourite Int? superSubs Int? hiddenGem Int? goalRush Int? diff --git a/src/controllers/General.ts b/src/controllers/General.ts index 16260af..ddc8ebc 100644 --- a/src/controllers/General.ts +++ b/src/controllers/General.ts @@ -45,7 +45,7 @@ export const GetUserOverview = async(req: any, rep: any) => { } }, tripleCaptain: true, - viceVictory: true, + fanFavourite: true, freeHit: true, superSubs: true, hiddenGem: true, @@ -54,7 +54,7 @@ export const GetUserOverview = async(req: any, rep: any) => { where: { OR: [ {tripleCaptain: weekId}, - {viceVictory: weekId}, + {fanFavourite: weekId}, {freeHit: weekId}, {superSubs: weekId}, {hiddenGem: weekId}, diff --git a/src/controllers/Team.ts b/src/controllers/Team.ts index 3869734..df557bb 100644 --- a/src/controllers/Team.ts +++ b/src/controllers/Team.ts @@ -317,12 +317,12 @@ export const GetPointsTeamHandler = async (req: any, rep: any) => { export const PostBoosterTeamHandler = async (req: any, rep: any) => { const boosterUnCC = req.body.type.charAt(0).toUpperCase() + req.body.type.slice(1); - const validBoosters = ["tripleCaptain","viceVictory","hiddenGem","goalRush","superSubs","freeHit"]; + const validBoosters = ["tripleCaptain","fanFavourite","hiddenGem","goalRush","superSubs","freeHit"]; if(!validBoosters.includes(req.body.type)) throw new HttpError("Invalid booster", 404) - const isPlayerBooster = ["hiddenGem","goalRush"].includes(req.body.type); + const isPlayerBooster = ["hiddenGem","goalRush","fanFavourite"].includes(req.body.type); const currentWeek = await upcomingWeekId(); const teamWithBoosters: { [key: string]: any } | null = await prisma.team.findFirst({ @@ -330,7 +330,7 @@ export const PostBoosterTeamHandler = async (req: any, rep: any) => { goalRush: true, tripleCaptain: true, hiddenGem: true, - viceVictory: true, + fanFavourite: true, selections: { select: { playerId: true, From c8d62daff4e342225d52d32c3f53538d322906f1 Mon Sep 17 00:00:00 2001 From: Jonas Simoen Date: Mon, 20 May 2024 20:56:35 +0200 Subject: [PATCH 3/4] minor fixes --- prisma/schema.prisma | 102 +--------------------------------- src/controllers/MatchEvent.ts | 78 -------------------------- src/controllers/Team.ts | 2 + src/controllers/UserAuth.ts | 10 +++- src/middleware/RequireUser.ts | 5 +- src/routers/Main.ts | 3 - src/routers/MatchEvent.ts | 52 ----------------- src/types/body-schema.ts | 28 ---------- 8 files changed, 16 insertions(+), 264 deletions(-) delete mode 100644 src/controllers/MatchEvent.ts delete mode 100644 src/routers/MatchEvent.ts diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 65d62a9..cf0aa4b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -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" // previewFeatures = ["metrics"] @@ -11,20 +8,6 @@ datasource db { url = env("DATABASE_URL") } -enum MatchEventType { - Goal - Assist - SubstituteIn - SubstituteOut - PenaltyScored - PenaltyMissed - PenaltySaved - YellowCard - SecondYellowCard - RedCard - Starting -} - enum PlayerBoosterType { HiddenGem GoalRush @@ -42,10 +25,9 @@ model User { street String? streetNr String? postCode String? - // favoriteClubId String - // registerInfo String role Int payed Boolean? @default(false) + banned Boolean? @default(false) teams Team[] Audit Audit[] @@ -77,7 +59,6 @@ model Player { selections Selection[] club Club? @relation(fields: [clubId], references: [id], onDelete: Cascade) - MatchEvent MatchEvent[] stats Statistic[] inPlayer Transfer[] @relation("inPlayer") outPlayer Transfer[] @relation("outPlayer") @@ -255,21 +236,9 @@ model Match { away Club? @relation(name: "awayMatch", fields: [awayId], references: [id]) week Week? @relation(fields: [weekId], references: [id]) - MatchEvent MatchEvent[] Statistic Statistic[] } -model MatchEvent { - id Int @id @default(autoincrement()) - type MatchEventType - matchId Int - playerId Int - minute Int - - match Match @relation(fields: [matchId], references: [id], onDelete: Cascade) - player Player @relation(fields: [playerId], references: [id], onDelete: Cascade) -} - model Transfer { id Int @id @default(autoincrement()) @@ -335,71 +304,4 @@ model Article { timestampUpdated DateTime? author User @relation(fields: [authorId], references: [id]) authorId Int -} - -// model WeeksOnTeams { -// week Week @relation(fields: [weekId], references: [id]) -// team Team @relation(fields: [teamId], references: [id]) -// weekId Int -// teamId Int - -// @@id([weekId, teamId]) -// } - -// export interface Player { -// id: number -// name: string -// short: string -// forename: string -// surname: string -// positionId: number -// externalId?: number -// value: number -// ban?: number -// injury?: number -// form?: number -// squadDepth?: number -// fieldOrder: number -// info?: number -// portraitUrl: string -// star: number -// setPieces: number -// captain: number -// caps: number -// squadStatus?: string -// clubId: number -// } - -// export interface Club { -// id: number -// name: string -// short: string -// styling: any -// externalId: number -// } - -// export interface DeadlineInfo { -// displayWeek: number -// deadlineWeek: number -// deadlineDate: string -// rosterEndWeek: number -// } - -// export interface Week { -// weekId: number -// roundId: any -// deadlineDate: string -// } - -// export interface Round { -// roundId: any -// deadlineDate: string -// } - -// export interface Club { -// id: number -// name: string -// short: string -// styling: any -// externalId: number -// } +} \ No newline at end of file diff --git a/src/controllers/MatchEvent.ts b/src/controllers/MatchEvent.ts deleted file mode 100644 index f7e27fa..0000000 --- a/src/controllers/MatchEvent.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { prisma } from "../db/client" - -export const GetMatchEventsHandler = async (req: any, rep: any) => { - const events = await prisma.matchEvent.findMany({ - where: { - matchId: +req.params.matchId - }, - orderBy: { - type: 'asc' - }, - include: { - player: true - } - }); - rep.send(events); -} - -// export const GetMatchEventHandler = async (req: any, rep: any) => { -// const event = await prisma.matchEvent.findUnique({ -// where: { -// id: req.params.id -// } -// }); -// rep.send(event); -// } - -export const PutMatchEventHandler = async (req: any, rep: any) => { - const events = await prisma.matchEvent.deleteMany({ - where: { - matchId: +req.params.matchId - } - }); - const event = await prisma.matchEvent.createMany({ - data: { - ...req.body - } - }); - rep.send(event); -} - -export const PostMatchEventsHandler = async (req: any, rep: any) => { - const eventsData = req.body.map((ev: any) => { - return { - type: ev.type, - matchId: ev.matchId, - playerId: ev.playerId, - minute: ev.minute, - } - }) - const event = await prisma.matchEvent.createMany({ - data: eventsData, - }); - rep.send(event); -} -export const PostMatchStartingHandler = async (req: any, rep: any) => { - const events = await prisma.matchEvent.deleteMany({ - where: { - matchId: +req.params.matchId, - type: 'Starting' - } - }); - const startingData = req.body.map((id: any) => { - return { - type: 'Starting', - matchId: +req.params.matchId, - playerId: id, - minute: 0, - } - }) - const starting = await prisma.matchEvent.createMany({ - data: startingData, - }); - rep.send(starting); -} - -export const DeleteMatchEventHandler = async (req: any, rep: any) => { - -} \ No newline at end of file diff --git a/src/controllers/Team.ts b/src/controllers/Team.ts index df557bb..eda65db 100644 --- a/src/controllers/Team.ts +++ b/src/controllers/Team.ts @@ -101,6 +101,7 @@ export const PostAddTeamHandler = async (req: any, rep: any) => { userId: req.user.id, action: 'POST_CREATE_UPDATE', params: JSON.stringify({ + teamId: req.team.id, userId: req.user.id, selections: { createMany: { @@ -473,6 +474,7 @@ export const PostEditTeamHandler = async (req: any, rep: any) => { userId: req.user.id, action: `EDIT_TEAM_${hasFreeHit ? 'FREE_HIT' : 'BEFORE_START'}`, params: JSON.stringify({ + teamId: +req.params.id, userId: req.user.id, selections: allWithValues, budget: budget, diff --git a/src/controllers/UserAuth.ts b/src/controllers/UserAuth.ts index 18ce896..fdb74de 100644 --- a/src/controllers/UserAuth.ts +++ b/src/controllers/UserAuth.ts @@ -37,7 +37,13 @@ export const GoogleAuthHandler = async (req: AccessTokenRequest, rep: any) => { } }); - let firstSignIn = false; + let firstSignIn = false; + if( !user && (process.env.DISABLED_REGISTRATIONS === "true" || false)) { + return rep.redirect(`${process.env.WEBAPP_URL}/denied?${qs.stringify({ reason: "registrations-disabled" })}`); + } + if (user && user.banned) { + return rep.redirect(`${process.env.WEBAPP_URL}/denied?${qs.stringify({ reason: "banned" })}`); + } if (!user) { user = await prisma.user.create({ data: { @@ -54,7 +60,7 @@ export const GoogleAuthHandler = async (req: AccessTokenRequest, rep: any) => { const refreshToken = signJwt({ ...user }, { expiresIn: "30d" }); rep.setCookie("token", accessToken, accessTokenCookieOptions); rep.setCookie("refreshToken", refreshToken, refreshTokenCookieOptions); - rep.redirect(`${process.env.WEBAPP_URL}/login/callback?${qs.stringify({ token: accessToken, refreshToken: refreshToken })}`); + return rep.redirect(`${process.env.WEBAPP_URL}/login/callback?${qs.stringify({ token: accessToken, refreshToken: refreshToken })}`); // rep.send(googleUserInfo) diff --git a/src/middleware/RequireUser.ts b/src/middleware/RequireUser.ts index 29477b6..61b609b 100644 --- a/src/middleware/RequireUser.ts +++ b/src/middleware/RequireUser.ts @@ -4,7 +4,10 @@ export const RequireUser = (req: any, rep: any, done: any) => { const user = req.user; if (!user) { - done(new HttpError("No credentials provided", 401)); + done(new HttpError("No credentials provided.", 401)); + } + if (user?.banned) { + done(new HttpError("You have been banned.", 403)); } done(); } \ No newline at end of file diff --git a/src/routers/Main.ts b/src/routers/Main.ts index 6395f7f..f2868aa 100644 --- a/src/routers/Main.ts +++ b/src/routers/Main.ts @@ -5,7 +5,6 @@ import { AdminPlayerRouter, PublicPlayerRouter } from './Player'; import { AdminClubRouter, PublicClubRouter } from './Club'; import { RequireAdmin } from '../middleware//RequireAdmin'; import { AdminMatchRouter, PublicMatchRouter } from './Match'; -import { AdminMatchEventRouter, PublicMatchEventRouter } from './MatchEvent'; import { AdminMatchStatisticRouter, PublicMatchStatisticRouter, PublicPlayerStatisticRouter } from './Statistic'; import { AdminWeekRouter, PublicWeekRouter } from './Week'; import { AdminPageRouter, PublicPageRouter } from './Page'; @@ -20,7 +19,6 @@ export const PublicRouter: FastifyPluginAsync = async server => { server.register(PublicPlayerRouter, { prefix: '/players' }) server.register(PublicClubRouter, { prefix: '/clubs' }) server.register(PublicMatchRouter, { prefix: '/matches' }) - server.register(PublicMatchEventRouter, { prefix: '/matches/:matchId/events' }) server.register(PublicMatchStatisticRouter, { prefix: '/matches/:matchId/stats' }) server.register(PublicWeekRouter, { prefix: '/weeks' }) server.register(PublicPlayerStatisticRouter, { prefix: '/player-stats' }) @@ -34,7 +32,6 @@ export const AdminRouter: FastifyPluginAsync = async server => { server.register(AdminPlayerRouter, { prefix: '/players' }) server.register(AdminClubRouter, { prefix: '/clubs' }) server.register(AdminMatchRouter, { prefix: '/matches' }) - server.register(AdminMatchEventRouter, { prefix: '/matches/:matchId/events' }) server.register(AdminMatchStatisticRouter, { prefix: '/matches/:matchId/stats' }) server.register(AdminWeekRouter, { prefix: '/weeks' }) server.register(AdminPageRouter, { prefix: '/pages' }) diff --git a/src/routers/MatchEvent.ts b/src/routers/MatchEvent.ts deleted file mode 100644 index 9cb775b..0000000 --- a/src/routers/MatchEvent.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { GetMatchEventsHandler, PutMatchEventHandler, PostMatchEventsHandler, DeleteMatchEventHandler, PostMatchStartingHandler } from "../controllers/MatchEvent"; -import { RequireUser } from "../middleware/RequireUser"; -import { MatchEventPutSchema, MatchEventPostSchema, MatchStartingPostSchema } from "../types/body-schema"; -import { FastifyPluginAsync } from "fastify"; - -export const PublicMatchEventRouter: FastifyPluginAsync = async server => { - server.route({ - method: 'GET', - url: '', - preHandler: RequireUser, - handler: GetMatchEventsHandler - }); -} - -export const AdminMatchEventRouter: FastifyPluginAsync = async server => { - server.route({ - method: 'PUT', - url: '', - preHandler: RequireUser, - handler: PutMatchEventHandler, - schema: { - body: MatchEventPutSchema - } - }); - - server.route({ - method: 'POST', - url: '', - preHandler: RequireUser, - handler: PostMatchEventsHandler, - schema: { - body: MatchEventPostSchema - } - }); - - server.route({ - method: 'POST', - url: '/starting', - preHandler: RequireUser, - handler: PostMatchStartingHandler, - schema: { - body: MatchStartingPostSchema - } - }); - - server.route({ - method: 'DELETE', - url: '', - preHandler: RequireUser, - handler: DeleteMatchEventHandler - }); -} \ No newline at end of file diff --git a/src/types/body-schema.ts b/src/types/body-schema.ts index 0a80054..88bc167 100644 --- a/src/types/body-schema.ts +++ b/src/types/body-schema.ts @@ -1,5 +1,3 @@ -import { MatchEventType } from "@prisma/client"; - export const GeneralClubWinnerSchema = { body: { type: "object", @@ -145,32 +143,6 @@ export const MatchPutSchema = { }, }; -export const MatchEventPostSchema = { - type: "array", - items: { - type: "object", - properties: { - type: { type: "string" }, - matchId: { type: "number" }, - playerId: { type: "number" }, - minute: { type: "number" }, - }, - }, -}; - -export const MatchEventPutSchema = { - type: "array", - items: { - type: "object", - properties: { - type: { type: "string" }, - matchId: { type: "number" }, - playerId: { type: "number" }, - minute: { type: "number" }, - }, - }, -}; - export const MatchStartingPostSchema = { type: "array", items: { type: "number" }, From dbe421a662fc221196f244c84f6c8775b0105f10 Mon Sep 17 00:00:00 2001 From: Jonas Simoen Date: Tue, 21 May 2024 19:40:44 +0200 Subject: [PATCH 4/4] fix(notifications): topic per environment --- src/controllers/Notification.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/Notification.ts b/src/controllers/Notification.ts index 6fef5e9..a38e46b 100644 --- a/src/controllers/Notification.ts +++ b/src/controllers/Notification.ts @@ -3,7 +3,7 @@ import { app } from "../../api/index" import { prisma } from "../db/client"; export const RegisterTokenHandler = async(req: any, rep: any) => { - getMessaging(app).subscribeToTopic(req.body.token, "edd-app"); + getMessaging(app).subscribeToTopic(req.body.token, `edd-app-${process.env.ENV}`); const token = await prisma.notificationToken.create({ data: { token: req.body.token,