From c306e86ccaae422aa6284755a8b98d4dfae0eec6 Mon Sep 17 00:00:00 2001 From: Jeeiii Date: Thu, 28 Mar 2024 22:53:18 +0100 Subject: [PATCH] feat: add missing APIs endpoints on ApiSdk --- apps/api/src/app/groups/groups.controller.ts | 178 ++++++++- apps/dashboard/src/api/bandadaAPI.ts | 44 +-- libs/api-sdk/src/admins.ts | 68 ++++ libs/api-sdk/src/apiSdk.ts | 124 ++++++- libs/api-sdk/src/groups.ts | 143 +++++++- libs/api-sdk/src/index.test.ts | 367 ++++++++++++++++++- libs/api-sdk/src/types/index.ts | 44 +++ 7 files changed, 907 insertions(+), 61 deletions(-) create mode 100644 libs/api-sdk/src/admins.ts diff --git a/apps/api/src/app/groups/groups.controller.ts b/apps/api/src/app/groups/groups.controller.ts index bc8bc954..0148913b 100644 --- a/apps/api/src/app/groups/groups.controller.ts +++ b/apps/api/src/app/groups/groups.controller.ts @@ -15,7 +15,6 @@ import { import { ApiBody, ApiCreatedResponse, - ApiExcludeEndpoint, ApiHeader, ApiOperation, ApiQuery, @@ -64,37 +63,176 @@ export class GroupsController { @Post() @UseGuards(AuthGuard) - @ApiExcludeEndpoint() - async createGroup(@Req() req: Request, @Body() dto: CreateGroupDto) { - const group = await this.groupsService.createGroup( - dto, - req.session.adminId - ) - const fingerprint = await this.groupsService.getFingerprint(group.id) + @ApiBody({ required: false, type: Array }) + @ApiHeader({ name: "x-api-key", required: false }) + @ApiCreatedResponse({ type: Group }) + @ApiOperation({ + description: "Create one or more groups using an API Key or manually." + }) + async createGroups( + @Body() dtos: Array, + @Headers() headers: Headers, + @Req() req: Request + ) { + let groups = [] + const groupsToResponseDTO = [] - return mapGroupToResponseDTO(group, fingerprint) + const apiKey = headers["x-api-key"] as string + + if (apiKey) { + groups = await this.groupsService.createGroupsWithAPIKey( + dtos, + apiKey + ) + } + + if (req.session.adminId) { + groups = await this.groupsService.createGroupsManually( + dtos, + req.session.adminId + ) + } + + for await (const group of groups) { + const fingerprint = await this.groupsService.getFingerprint( + group.id + ) + + groupsToResponseDTO.push(mapGroupToResponseDTO(group, fingerprint)) + } + + return groupsToResponseDTO + } + + @Delete() + @UseGuards(AuthGuard) + @ApiBody({ required: false, type: Array }) + @ApiHeader({ name: "x-api-key", required: false }) + @ApiOperation({ + description: "Remove one or more groups using an API Key or manually." + }) + async removeGroups( + @Body() groupsIds: Array, + @Headers() headers: Headers, + @Req() req: Request + ) { + const apiKey = headers["x-api-key"] as string + + if (apiKey) { + await this.groupsService.removeGroupsWithAPIKey(groupsIds, apiKey) + } + + if (req.session.adminId) { + await this.groupsService.removeGroupsManually( + groupsIds, + req.session.adminId + ) + } } @Delete(":group") @UseGuards(AuthGuard) - @ApiExcludeEndpoint() - async removeGroup(@Req() req: Request, @Param("group") groupId: string) { - await this.groupsService.removeGroup(groupId, req.session.adminId) + @ApiHeader({ name: "x-api-key", required: false }) + @ApiOperation({ + description: "Remove a specific group using an API Key or manually" + }) + async removeGroup( + @Param("group") groupId: string, + @Headers() headers: Headers, + @Req() req: Request + ) { + const apiKey = headers["x-api-key"] as string + + if (apiKey) { + await this.groupsService.removeGroupWithAPIKey(groupId, apiKey) + } + + if (req.session.adminId) { + await this.groupsService.removeGroupManually( + groupId, + req.session.adminId + ) + } + } + + @Patch() + @UseGuards(AuthGuard) + @ApiBody({ required: false, type: Array }) + @ApiCreatedResponse({ type: Array }) + @ApiHeader({ name: "x-api-key", required: false }) + @ApiOperation({ + description: "Update one or more groups using an API Key or manually." + }) + async updateGroups( + @Headers() headers: Headers, + @Body() groupsIds: Array, + @Body() dtos: Array, + @Req() req: Request + ) { + let groups = [] + const groupsToResponseDTO = [] + + const apiKey = headers["x-api-key"] as string + + if (apiKey) { + groups = await this.groupsService.updateGroupsWithApiKey( + groupsIds, + dtos, + apiKey + ) + } + + if (req.session.adminId) { + groups = await this.groupsService.updateGroupsManually( + groupsIds, + dtos, + req.session.adminId + ) + } + + for await (const group of groups) { + const fingerprint = await this.groupsService.getFingerprint( + group.id + ) + + groupsToResponseDTO.push(mapGroupToResponseDTO(group, fingerprint)) + } + + return groupsToResponseDTO } @Patch(":group") @UseGuards(AuthGuard) - @ApiExcludeEndpoint() + @ApiHeader({ name: "x-api-key", required: false }) + @ApiBody({ required: false, type: UpdateGroupDto }) + @ApiCreatedResponse({ type: Group }) + @ApiOperation({ + description: "Update a specific group using an API Key or manually." + }) async updateGroup( - @Req() req: Request, @Param("group") groupId: string, - @Body() dto: UpdateGroupDto + @Headers() headers: Headers, + @Body() dto: UpdateGroupDto, + @Req() req: Request ) { - const group = await this.groupsService.updateGroup( - groupId, - dto, - req.session.adminId - ) + let group: any + const apiKey = headers["x-api-key"] as string + + if (apiKey) { + group = await this.groupsService.updateGroupWithApiKey( + groupId, + dto, + apiKey + ) + } + + if (req.session.adminId) { + group = await this.groupsService.updateGroupManually( + groupId, + dto, + req.session.adminId + ) + } const fingerprint = await this.groupsService.getFingerprint(groupId) diff --git a/apps/dashboard/src/api/bandadaAPI.ts b/apps/dashboard/src/api/bandadaAPI.ts index 0b80ea3e..874f0342 100644 --- a/apps/dashboard/src/api/bandadaAPI.ts +++ b/apps/dashboard/src/api/bandadaAPI.ts @@ -87,18 +87,20 @@ export async function createGroup( credentials?: any ): Promise { try { - const group = await request(`${API_URL}/groups`, { + const groups = await request(`${API_URL}/groups`, { method: "POST", - data: { - name, - description, - treeDepth, - fingerprintDuration, - credentials: JSON.stringify(credentials) - } + data: [ + { + name, + description, + treeDepth, + fingerprintDuration, + credentials: JSON.stringify(credentials) + } + ] }) - return { ...group, type: "off-chain" } + return { ...groups.at(0), type: "off-chain" } } catch (error: any) { console.error(error) createAlert(error.response.data.message) @@ -169,30 +171,6 @@ export async function updateApiKey( } } -/** - * It updates the detail of a group. - * @param group The group id. - * @param memberId The group member id. - */ -// @todo needs refactoring to support the new logic. -// export async function updateGroup( -// groupId: string, -// { apiEnabled }: { apiEnabled: boolean } -// ): Promise { -// try { -// const group = await request(`${API_URL}/groups/${groupId}`, { -// method: "PATCH", -// data: { apiEnabled } -// }) - -// return { ...group, type: "off-chain" } -// } catch (error: any) { -// console.error(error) -// createAlert(error.response.data.message) -// return null -// } -// } - /** * It removes a group. * @param groupId The group id. diff --git a/libs/api-sdk/src/admins.ts b/libs/api-sdk/src/admins.ts new file mode 100644 index 00000000..03f31da8 --- /dev/null +++ b/libs/api-sdk/src/admins.ts @@ -0,0 +1,68 @@ +import { request } from "@bandada/utils" +import { AdminRequest, AdminResponse, AdminUpdateApiKeyRequest } from "./types" + +const url = "/admins" + +/** + * Create an admin with the provided details. + * @param dto Array of objects containing the details for the admin to be created. + * @returns Array of the created groups. + */ +export async function createAdmin( + config: object, + dto: AdminRequest +): Promise { + const newConfig: any = { + method: "post", + data: { + dto + }, + ...config + } + + return request(url, newConfig) +} + +/** + * Get an admin. + * @param adminId The admin id. + * @returns The admin with given id. + */ +export async function getAdmin( + config: object, + adminId: string +): Promise { + const requestUrl = `${url}/${adminId}` + + const newConfig: any = { + method: "get", + ...config + } + + return request(requestUrl, newConfig) +} + +/** + * Update an admin API key. + * @param adminId The admin id. + * @param dto The action to be executed on the API key. + * @returns The updated API key. + */ +export async function updateApiKey( + config: object, + adminId: string, + dto: AdminUpdateApiKeyRequest +): Promise { + const requestUrl = `${url}/${adminId}/apikey` + + const newConfig: any = { + method: "put", + body: { + adminId, + dto + }, + ...config + } + + return request(requestUrl, newConfig) +} diff --git a/libs/api-sdk/src/apiSdk.ts b/libs/api-sdk/src/apiSdk.ts index b9d925e1..1f254e4b 100644 --- a/libs/api-sdk/src/apiSdk.ts +++ b/libs/api-sdk/src/apiSdk.ts @@ -1,8 +1,22 @@ -import { SupportedUrl, GroupResponse, InviteResponse } from "./types" +import { + SupportedUrl, + GroupResponse, + InviteResponse, + GroupRequest, + GroupUpdateRequest, + AdminRequest, + AdminResponse, + AdminUpdateApiKeyRequest +} from "./types" import checkParameter from "./checkParameter" import { getGroups, getGroup, + createGroups, + removeGroup, + removeGroups, + updateGroup, + updateGroups, isGroupMember, generateMerkleProof, addMemberByApiKey, @@ -11,6 +25,7 @@ import { removeMemberByApiKey, removeMembersByApiKey } from "./groups" +import { createAdmin, getAdmin, updateApiKey } from "./admins" import { getInvite } from "./invites" export default class ApiSdk { @@ -64,6 +79,43 @@ export default class ApiSdk { return this._config } + /** + * Create an admin. + * @param dto The data of the admin. + * @returns Specific admin. + */ + async createAdmin(dto: AdminRequest): Promise { + const admin = await createAdmin(this._config, dto) + + return admin + } + + /** + * Get the admin with given id. + * @param adminId The admin id. + * @returns Specific admin. + */ + async getAdmin(adminId: string): Promise { + const admin = await getAdmin(this._config, adminId) + + return admin + } + + /** + * Update an admin API key. + * @param adminId The admin id. + * @param dto The action to be executed on the API key. + * @returns The updated API key. + */ + async updateApiKey( + adminId: string, + dto: AdminUpdateApiKeyRequest + ): Promise { + const apiKey = await updateApiKey(this._config, adminId, dto) + + return apiKey + } + /** * Returns the list of groups. * @returns List of groups. @@ -74,6 +126,76 @@ export default class ApiSdk { return groups } + /** + * Creates one or more groups using the API key. + * @param dtos The data of one or more groups. + * @param apiKey The API key of the admin of the group. + * @returns Specific group. + */ + async createGroups( + dtos: Array, + apiKey: string + ): Promise> { + const groups = await createGroups(this._config, dtos, apiKey) + + return groups + } + + /** + * Removes a group using the API key. + * @param groupId The group id. + * @param apiKey The API key of the admin of the group. + */ + async removeGroup(groupId: string, apiKey: string): Promise { + return removeGroup(this._config, groupId, apiKey) + } + + /** + * Removes one or more group using the API key. + * @param groupsIds The groups ids. + * @param apiKey The API key of the admin of the group. + */ + async removeGroups( + groupsIds: Array, + apiKey: string + ): Promise { + return removeGroups(this._config, groupsIds, apiKey) + } + + /** + * Update a specific group using the API key. + * @param groupId The group id. + * @param dto The data to update for the group. + * @param apiKey The API key of the admin of the group. + * @returns Updated specific group. + */ + async updateGroup( + groupId: string, + dto: GroupUpdateRequest, + apiKey: string + ): Promise { + const group = await updateGroup(this._config, groupId, dto, apiKey) + + return group + } + + /** + * Updats one or more groups using the API key. + * @param groupsIds The groups ids. + * @param dtos The data to update for the groups. + * @param apiKey The API key of the admin of the group. + * @returns Updated specific groups. + */ + async updateGroups( + groupsIds: Array, + dtos: Array, + apiKey: string + ): Promise> { + const groups = await updateGroups(this._config, groupsIds, dtos, apiKey) + + return groups + } + /** * Returns a specific group. * @param groupId Group id. diff --git a/libs/api-sdk/src/groups.ts b/libs/api-sdk/src/groups.ts index b8bcaa30..3299bbaf 100644 --- a/libs/api-sdk/src/groups.ts +++ b/libs/api-sdk/src/groups.ts @@ -1,5 +1,5 @@ import { request } from "@bandada/utils" -import { GroupResponse } from "./types" +import { GroupRequest, GroupResponse, GroupUpdateRequest } from "./types" const url = "/groups" @@ -18,6 +18,147 @@ export async function getGroups(config: object): Promise { return groups } +/** + * Creates one or more groups with the provided details. + * @param dtos Array of objects containing the details for the groups to be created. + * @param apiKey API Key of the admin. + * @returns Array of the created groups. + */ +export async function createGroups( + config: object, + dtos: Array, + apiKey: string +): Promise> { + const newConfig: any = { + method: "post", + data: { + dtos + }, + ...config + } + + newConfig.headers["x-api-key"] = apiKey + + const req = await request(url, newConfig) + + return req +} + +/** + * Removes the group. + * @param groupId The group id. + * @param apiKey API Key of the admin. + */ +export async function removeGroup( + config: object, + groupId: string, + apiKey: string +): Promise { + const requestUrl = `${url}/${groupId}` + + const newConfig: any = { + method: "delete", + data: { + apiKey + }, + ...config + } + + newConfig.headers["x-api-key"] = apiKey + + const req = await request(requestUrl, newConfig) + + return req +} + +/** + * Removes one or more groups. + * @param groupsIds The groups ids. + * @param apiKey API Key of the admin. + */ +export async function removeGroups( + config: object, + groupsIds: Array, + apiKey: string +): Promise { + const newConfig: any = { + method: "delete", + data: { + groupsIds, + apiKey + }, + ...config + } + + newConfig.headers["x-api-key"] = apiKey + + const req = await request(url, newConfig) + + return req +} + +/** + * Updates the group. + * @param groupId The group id. + * @param dto The data to update for the group. + * @param apiKey API Key of the admin. + * @return The updated group. + */ +export async function updateGroup( + config: object, + groupId: string, + dto: GroupUpdateRequest, + apiKey: string +): Promise { + const requestUrl = `${url}/${groupId}` + + const newConfig: any = { + method: "put", + data: { + groupId, + dto, + apiKey + }, + ...config + } + + newConfig.headers["x-api-key"] = apiKey + + const req = await request(requestUrl, newConfig) + + return req +} + +/** + * Updates the groups. + * @param groupsIds The groups ids. + * @param dtos The data to update for the groups. + * @param apiKey API Key of the admin. + * @return The updated groups. + */ +export async function updateGroups( + config: object, + groupsIds: Array, + dtos: Array, + apiKey: string +): Promise> { + const newConfig: any = { + method: "put", + data: { + groupsIds, + dtos, + apiKey + }, + ...config + } + + newConfig.headers["x-api-key"] = apiKey + + const req = await request(url, newConfig) + + return req +} + /** * Returns a specific group. * @param groupId Group id. diff --git a/libs/api-sdk/src/index.test.ts b/libs/api-sdk/src/index.test.ts index ed0ddba8..318d047e 100644 --- a/libs/api-sdk/src/index.test.ts +++ b/libs/api-sdk/src/index.test.ts @@ -1,11 +1,25 @@ -import { request } from "@bandada/utils" +import { request, ApiKeyActions } from "@bandada/utils" import ApiSdk from "./apiSdk" -import { GroupResponse, InviteResponse, SupportedUrl } from "./types" +import { + AdminRequest, + AdminResponse, + AdminUpdateApiKeyRequest, + GroupRequest, + GroupResponse, + GroupUpdateRequest, + InviteResponse, + SupportedUrl +} from "./types" -jest.mock("@bandada/utils", () => ({ - __esModule: true, - request: jest.fn() -})) +jest.mock("@bandada/utils", () => { + const originalModule = jest.requireActual("@bandada/utils") + + return { + __esModule: true, + ...originalModule, + request: jest.fn() + } +}) const requestMocked = request as jest.MockedFunction @@ -68,7 +82,348 @@ describe("Bandada API SDK", () => { expect(apiSdk.url).toBe(SupportedUrl.DEV) }) }) + describe("Admins", () => { + describe("#createAdmin", () => { + it("Should create an admin", async () => { + const expectedAdmin: AdminRequest = { + id: "1", + address: + "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847" + } + + requestMocked.mockImplementationOnce(() => + Promise.resolve({ + id: "0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", + address: + "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + username: + "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + createdAt: "2024-03-28T20:45:53.142Z", + apiKey: null, + apiEnabled: false, + updatedAt: "2024-03-28T20:45:53.000Z" + }) + ) + + apiSdk = new ApiSdk(SupportedUrl.DEV) + const admin: AdminResponse = await apiSdk.createAdmin( + expectedAdmin + ) + + expect(admin.id).toBeDefined() + expect(admin.username).toBe(expectedAdmin.address) + expect(admin.address).toBe(expectedAdmin.address) + expect(admin.apiKey).toBeNull() + expect(admin.apiEnabled).toBeFalsy() + expect(admin.createdAt).toBeDefined() + expect(admin.updatedAt).toBeDefined() + }) + }) + describe("#getAdmin", () => { + it("Should return an admin", async () => { + const adminId = + "0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6" + const expectedAdmin: AdminResponse = { + id: "0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", + address: + "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + username: + "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + apiKey: "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc", + apiEnabled: true + } + + requestMocked.mockImplementationOnce(() => + Promise.resolve({ + id: "0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", + address: + "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + username: + "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + apiKey: "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc", + apiEnabled: true, + createdAt: "2024-03-28T20:45:53.000Z", + updatedAt: "2024-03-28T20:45:53.000Z" + }) + ) + + apiSdk = new ApiSdk(SupportedUrl.DEV) + const admin: AdminResponse = await apiSdk.getAdmin(adminId) + + expect(admin.id).toBeDefined() + expect(admin.username).toBe(expectedAdmin.address) + expect(admin.address).toBe(expectedAdmin.address) + expect(admin.apiKey).toBe(expectedAdmin.apiKey) + expect(admin.apiEnabled).toBe(expectedAdmin.apiEnabled) + expect(admin.createdAt).toBeDefined() + expect(admin.updatedAt).toBeDefined() + }) + }) + describe("#updateApiKey", () => { + it("Should update the api key", async () => { + const adminId = + "0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6" + const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + const action: AdminUpdateApiKeyRequest = { + action: ApiKeyActions.Generate + } + + requestMocked.mockImplementationOnce(() => + Promise.resolve(apiKey) + ) + + apiSdk = new ApiSdk(SupportedUrl.DEV) + const updatedApiKey: string = await apiSdk.updateApiKey( + adminId, + action + ) + + expect(updatedApiKey).toBe(apiKey) + }) + }) + }) describe("Groups", () => { + describe("#createGroup", () => { + it("Should create a group", async () => { + const expectedGroup: GroupRequest = { + id: "10402173435763029700781503965100", + name: "Group1", + description: "This is a new group", + treeDepth: 16, + fingerprintDuration: 3600 + } + const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + + 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 + } + ]) + ) + + apiSdk = new ApiSdk(SupportedUrl.DEV) + const groups: Array = await apiSdk.createGroups( + [expectedGroup], + apiKey + ) + const group = groups.at(0)! + + expect(group.id).toBe(expectedGroup.id) + expect(group.description).toBe(expectedGroup.description) + expect(group.name).toBe(expectedGroup.name) + expect(group.treeDepth).toBe(expectedGroup.treeDepth) + expect(group.fingerprintDuration).toBe( + group.fingerprintDuration + ) + expect(group.members).toHaveLength(0) + expect(group.credentials).toBeNull() + }) + }) + describe("#createGroups", () => { + it("Should create the groups", async () => { + const expectedGroups: Array = [ + { + id: "10402173435763029700781503965100", + name: "Group1", + description: "This is a new group", + treeDepth: 16, + fingerprintDuration: 3600 + }, + { + id: "20402173435763029700781503965200", + name: "Group2", + description: "This is a new group", + treeDepth: 32, + fingerprintDuration: 7200 + } + ] + const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + + 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 + }, + { + id: "20402173435763029700781503965200", + name: "Group2", + description: "This is a new group", + admin: "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + treeDepth: 32, + fingerprintDuration: 7200, + createdAt: "2023-07-15T08:21:05.000Z", + members: [], + credentials: null + } + ]) + ) + + apiSdk = new ApiSdk(SupportedUrl.DEV) + const groups: Array = await apiSdk.createGroups( + [expectedGroups[0], expectedGroups[1]], + apiKey + ) + + groups.forEach((group: GroupResponse, i: number) => { + expect(group.id).toBe(expectedGroups[i].id) + expect(group.description).toBe( + expectedGroups[i].description + ) + expect(group.name).toBe(expectedGroups[i].name) + expect(group.treeDepth).toBe(expectedGroups[i].treeDepth) + expect(group.fingerprintDuration).toBe( + group.fingerprintDuration + ) + expect(group.members).toHaveLength(0) + expect(group.credentials).toBeNull() + }) + }) + }) + describe("#removeGroup", () => { + it("Should create a group", async () => { + const groupId = "10402173435763029700781503965100" + const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + + requestMocked.mockImplementationOnce(() => Promise.resolve()) + + apiSdk = new ApiSdk(SupportedUrl.DEV) + const res = await apiSdk.removeGroup(groupId, apiKey) + expect(res).toBeUndefined() + }) + }) + describe("#removeGroups", () => { + it("Should create a group", async () => { + const groupsIds = [ + "10402173435763029700781503965100", + "20402173435763029700781503965200" + ] + const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + + requestMocked.mockImplementationOnce(() => Promise.resolve()) + + apiSdk = new ApiSdk(SupportedUrl.DEV) + const res = await apiSdk.removeGroups(groupsIds, apiKey) + expect(res).toBeUndefined() + }) + }) + describe("#updateGroup", () => { + it("Should update a group", async () => { + const groupId = "10402173435763029700781503965100" + const updatedGroup: GroupUpdateRequest = { + description: "This is a new group", + treeDepth: 16, + fingerprintDuration: 3600 + } + const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + + 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 + }) + ) + + apiSdk = new ApiSdk(SupportedUrl.DEV) + const group: GroupResponse = await apiSdk.updateGroup( + groupId, + updatedGroup, + apiKey + ) + + expect(group.description).toBe(updatedGroup.description) + expect(group.treeDepth).toBe(updatedGroup.treeDepth) + expect(group.fingerprintDuration).toBe( + updatedGroup.fingerprintDuration + ) + }) + }) + describe("#updateGroups", () => { + it("Should update some groups", async () => { + const groupsIds = [ + "10402173435763029700781503965100", + "20402173435763029700781503965200" + ] + const updatedGroups: Array = [ + { + description: "This is a new group1", + treeDepth: 32, + fingerprintDuration: 7200 + }, + { + description: "This is a new group2", + treeDepth: 32, + fingerprintDuration: 7200 + } + ] + const apiKey = "70f07d0d-6aa2-4fe1-b4b9-06c271a641dc" + + requestMocked.mockImplementationOnce(() => + Promise.resolve([ + { + id: "10402173435763029700781503965100", + name: "Group1", + description: "This is a new group1", + admin: "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + treeDepth: 32, + fingerprintDuration: 7200, + createdAt: "2023-07-15T08:21:05.000Z", + members: [], + credentials: null + }, + { + id: "20402173435763029700781503965200", + name: "Group1", + description: "This is a new group2", + admin: "0xdf558148e66850ac48dbe2c8119b0eefa7d08bfd19c997c90a142eb97916b847", + treeDepth: 32, + fingerprintDuration: 7200, + createdAt: "2023-07-15T08:21:05.000Z", + members: [], + credentials: null + } + ]) + ) + + apiSdk = new ApiSdk(SupportedUrl.DEV) + const groups: Array = await apiSdk.updateGroups( + groupsIds, + updatedGroups, + apiKey + ) + + groups.forEach((group: GroupResponse, i: number) => { + expect(group.description).toBe(updatedGroups[i].description) + expect(group.treeDepth).toBe(updatedGroups[i].treeDepth) + expect(group.fingerprintDuration).toBe( + updatedGroups[i].fingerprintDuration + ) + }) + }) + }) describe("#getGroups", () => { it("Should return all groups", async () => { requestMocked.mockImplementationOnce(() => diff --git a/libs/api-sdk/src/types/index.ts b/libs/api-sdk/src/types/index.ts index 18c6f724..6b86d090 100644 --- a/libs/api-sdk/src/types/index.ts +++ b/libs/api-sdk/src/types/index.ts @@ -1,3 +1,5 @@ +import { ApiKeyActions } from "@bandada/utils" + export type GroupResponse = { id: string name: string @@ -14,6 +16,48 @@ export type GroupResponse = { } } +export type GroupRequest = { + name: string + description: string + treeDepth: number + fingerprintDuration: number + id?: string + credentials?: { + id: string + criteria: Record + } +} + +export type GroupUpdateRequest = { + description: string + treeDepth: number + fingerprintDuration: number + credentials?: { + id: string + criteria: Record + } +} + +export type AdminRequest = { + id: string + address: string + username?: string +} + +export type AdminResponse = { + id: string + address: string + username: string + apiKey: string + apiEnabled: boolean + createdAt?: Date + updatedAt?: Date +} + +export type AdminUpdateApiKeyRequest = { + action: ApiKeyActions +} + type Group = { id: string name: string