diff --git a/apps/api/src/app/groups/dto/add-member-to-groups.dto.ts b/apps/api/src/app/groups/dto/add-member-to-groups.dto.ts new file mode 100644 index 00000000..b94f169c --- /dev/null +++ b/apps/api/src/app/groups/dto/add-member-to-groups.dto.ts @@ -0,0 +1,9 @@ +import { ApiProperty } from "@nestjs/swagger" +import { ArrayNotEmpty, IsArray } from "class-validator" + +export class AddMemberToGroupsDto { + @IsArray() + @ArrayNotEmpty() + @ApiProperty() + readonly groupIds: string[] +} diff --git a/apps/api/src/app/groups/groups.controller.ts b/apps/api/src/app/groups/groups.controller.ts index bf1bc24e..a6a1ea0a 100644 --- a/apps/api/src/app/groups/groups.controller.ts +++ b/apps/api/src/app/groups/groups.controller.ts @@ -31,6 +31,7 @@ import { UpdateGroupsDto } from "./dto/update-groups.dto" import { GroupsService } from "./groups.service" import { mapGroupToResponseDTO } from "./groups.utils" import { RemoveGroupsDto } from "./dto/remove-groups.dto" +import { AddMemberToGroupsDto } from "./dto/add-member-to-groups.dto" @ApiTags("groups") @Controller("groups") @@ -40,15 +41,26 @@ export class GroupsController { @Get() @ApiQuery({ name: "adminId", required: false, type: String }) @ApiQuery({ name: "memberId", required: false, type: String }) + @ApiQuery({ + name: "groupIds", + required: false, + type: String, + isArray: true + }) @ApiOperation({ description: "Returns the list of groups." }) @ApiCreatedResponse({ type: Group, isArray: true }) async getGroups( @Query("adminId") adminId: string, - @Query("memberId") memberId: string + @Query("memberId") memberId: string, + @Query("groupIds") groupIds: string[] ) { - const groups = await this.groupsService.getGroups({ adminId, memberId }) - const groupIds = groups.map((group) => group.id) - const fingerprints = await this.groupsService.getFingerprints(groupIds) + const groups = await this.groupsService.getGroups({ + adminId, + memberId, + groupIds + }) + const groupsIds = groups.map((group) => group.id) + const fingerprints = await this.groupsService.getFingerprints(groupsIds) return groups.map((group, index) => mapGroupToResponseDTO(group, fingerprints[index]) @@ -365,6 +377,38 @@ export class GroupsController { throw new NotImplementedException() } + @Post("/members/:member") + @ApiBody({ type: AddMemberToGroupsDto }) + @ApiHeader({ name: "x-api-key", required: true }) + @ApiOperation({ + description: + "Adds a member to multiple groups. Requires an API Key in the headers or a valid session." + }) + async addMemberToGroups( + @Param("member") memberId: string, + @Body() dto: AddMemberToGroupsDto, + @Headers() headers: Headers, + @Req() req: Request + ): Promise { + const apiKey = headers["x-api-key"] as string + + if (apiKey) { + await this.groupsService.addMemberToGroupsWithAPIKey( + dto.groupIds, + memberId, + apiKey + ) + } else if (req.session.adminId) { + await this.groupsService.addMemberToGroupsManually( + dto.groupIds, + memberId, + req.session.adminId + ) + } else { + throw new NotImplementedException() + } + } + @Delete(":group/members/:member") @ApiHeader({ name: "x-api-key", required: true }) @ApiOperation({ diff --git a/apps/api/src/app/groups/groups.service.test.ts b/apps/api/src/app/groups/groups.service.test.ts index 95792863..2abe06a0 100644 --- a/apps/api/src/app/groups/groups.service.test.ts +++ b/apps/api/src/app/groups/groups.service.test.ts @@ -266,6 +266,34 @@ describe("GroupsService", () => { expect(result).toHaveLength(1) }) + + it("Should return a list of groups by group ids", async () => { + const group1 = await groupsService.createGroup( + { + name: "Group Id 1", + description: "This is a description", + treeDepth: 16, + fingerprintDuration: 3600 + }, + "admin" + ) + + const group2 = await groupsService.createGroup( + { + name: "Group Id 2", + description: "This is a description", + treeDepth: 16, + fingerprintDuration: 3600 + }, + "admin" + ) + + const result = await groupsService.getGroups({ + groupIds: [group1.id, group2.id] + }) + + expect(result).toHaveLength(2) + }) }) describe("# getGroup", () => { @@ -1487,6 +1515,212 @@ describe("GroupsService", () => { }) }) + describe("# addMemberToGroupsManually", () => { + let groups: Array + let admin: Admin + + beforeAll(async () => { + admin = await adminsService.create({ + id: "admin", + address: "0x" + }) + + groups = await groupsService.createGroupsManually( + [ + { + name: "Multiple Group 1", + description: "This is a new group", + treeDepth: 16, + fingerprintDuration: 3600 + }, + { + name: "Multiple Group 2", + description: "This is a new group", + treeDepth: 16, + fingerprintDuration: 3600 + } + ], + admin.id + ) + }) + + it("Should add a member to multiple groups manually", async () => { + const multipleGroups = + await groupsService.addMemberToGroupsManually( + groups.map((g) => g.id), + "123123", + admin.id + ) + + expect(multipleGroups).toHaveLength(2) + }) + + it("Should not add a member to the groups if the group is a credential group", async () => { + const _group = await groupsService.createGroup( + { + name: "Multiple Group Credential Group", + description: "This is a new group", + treeDepth: 16, + fingerprintDuration: 3600, + credentials: { + id: "GITHUB_FOLLOWERS", + criteria: { + minFollowers: 5 + } + } + }, + admin.id + ) + + const fun = groupsService.addMemberToGroupsManually( + [groups[0].id, _group.id], + "456456", + admin.id + ) + + await expect(fun).rejects.toThrow( + `The group '${_group.name}' is a credential group. You cannot manually add members to a credential group.` + ) + }) + + it("Should not add a member to multiple groups if the member already exists", async () => { + const fun = groupsService.addMemberToGroupsManually( + groups.map((g) => g.id), + "123123", + admin.id + ) + + await expect(fun).rejects.toThrow( + `Member '123123' already exists in the group '${groups[0].id}'` + ) + }) + + it("Should not add a member to multiple groups if the admin is the wrong admin", async () => { + const fun = groupsService.addMemberToGroupsManually( + groups.map((g) => g.id), + "123123", + "wrong-admin" + ) + + await expect(fun).rejects.toThrow( + `You are not the admin of the group '${groups[0].id}'` + ) + }) + }) + + describe("# addMembersToGroupsWithAPIKey", () => { + let groups: Array + let admin: Admin + let apiKey: string + + beforeAll(async () => { + admin = await adminsService.create({ + id: "admin", + address: "0x" + }) + + apiKey = await adminsService.updateApiKey( + admin.id, + ApiKeyActions.Generate + ) + + groups = await groupsService.createGroupsManually( + [ + { + name: "Multiple Group API 1", + description: "This is a new group", + treeDepth: 16, + fingerprintDuration: 3600 + }, + { + name: "Multiple Group API 2", + description: "This is a new group", + treeDepth: 16, + fingerprintDuration: 3600 + } + ], + admin.id + ) + }) + + it("Should add a member to multiple groups via API", async () => { + const multipleGroups = + await groupsService.addMemberToGroupsWithAPIKey( + groups.map((g) => g.id), + "123123", + apiKey + ) + + expect(multipleGroups).toHaveLength(2) + }) + + it("Should not add a member to the groups if the group is a credential group", async () => { + const _group = await groupsService.createGroup( + { + name: "Multiple Group Credential Group API", + description: "This is a new group", + treeDepth: 16, + fingerprintDuration: 3600, + credentials: { + id: "GITHUB_FOLLOWERS", + criteria: { + minFollowers: 5 + } + } + }, + admin.id + ) + + const fun = groupsService.addMemberToGroupsWithAPIKey( + [groups[0].id, _group.id], + "456456", + apiKey + ) + + await expect(fun).rejects.toThrow( + `The group '${_group.name}' is a credential group. You cannot add members to a credential group using an API Key.` + ) + }) + + it("Should not add a member to multiple groups if the member already exists", async () => { + const fun = groupsService.addMemberToGroupsWithAPIKey( + groups.map((g) => g.id), + "123123", + apiKey + ) + + await expect(fun).rejects.toThrow( + `Member '123123' already exists in the group '${groups[0].id}'` + ) + }) + + it("Should not add a member to multiple groups if the API key is invalid", async () => { + const fun = groupsService.addMemberToGroupsWithAPIKey( + groups.map((g) => g.id), + "123123", + "invalid-apikey" + ) + + await expect(fun).rejects.toThrow( + `Invalid API key or API access not enabled for admin '${admin.id}'` + ) + }) + + it("Should not add a member to multiple groups if the API key is disabled", async () => { + await adminsService.updateApiKey(admin.id, ApiKeyActions.Disable) + + const fun = groupsService.addMemberToGroupsWithAPIKey( + groups.map((g) => g.id), + "123123", + apiKey + ) + + await expect(fun).rejects.toThrow( + `Invalid API key or API access not enabled for admin '${admin.id}'` + ) + }) + }) + describe("# createGroupManually", () => { const groupDto: CreateGroupDto = { id: "1", diff --git a/apps/api/src/app/groups/groups.service.ts b/apps/api/src/app/groups/groups.service.ts index c0c7eae2..b6936e28 100644 --- a/apps/api/src/app/groups/groups.service.ts +++ b/apps/api/src/app/groups/groups.service.ts @@ -11,7 +11,7 @@ import { } from "@nestjs/common" import { InjectRepository } from "@nestjs/typeorm" import { Group as CachedGroup } from "@semaphore-protocol/group" -import { Repository } from "typeorm" +import { Repository, In } from "typeorm" import { InvitesService } from "../invites/invites.service" import { AdminsService } from "../admins/admins.service" import { CreateGroupDto } from "./dto/create-group.dto" @@ -552,6 +552,98 @@ export class GroupsService { return this.addMembers(groupId, memberIds) } + /** + * Add a member to multiple groups manually as an admin. + * @param groupIds Array of group ids to be added. + * @param memberId Member id. + * @param adminId Group admin id. + * @returns Array of groups of added member. + */ + async addMemberToGroupsManually( + groupIds: string[], + memberId: string, + adminId: string + ): Promise { + for await (const groupId of groupIds) { + const group = await this.getGroup(groupId) + + if (group.adminId !== adminId) { + throw new UnauthorizedException( + `You are not the admin of the group '${groupId}'` + ) + } + + if (group.credentials !== null) { + throw new Error( + `The group '${group.name}' is a credential group. You cannot manually add members to a credential group.` + ) + } + + if (this.isGroupMember(groupId, memberId)) { + throw new BadRequestException( + `Member '${memberId}' already exists in the group '${groupId}'` + ) + } + } + + for await (const groupId of groupIds) { + await this.addMember(groupId, memberId) + } + + return this.getGroups({ groupIds }) + } + + /** + * Add a member to multiple groups using API Key. + * @param groupIds Array of group ids to be added. + * @param memberId Member id. + * @param apiKey API key for the group. + * @returns Array of groups of added member. + */ + async addMemberToGroupsWithAPIKey( + groupIds: string[], + memberId: string, + apiKey: string + ): Promise { + for await (const groupId of groupIds) { + const group = await this.getGroup(groupId) + + const admin = await this.adminsService.findOne({ + id: group.adminId + }) + + if (!admin) { + throw new BadRequestException( + `Invalid admin for group '${groupId}'` + ) + } + + if (!admin.apiEnabled || admin.apiKey !== apiKey) { + throw new BadRequestException( + `Invalid API key or API access not enabled for admin '${admin.id}'` + ) + } + + if (group.credentials !== null) { + throw new Error( + `The group '${group.name}' is a credential group. You cannot add members to a credential group using an API Key.` + ) + } + + if (this.isGroupMember(groupId, memberId)) { + throw new BadRequestException( + `Member '${memberId}' already exists in the group '${groupId}'` + ) + } + } + + for await (const groupId of groupIds) { + await this.addMember(groupId, memberId) + } + + return this.getGroups({ groupIds }) + } + /** * Add a member to the group. * @param groupId Group id. @@ -820,6 +912,7 @@ export class GroupsService { async getGroups(filters?: { adminId?: string memberId?: string + groupIds?: string[] }): Promise { let where = {} @@ -838,6 +931,13 @@ export class GroupsService { } } + if (filters?.groupIds) { + where = { + id: In(filters.groupIds), + ...where + } + } + return this.groupRepository.find({ relations: { members: true }, where, diff --git a/apps/docs/docs/api-sdk.md b/apps/docs/docs/api-sdk.md index 9bd13bdf..3988ddc2 100644 --- a/apps/docs/docs/api-sdk.md +++ b/apps/docs/docs/api-sdk.md @@ -322,6 +322,21 @@ const memberId = "1" const groups = await apiSdk.getGroupsByMemberId(memberId) ``` +## Get groups by group ids + +\# **getGroupByGroupIds**(): _Promise\_ + +Returns the list of groups by group ids. + +```ts +const groupIds = [ + "10402173435763029700781503965100", + "20402173435763029700781503965200" +] + +const groups = await apiSdk.getGroupsByGroupIds(groupIds) +``` + ## Is group member \# **isGroupMember**(): _Promise\_ @@ -390,6 +405,20 @@ const inviteCode = "MQYS4UR5" await apiSdk.addMemberByInviteCode(groupId, memberId, inviteCode) ``` +## Add member to groups using an API Key + +\# **addMemberToGroupsByApiKey**(): _Promise\_ + +Adds a member to multiple groups using an API Key. + +```ts +const groupIds = ["10402173435763029700781503965100", "20402173435763029700781503965200"] +const memberId = "1" +const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + +await apiSdk.addMemberToGroupsByApiKey(groupIds, memberId, apiKey) +``` + ## Remove member using an API Key \# **removeMemberByApiKey**(): _Promise\_ diff --git a/libs/api-sdk/README.md b/libs/api-sdk/README.md index 21e01288..2318d2b3 100644 --- a/libs/api-sdk/README.md +++ b/libs/api-sdk/README.md @@ -345,6 +345,21 @@ const memberId = "1" const groups = await apiSdk.getGroupsByMemberId(memberId) ``` +## Get groups by group ids + +\# **getGroupByGroupIds**(): _Promise\_ + +Returns the list of groups by group ids. + +```ts +const groupIds = [ + "10402173435763029700781503965100", + "20402173435763029700781503965200" +] + +const groups = await apiSdk.getGroupsByGroupIds(groupIds) +``` + ## Is group member \# **isGroupMember**(): _Promise\_ @@ -413,6 +428,23 @@ const inviteCode = "MQYS4UR5" await apiSdk.addMemberByInviteCode(groupId, memberId, inviteCode) ``` +## Add member to groups using an API Key + +\# **addMemberToGroupsByApiKey**(): _Promise\_ + +Adds a member to multiple groups using an API Key. + +```ts +const groupIds = [ + "10402173435763029700781503965100", + "20402173435763029700781503965200" +] +const memberId = "1" +const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + +await apiSdk.addMemberToGroupsByApiKey(groupIds, memberId, apiKey) +``` + ## Remove member using an API Key \# **removeMemberByApiKey**(): _Promise\_ diff --git a/libs/api-sdk/src/apiSdk.ts b/libs/api-sdk/src/apiSdk.ts index 822564dc..95282f5a 100644 --- a/libs/api-sdk/src/apiSdk.ts +++ b/libs/api-sdk/src/apiSdk.ts @@ -24,8 +24,10 @@ import { removeMembersByApiKey, getGroupsByAdminId, getGroupsByMemberId, + getGroupsByGroupIds, getCredentialGroupJoinUrl, - getMultipleCredentialsGroupJoinUrl + getMultipleCredentialsGroupJoinUrl, + addMemberToGroupsByApiKey } from "./groups" import { createInvite, getInvite, redeemInvite } from "./invites" @@ -112,6 +114,17 @@ export default class ApiSdk { return groups } + /** + * Returns the list of groups by group ids. + * @param groupIds Group ids. + * @returns List of groups by group ids. + */ + async getGroupsByGroupIds(groupIds: string[]): Promise { + const groups = await getGroupsByGroupIds(this._config, groupIds) + + return groups + } + /** * Creates a group using the API key. * @param groupCreationDetails Data to create the group. @@ -314,6 +327,26 @@ export default class ApiSdk { await addMemberByInviteCode(this._config, groupId, memberId, inviteCode) } + /** + * Adds a member to multiple groups using an API Key. + * @param groupIds Array of group ids. + * @param memberId Member id. + * @param apiKey API Key of the admin of the group. + * @returns Array of the groups of added member. + */ + async addMemberToGroupsByApiKey( + groupIds: string[], + memberId: string, + apiKey: string + ): Promise { + await addMemberToGroupsByApiKey( + this._config, + groupIds, + memberId, + apiKey + ) + } + /** * Removes a member from a group using an API Key. * @param groupId Group id. diff --git a/libs/api-sdk/src/groups.ts b/libs/api-sdk/src/groups.ts index 4cc9481f..e8a0be35 100644 --- a/libs/api-sdk/src/groups.ts +++ b/libs/api-sdk/src/groups.ts @@ -95,6 +95,41 @@ export async function getGroupsByMemberId( return groups } +/** + * Returns the list of groups by group ids. + * @param groupIds Group ids. + * @returns List of groups by group ids. + */ +export async function getGroupsByGroupIds( + config: object, + groupIds: string[] +): Promise { + let requestUrl = `${url}?` + + for (const groupId of groupIds) { + requestUrl += `&groupIds=${groupId}` + } + + let groups = await request(requestUrl, config) + + groups = groups.map((group: any) => { + let credentials + + try { + credentials = JSON.parse(group.credentials) + } catch (error) { + credentials = null + } + + return { + ...group, + credentials + } + }) + + return groups +} + /** * Creates one or more groups with the provided details. * @param groupsCreationDetails Data to create the groups. @@ -375,6 +410,34 @@ export async function addMemberByInviteCode( await request(requestUrl, newConfig) } +/** + * Adds a member to multiple groups. + * @param groupIds Array of group ids. + * @param memberId Member id. + * @param apiKey API Key of the admin. + * @returns Array of the groups of added member. + */ +export function addMemberToGroupsByApiKey( + config: object, + groupIds: string[], + memberId: string, + apiKey: string +): Promise { + const newConfig: any = { + method: "post", + data: { + groupIds + }, + ...config + } + + newConfig.headers["x-api-key"] = apiKey + + const req = request(`${url}/members/${memberId}`, newConfig) + + return req +} + /** * Removes a member from a group using an API Key. * @param groupId Group id. diff --git a/libs/api-sdk/src/index.test.ts b/libs/api-sdk/src/index.test.ts index 6d3203d8..8f8cc5ce 100644 --- a/libs/api-sdk/src/index.test.ts +++ b/libs/api-sdk/src/index.test.ts @@ -604,6 +604,59 @@ describe("Bandada API SDK", () => { expect(groups[0].credentials).toBeNull() }) }) + describe("getGroupsByGroupIds", () => { + it("Should return all groups by group ids", async () => { + requestMocked.mockImplementationOnce(() => + Promise.resolve([ + { + id: "10402173435763029700781503965100", + name: "Group1", + description: "This is a new group", + admin: "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + treeDepth: 16, + fingerprintDuration: 3600, + createdAt: "2023-07-15T08:21:05.000Z", + members: [], + credentials: null + } + ]) + ) + + const groupIds = ["10402173435763029700781503965100"] + + const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) + const groups: Group[] = await apiSdk.getGroupsByGroupIds( + groupIds + ) + expect(groups).toHaveLength(1) + }) + it("Should return all groups by group ids and null in the credentials that don't have a valid JSON string", async () => { + requestMocked.mockImplementationOnce(() => + Promise.resolve([ + { + id: "10402173435763029700781503965100", + name: "Group1", + description: "This is a new group", + admin: "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + treeDepth: 16, + fingerprintDuration: 3600, + createdAt: "2023-07-15T08:21:05.000Z", + members: [], + credentials: {} + } + ]) + ) + + const groupIds = ["10402173435763029700781503965100"] + + const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) + const groups: Group[] = await apiSdk.getGroupsByGroupIds( + groupIds + ) + expect(groups).toHaveLength(1) + expect(groups[0].credentials).toBeNull() + }) + }) describe("#getGroup", () => { it("Should return a group", async () => { requestMocked.mockImplementationOnce(() => @@ -795,86 +848,105 @@ describe("Bandada API SDK", () => { ) expect(res).toBeUndefined() }) - describe("#removeMemberByApiKey", () => { - it("Should remove a member from a group using an API Key", async () => { - requestMocked.mockImplementationOnce(() => - Promise.resolve() - ) + }) - const groupId = "10402173435763029700781503965100" - const memberId = "1" - const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + describe("#addMemberToGroups", () => { + it("Should add a member to multiple groups using an API Key", async () => { + requestMocked.mockImplementationOnce(() => Promise.resolve()) - const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) - const res = await apiSdk.removeMemberByApiKey( - groupId, - memberId, - apiKey - ) - expect(res).toBeUndefined() - }) + const groupIds = [ + "10402173435763029700781503965100", + "20402173435763029700781503965200" + ] + const memberId = "1" + const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + + const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) + const res = await apiSdk.addMemberToGroupsByApiKey( + groupIds, + memberId, + apiKey + ) + + expect(res).toBeUndefined() }) + }) - describe("#removeMembersByApiKey", () => { - it("Should remove multiple members from a group using an API Key", async () => { - requestMocked.mockImplementationOnce(() => - Promise.resolve() - ) + describe("#removeMemberByApiKey", () => { + it("Should remove a member from a group using an API Key", async () => { + requestMocked.mockImplementationOnce(() => Promise.resolve()) - const groupId = "10402173435763029700781503965100" - const memberIds = ["1", "2", "3"] - const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + const groupId = "10402173435763029700781503965100" + const memberId = "1" + const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" - const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) - const res = await apiSdk.removeMembersByApiKey( - groupId, - memberIds, - apiKey - ) - expect(res).toBeUndefined() - }) + const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) + const res = await apiSdk.removeMemberByApiKey( + groupId, + memberId, + apiKey + ) + expect(res).toBeUndefined() }) + }) - describe("#getCredentialGroupJoinUrl", () => { - it("Should generate a custom url for joining a credential group", async () => { - const dashboardUrl = DashboardUrl.DEV - const groupId = "10402173435763029700781503965100" - const commitment = "1" - const providerName = "github" - const redirectUri = "http://localhost:3003" - - const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) - const res = apiSdk.getCredentialGroupJoinUrl( - dashboardUrl, - groupId, - commitment, - providerName, - redirectUri - ) + describe("#removeMembersByApiKey", () => { + it("Should remove multiple members from a group using an API Key", async () => { + requestMocked.mockImplementationOnce(() => Promise.resolve()) + + const groupId = "10402173435763029700781503965100" + const memberIds = ["1", "2", "3"] + const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + + const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) + const res = await apiSdk.removeMembersByApiKey( + groupId, + memberIds, + apiKey + ) + expect(res).toBeUndefined() + }) + }) - const url = `${dashboardUrl}/credentials?group=${groupId}&member=${commitment}&provider=${providerName}&redirect_uri=${redirectUri}?redirect=true` + describe("#getCredentialGroupJoinUrl", () => { + it("Should generate a custom url for joining a credential group", async () => { + const dashboardUrl = DashboardUrl.DEV + const groupId = "10402173435763029700781503965100" + const commitment = "1" + const providerName = "github" + const redirectUri = "http://localhost:3003" - expect(res).toBe(url) - }) + const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) + const res = apiSdk.getCredentialGroupJoinUrl( + dashboardUrl, + groupId, + commitment, + providerName, + redirectUri + ) + + const url = `${dashboardUrl}/credentials?group=${groupId}&member=${commitment}&provider=${providerName}&redirect_uri=${redirectUri}?redirect=true` + + expect(res).toBe(url) }) + }) - describe("#getMultipleCredentialGroupJoinUrl", () => { - it("Should generate a custom url for joining a multiple credential group", async () => { - const dashboardUrl = DashboardUrl.DEV - const groupId = "10402173435763029700781503965100" - const commitment = "1" - - const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) - const res = apiSdk.getMultipleCredentialsGroupJoinUrl( - dashboardUrl, - groupId, - commitment - ) + describe("#getMultipleCredentialGroupJoinUrl", () => { + it("Should generate a custom url for joining a multiple credential group", async () => { + const dashboardUrl = DashboardUrl.DEV + const groupId = "10402173435763029700781503965100" + const commitment = "1" + + const apiSdk: ApiSdk = new ApiSdk(SupportedUrl.DEV) + const res = apiSdk.getMultipleCredentialsGroupJoinUrl( + dashboardUrl, + groupId, + commitment + ) - const url = `${dashboardUrl}/credentials?group=${groupId}&member=${commitment}&type=multiple` + const url = `${dashboardUrl}/credentials?group=${groupId}&member=${commitment}&type=multiple` - expect(res).toBe(url) - }) + expect(res).toBe(url) }) }) })