Skip to content

Commit

Permalink
Merge pull request #600 from bandada-infra/feat/check-invite
Browse files Browse the repository at this point in the history
feat: invite code validity check
  • Loading branch information
vplasencia authored Nov 22, 2024
2 parents 0f3a763 + f83fd6b commit 23d3cc6
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 1 deletion.
10 changes: 10 additions & 0 deletions apps/api/src/app/invites/invites.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ export class InvitesController {
return mapEntity(invite)
}

@Get("check/:code/group/:groupId")
@ApiOperation({ description: "Checks if a specific invite is valid." })
@ApiCreatedResponse({ type: Boolean })
async checkInvite(
@Param("code") inviteCode: string,
@Param("groupId") groupId: string
): Promise<boolean> {
return this.invitesService.checkInvite(inviteCode, groupId)
}

@Patch("redeem")
@ApiBody({ type: RedeemInviteDto })
@ApiHeader({ name: "x-api-key", required: true })
Expand Down
19 changes: 19 additions & 0 deletions apps/api/src/app/invites/invites.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,25 @@ describe("InvitesService", () => {
})
})

describe("# checkInvite", () => {
it("Should return true if invite is valid", async () => {
const { code } = await invitesService.createInvite(
{ groupId },
admin.id
)

const invite = await invitesService.checkInvite(code, groupId)

expect(invite).toBeTruthy()
})

it("Should return false if invite is invalid", async () => {
const invite = await invitesService.checkInvite("12345", groupId)

expect(invite).toBeFalsy()
})
})

describe("# redeemInvite", () => {
let invite: Invite

Expand Down
18 changes: 18 additions & 0 deletions apps/api/src/app/invites/invites.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,24 @@ export class InvitesService {
return invite
}

/**
* Returns boolean value if the invite code is valid.
* @param inviteCode Invite code.
* @param groupId Group id.
* @returns Boolean.
*/
async checkInvite(inviteCode: string, groupId: string): Promise<boolean> {
const invite = await this.inviteRepository.findOne({
where: {
code: inviteCode,
group: { id: groupId }
},
relations: ["group"]
})

return !!invite
}

/**
* Redeems an invite by consuming its code. Every invite
* can be used only once.
Expand Down
21 changes: 21 additions & 0 deletions apps/client/src/api/bandadaAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,27 @@ export async function addMemberByInviteCode(
}
}

export async function checkInvite(
inviteCode: string,
groupId: string
): Promise<boolean> {
try {
return await request(
`${API_URL}/invites/check/${inviteCode}/group/${groupId}`
)
} catch (error: any) {
console.error(error)

if (error.response) {
alert(error.response.statusText)
} else {
alert("Some error occurred!")
}

return false
}
}

export async function redeemInvite(
inviteCode: string,
groupId: string
Expand Down
11 changes: 11 additions & 0 deletions apps/client/src/pages/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ export default function HomePage(): JSX.Element {
return
}

const isValid = await bandadaAPI.checkInvite(
inviteCode,
invite.group.id
)

if (!isValid) {
setLoading(false)
alert("Invalid invite code")
return
}

const signer = library.getSigner(account)

const message = `Sign this message to generate your Semaphore identity.`
Expand Down
26 changes: 26 additions & 0 deletions apps/docs/docs/api-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,32 @@ const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc"
const invite = await apiSdk.getInvite(inviteCode)
```

## Check invite

\# **checkInvite**(): _Promise\<boolean>_

Returns boolean value if the invite code is valid.

```ts
const inviteCode = "C5VAG4HD"
const groupId = "10402173435763029700781503965100"

const isValid = await apiSdk.checkInvite(inviteCode, groupId)
```

## Redeem invite

\# **redeemInvite**(): _Promise\<Invite>_

Redeems a specific invite.

```ts
const groupId = "10402173435763029700781503965100"
const inviteCode = "C5VAG4HD"

const invite = await apiSdk.redeemInvite(inviteCode, groupId)
```

## Get credential group join URL

\# **getCredentialGroupJoinUrl**(): _string_
Expand Down
13 changes: 13 additions & 0 deletions libs/api-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,19 @@ const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc"
const invite = await apiSdk.getInvite(inviteCode)
```

## Check invite

\# **checkInvite**(): _Promise\<boolean>_

Returns boolean value if the invite code is valid.

```ts
const inviteCode = "C5VAG4HD"
const groupId = "10402173435763029700781503965100"

const isValid = await apiSdk.checkInvite(inviteCode, groupId)
```

## Redeem invite

\# **redeemInvite**(): _Promise\<Invite>_
Expand Down
18 changes: 17 additions & 1 deletion libs/api-sdk/src/apiSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
getGroupsByType,
createAssociatedGroup
} from "./groups"
import { createInvite, getInvite, redeemInvite } from "./invites"
import { checkInvite, createInvite, getInvite, redeemInvite } from "./invites"

export default class ApiSdk {
private _url: string
Expand Down Expand Up @@ -419,6 +419,22 @@ export default class ApiSdk {
return invite
}

/**
* Returns boolean value if the invite code is valid.
* @param inviteCode Invite code.
* @param groupId Group id.
* @returns Boolean.
*/
async checkInvite(inviteCode: string, groupId: string): Promise<boolean> {
const isInviteValid = await checkInvite(
this._config,
inviteCode,
groupId
)

return isInviteValid
}

/**
* Redeems a specific invite.
* @param inviteCode Invite code.
Expand Down
19 changes: 19 additions & 0 deletions libs/api-sdk/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,25 @@ describe("Bandada API SDK", () => {
})
})

describe("# checkInvite", () => {
it("Should check if an invite is valid", async () => {
const groupId = "95633257675970239314311768035433"
const inviteCode = "C5VAG4HD"

requestMocked.mockImplementationOnce(() =>
Promise.resolve(true)
)

const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV)
const isInviteValid = await apiSdk.checkInvite(
inviteCode,
groupId
)

expect(isInviteValid).toBeTruthy()
})
})

describe("# redeemInvite", () => {
it("Should redeem an invite", async () => {
const groupId = "95633257675970239314311768035433"
Expand Down
25 changes: 25 additions & 0 deletions libs/api-sdk/src/invites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@ export async function getInvite(
return invite
}

/**
* Returns boolean value if the invite code is valid.
* @param inviteCode Invite code.
* @param groupId Group id.
* @returns Boolean.
*/
export async function checkInvite(
config: object,
inviteCode: string,
groupId: string
): Promise<boolean> {
const requestUrl = `${url}/check/${inviteCode}/group/${groupId}`

const req = await request(requestUrl, config)

return req
}

/**
* Creates one new group invite.
* @param groupId The group identifier.
Expand All @@ -47,6 +65,13 @@ export async function createInvite(
return req
}

/**
* Redeems a specific invite.
* @param inviteCode Invite code to be redeemed.
* @param groupId Group id.
* @param apiKey API Key of the admin.
* @returns The updated redeemed invite.
*/
export async function redeemInvite(
config: object,
inviteCode: string,
Expand Down

0 comments on commit 23d3cc6

Please sign in to comment.