Skip to content

Commit

Permalink
add endpoint to update invites
Browse files Browse the repository at this point in the history
  • Loading branch information
FaisalAl-Tameemi committed Sep 16, 2024
1 parent 36c0ddf commit 7977fef
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 3 deletions.
1 change: 1 addition & 0 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The API provides a comprehensive set of endpoints that allow you to:
5. Log and retrieve detailed transaction histories
6. Set up and trigger achievements and rewards
7. Implement event logging for user actions
8. Create and manage invites for communities

LoyaltyBank also includes the ability to have wallet balances and log transactions which can support a fully functional points system, among other use cases. Whether you're building a loyalty program, gamification features, or a complex rewards ecosystem, LoyaltyBank's API offers the flexibility and functionality to bring your vision to life.

Expand Down
10 changes: 10 additions & 0 deletions api/src/api/invite/inviteController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ export class InviteController {
.then((invite) => handleSuccessResponse({ invite }, res))
.catch((error) => handleErrorResponse(error, res))
}

updateInvite: RequestHandler = async (req: Request, res: Response) => {
const { inviteId } = req.params
const { status, expiresAt, maxUses } = req.body

return inviteService
.updateInvite(req.userId!, inviteId, { status, expiresAt, maxUses })
.then((invite) => handleSuccessResponse({ invite }, res))
.catch((error) => handleErrorResponse(error, res))
}
}

export const inviteController = new InviteController()
16 changes: 15 additions & 1 deletion api/src/api/invite/inviteRequestValidation.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { InviteStatus } from '@prisma/client'
import { InviteIncludeSchema, InviteWhereInputSchema } from '@zodSchema/index'
import { z } from "zod"

Expand All @@ -13,5 +14,18 @@ export const QueryInviteSchema = z.object({
})

export const AcceptInviteSchema = z.object({
inviteCode: z.string(),
body: z.object({
inviteCode: z.string(),
}),
})

export const UpdateInviteSchema = z.object({
params: z.object({
inviteId: z.string(),
}),
body: z.object({
status: z.nativeEnum(InviteStatus).optional(),
expiresAt: z.string().date().optional(),
maxUses: z.number().optional(),
}),
})
14 changes: 13 additions & 1 deletion api/src/api/invite/inviteRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import verifyJWT, { verifyJWTAndRole } from "@/common/middleware/verifyJWT"
import { inviteController } from "./inviteController"
import { InviteSchema } from '@zodSchema/index'
import { Role } from '@prisma/client'
import { AcceptInviteSchema, QueryInviteSchema } from './inviteRequestValidation'
import { AcceptInviteSchema, QueryInviteSchema, UpdateInviteSchema } from './inviteRequestValidation'
import { validateRequest } from '@/common/utils/httpHandlers'

export const inviteRegistry = new OpenAPIRegistry()
Expand Down Expand Up @@ -49,3 +49,15 @@ inviteRegistry.registerPath({
})

inviteRouter.post("/accept", verifyJWT, validateRequest(AcceptInviteSchema), inviteController.acceptInvite)

// Update an invite
inviteRegistry.registerPath({
method: "put",
path: "/invites/{inviteId}",
tags: ["Invite"],
responses: createApiResponse(z.object({
invite: InviteSchema,
}), "Success"),
})

inviteRouter.put("/:inviteId", verifyJWT, validateRequest(UpdateInviteSchema), inviteController.updateInvite)
55 changes: 54 additions & 1 deletion api/src/api/invite/inviteService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Prisma, Invite, InviteStatus } from '@prisma/client'
import { Prisma, Invite, InviteStatus, CommunityRole } from '@prisma/client'
import dbClient from '@/db'
import { QueryPaging } from '@/common/utils/commonTypes'
import { CustomError, CustomErrorCode } from '@/common/utils/errors'
Expand Down Expand Up @@ -96,6 +96,59 @@ export class InviteService {
total: results[1],
}
}

/**
* Update an invite
* @param userId: the id of the user updating the invite
* @param inviteId: the id of the invite to update
* @param updateData: the data to update the invite with
* @returns the updated invite
*/
async updateInvite(
userId: string,
inviteId: string,
updateData: Pick<Prisma.InviteUpdateInput, 'status' | 'expiresAt' | 'maxUses'>
): Promise<Invite> {
// Find the invite and ensure it's either created by the user or the user is an admin of the community
const invite = await dbClient.invite.findFirst({
where: {
id: inviteId,
OR: [
{
inviteBy: {
id: userId,
},
},
{
community: {
OR: [
{
memberships: {
some: {
id: userId,
communityRole: CommunityRole.ADMIN
},
},
},
{
createdById: userId,
}
]
}
}
]
},
})

if (!invite) {
throw new CustomError('Invite not found or user does not have permission to update', CustomErrorCode.INVALID_INVITE_OR_USER_NOT_ADMIN)
}

return dbClient.invite.update({
where: { id: inviteId },
data: updateData,
})
}
}

export const inviteService = new InviteService()
1 change: 1 addition & 0 deletions api/src/common/utils/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export enum CustomErrorCode {
INVITE_NOT_FOUND = 701,
INVITE_NOT_AVAILABLE = 702,
INVITE_MAX_USES_REACHED = 703,
INVALID_INVITE_OR_USER_NOT_ADMIN = 704,
}

export class CustomError extends Error {
Expand Down

0 comments on commit 7977fef

Please sign in to comment.