diff --git a/src/data/db/find.ts b/src/data/db/find.ts index 8ca1f6c..75417fb 100644 --- a/src/data/db/find.ts +++ b/src/data/db/find.ts @@ -93,6 +93,12 @@ export async function findClaimCode(code: string): Promise { }); } + +/** + * This function finds a gateway identity in the database + * @param {string} identity - The identity of the user to find + * @returns {Promise} - The gateway identity, if found + */ export async function findGatewayByIdentity(identity: string): Promise { return await prisma.gateWayIdentity.findFirst({ where: { @@ -120,6 +126,12 @@ export async function findUpdatedRooms(roomIds: string[]): Promise { }); } +/** + * This function finds a room with a message id + * @param {string} roomId - The id of the room to find + * @param {MessageI} message - The message id to find + * @returns {Promise} - A promise that resolves to a message + */ export async function findRoomWithMessageId( roomId: string, message: MessageI @@ -154,7 +166,12 @@ export async function findRoomWithMessageId( } } -export async function findAllJubmojiNullifiers() { + +/** + * This function finds all the used jubmoji nullifiers in the db + * @returns {Promise} - A promise that resolves to a list of used sig nullifiers + */ +export async function findAllJubmojiNullifiers(): Promise { const jubmojiNullifiers: Jubmojis[] = await prisma.gateWayIdentity.findMany({ select: { jubmoji: true diff --git a/src/data/db/remove.ts b/src/data/db/remove.ts index 8aff204..0d1141d 100644 --- a/src/data/db/remove.ts +++ b/src/data/db/remove.ts @@ -49,7 +49,6 @@ export function removeIdentityFromRoom( * @param {string} roomId - The id of the room to remove * @returns {Promise} - A promise that resolves to true if the room was removed and false otherwise * */ - export function removeRoom(roomId: string): Promise { return prisma.messages .deleteMany({ @@ -82,7 +81,6 @@ export function removeRoom(roomId: string): Promise { * @param {string} messageId - The id of the message to remove * @returns {Promise} - A promise that resolves to true if the message was removed and false otherwise */ - export function removeMessage(roomId: string, messageId: string) { return prisma.messages .deleteMany({ diff --git a/src/data/db/update.ts b/src/data/db/update.ts index 0c1a358..3f9b4c5 100644 --- a/src/data/db/update.ts +++ b/src/data/db/update.ts @@ -303,7 +303,6 @@ export async function addIdentityToBandadaRooms( * @param {string} roomId - The ID of the room * @param {string[]} ethAddresses - The list of Ethereum addresses to add to the group */ - export async function createEthGroup( name: string, roomId: string, diff --git a/src/data/messages.ts b/src/data/messages.ts index cd7f15e..114f21b 100644 --- a/src/data/messages.ts +++ b/src/data/messages.ts @@ -19,6 +19,12 @@ type EphemeralMessagesI = Record; const ephemeralMessageStore: EphemeralMessagesI = {}; +/** + * This code checks the ephemeral message store for a collision. + * @param {string} roomId - The ID of the room to check for collisions in + * @param {MessageI} message - The message to be added to the room + * @returns {MessageI | null} - Returns the old message if there is a collision, and null otherwise + */ function checkEmphemeralStore(roomId: string, message: MessageI): MessageI | null { // Check ephemeralMessages const epoch = message.epoch?.toString(); @@ -34,6 +40,11 @@ function checkEmphemeralStore(roomId: string, message: MessageI): MessageI | nul return null; } +/** + * This code adds a message to the ephemeral message store. + * @param {string} roomId - The ID of the room to add the message to + * @param {MessageI} message - The message to add to the room + */ function addMessageToEphemeralStore(roomId: string, message: MessageI) { const currentEpoch = String(message.epoch); @@ -137,6 +148,13 @@ export interface validateMessageResult { idc?: string | bigint; } +/** + * This code handles the collision check result and adds the message to the room if there is no collision. + * @param {RoomI} room - The room which the message will be added + * @param {MessageI} message - The message to be created + * @param {CollisionCheckResult} collisionResult - The result of the collision check + * @returns {Promise} - A result object which contains a boolean indicating whether the operation was successful + */ async function handleCollision( room: RoomI, message: MessageI, diff --git a/src/endpoints/gateways/discord.ts b/src/endpoints/gateways/discord.ts index 8c6a51d..1955e23 100644 --- a/src/endpoints/gateways/discord.ts +++ b/src/endpoints/gateways/discord.ts @@ -16,7 +16,7 @@ const discordPassword = process.env.DISCORD_PASSWORD const adminAuth = basicAuth({ users: { - discordAdmin: discordPassword + admin: discordPassword } }); @@ -152,7 +152,6 @@ router.post( filteredRooms.push(...newRooms); filteredNames.push(...(newRoomNames as string[])); } - console.log(filteredRooms); res.status(200).json({ rooms: filteredRooms, roomNames: filteredNames }); } else { const roomIds: string[] = []; @@ -193,7 +192,6 @@ router.post( */ router.post('/rooms', limiter, adminAuth, (req, res) => { const { discordUserId } = req.body as { discordUserId: string }; - console.log('here'); prisma.gateWayIdentity .findFirst({ where: { diff --git a/src/endpoints/gateways/ethereumGroup.ts b/src/endpoints/gateways/ethereumGroup.ts index 85c5f96..9649c23 100644 --- a/src/endpoints/gateways/ethereumGroup.ts +++ b/src/endpoints/gateways/ethereumGroup.ts @@ -25,9 +25,11 @@ const adminAuth = basicAuth({ } }); + const router = express.Router(); const prisma = new PrismaClient(); + // Fetches all ethereum groups that exist in the database router.get('/groups/all', adminAuth, (req: Request, res: Response) => { prisma.ethereumGroup @@ -67,7 +69,7 @@ router.get('/group/:address', limiter, (req, res) => { } }) .then((groups) => { - res.status(200).json(groups); + res.status(200).json({status: 'valid', groups: groups}); }) .catch((err) => { console.error(err); @@ -95,15 +97,21 @@ router.post( name: string; roomIds: string[]; }; - const ethereumGroup = await prisma.ethereumGroup.create({ - data: { - name: name, - rooms: { - connect: roomIds.map((roomId) => ({ roomId })) + if (!name) res.status(400).json({ success: false, message: 'Missing name' }); + try { + const ethereumGroup = await prisma.ethereumGroup.create({ + data: { + name: name, + rooms: { + connect: roomIds.map((roomId) => ({ roomId })) + } } - } - }); - res.json({ success: true, ethereumGroup }); + }); + res.status(200).json({ success: true, message: 'Ethereum group created', ethereumGroup }); + } catch (err) { + console.error(err); + res.status(500).json({ success: false, error: 'Internal Server Error' }); + } }) ); @@ -119,7 +127,7 @@ router.post( names: string[]; ethAddresses: string[]; }; - if (!names) return; + if (!names) res.status(400).json({ success: false, message: 'Missing group names' }); const groups = await prisma.ethereumGroup.updateMany({ where: { name: { @@ -132,7 +140,7 @@ router.post( } } }); - res.json({ success: true, groups }); + res.status(200).json({ success: true, groups }); }) ); @@ -210,7 +218,7 @@ router.post('/group/delete', adminAuth, (req, res) => { } }) .then((group) => { - res.status(200).json(group); + res.status(200).json({ success: true, group }); }) .catch((err) => { console.error(err); @@ -231,7 +239,7 @@ router.post('/group/delete', adminAuth, (req, res) => { * } */ router.post( - '/join', + '/message/sign', limiter, asyncHandler(async (req: Request, res: Response) => { const { message, signature } = req.body as { diff --git a/src/gateways/theWord/verifier.ts b/src/gateways/theWord/verifier.ts index 5414209..13c951d 100644 --- a/src/gateways/theWord/verifier.ts +++ b/src/gateways/theWord/verifier.ts @@ -2,7 +2,11 @@ import { groth16 } from 'snarkjs'; import vkey from './vkey'; import { SNARKProof } from 'idc-nullifier'; - +/** + * This function verifies a proof generated by theWord. + * @param {SNARKProof} proof - The proof to verify + * @returns {Promise} - A promise that resolves to true if the proof is valid and false otherwise + */ export async function verifyTheWordProof(proof: SNARKProof): Promise { const isValid = groth16.verify(vkey, proof.publicSignals, proof.proof); diff --git a/tests/discreetly.test.ts b/tests/discreetly.test.ts index ab1c382..51f5e5e 100644 --- a/tests/discreetly.test.ts +++ b/tests/discreetly.test.ts @@ -7,7 +7,7 @@ import { beforeAll, afterAll, describe, expect, test } from '@jest/globals'; import { randomRoomName } from './utils'; import { generateIdentityProof } from '../src/crypto/idcVerifier/verifier'; import { Identity } from '@semaphore-protocol/identity'; -import { doesNotReject } from 'assert'; + process.env.DATABASE_URL = process.env.DATABASE_URL_TEST; process.env.PORT = '3001'; @@ -33,17 +33,23 @@ const messageTestRoom = { roomId: CUSTOM_ID }; +let testEthAddress = '0x123123123'; + let roomByIdTest: string; let testCode: string; const testIdentity = new Identity(); +console.log('identity', testIdentity); const username = 'admin'; const password = process.env.PASSWORD; +const discordPassword = process.env.DISCORD_PASSWORD beforeAll(async () => { const prismaTest = new PrismaClient(); await prismaTest.messages.deleteMany(); await prismaTest.rooms.deleteMany(); await prismaTest.claimCodes.deleteMany(); + await prismaTest.ethereumGroup.deleteMany(); + await prismaTest.gateWayIdentity.deleteMany(); }); afterAll(async () => { @@ -57,14 +63,18 @@ describe('Endpoints', () => { .get('/') .then((res) => { expect(res.status).toBe(200); - expect(res.header['content-type']).toBe('application/json; charset=utf-8'); + expect(res.header['content-type']).toBe( + 'application/json; charset=utf-8' + ); expect(res.body.id).toBe(serverConfig.id); }) .catch((error) => console.error("GET '/' - " + error)); }); test('It should add a new room to the database', async () => { - const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64'); + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); await request(_app) .post('/room/add') .set('Authorization', `Basic ${base64Credentials}`) @@ -84,11 +94,20 @@ describe('Endpoints', () => { .catch((error) => console.warn('POST /room/add - ' + error)); }); test('It should create claimCode for the new room', async () => { - const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64'); + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); await request(_app) .post(`/admin/addcode`) .set('Authorization', `Basic ${base64Credentials}`) - .send({ numCodes: 1, rooms: [roomByIdTest], all: false, expiresAt: 0, usesLeft: -1 }) + .send({ + numCodes: 1, + rooms: [roomByIdTest], + all: false, + expiresAt: 0, + usesLeft: -1, + discordId: '53125497960' + }) .then((res) => { try { console.log(res.body); @@ -102,7 +121,9 @@ describe('Endpoints', () => { }); test('It should add a new room with a custom id to the database', async () => { - const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64'); + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); await request(_app) .post('/room/add') .set('Authorization', `Basic ${base64Credentials}`) @@ -122,7 +143,9 @@ describe('Endpoints', () => { }); test('It shouldnt add a new room with the same ID', async () => { - const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64'); + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); await request(_app) .post('/room/add') .set('Authorization', `Basic ${base64Credentials}`) @@ -130,10 +153,8 @@ describe('Endpoints', () => { .then((res) => { try { - console.log(res.status); expect(res.status).toEqual(400); const result = res.body; - console.warn(result); } catch (error) { console.warn('POST /room/add - ' + error); } @@ -148,6 +169,13 @@ describe('Endpoints', () => { try { expect(res.status).toEqual(200); expect(res.body.name).toEqual(room.roomName); + expect(res.body.roomId).toEqual(roomByIdTest); + expect(res.body.rateLimit).toEqual(1000); + expect(res.body.userMessageLimit).toEqual(1); + expect(res.body.membershipType).toEqual('IDENTITY_LIST') + expect(res.body.ephemeral).toEqual('PERSISTENT') + expect(res.body.encrypted).toEqual('PLAINTEXT'); + expect(res.body.identities.length).toBeGreaterThan(0); } catch (error) { console.error(`GET /api/room/:roomId - + ${error}`); } @@ -170,7 +198,9 @@ describe('Endpoints', () => { }); test('It should return all rooms', async () => { - const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64'); + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); await request(_app) .get('/admin/rooms') @@ -188,7 +218,9 @@ describe('Endpoints', () => { }); test("It should return all claim codes and add a user's identity to the rooms the claim code is associated with", async () => { - const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64'); + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); await request(_app) .get('/admin/logclaimcodes') @@ -224,7 +256,7 @@ describe('Endpoints', () => { let proof = await generateIdentityProof(testIdentity, BigInt(Date.now())); await request(_app) - .get(`/identity/${testIdentity.getCommitment().toString()}`) + .post(`/identity/${testIdentity.getCommitment().toString()}`) .send(proof) .then((res) => { try { @@ -240,7 +272,9 @@ describe('Endpoints', () => { const message = { message: 'Test message' }; - const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64'); + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); await request(_app) .post('/admin/message') .set('Authorization', `Basic ${base64Credentials}`) @@ -269,6 +303,107 @@ describe('Endpoints', () => { .catch((error) => console.error('GET /api/messages/:roomId - ' + error)); }); + test('It should create a new Ethereum group', async () => { + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); + await request(_app) + .post('/gateway/eth/group/create') + .set('Authorization', `Basic ${base64Credentials}`) + .send({ name: 'EthGroup-Test', roomIds: [roomByIdTest] }) + .then((res) => { + try { + expect(res.statusCode).toEqual(200); + expect(res.body.message).toEqual('Ethereum group created'); + } catch (error) { + console.error('POST /gateway/eth/group/create - ' + error); + } + }); + }); + + test('It should return all of the Ethereum Groups', async () => { + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); + await request(_app) + .get(`/gateway/eth/groups/all`) + .set('Authorization', `Basic ${base64Credentials}`) + .then((res) => { + try { + expect(res.statusCode).toEqual(200); + expect(res.body.length).toBeGreaterThan(0); + } catch (error) { + console.error('GET /gateway/eth/groups/all - ' + error); + } + }); + }); + + test('It should add Eth addresses to a group', async () => { + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); + await request(_app) + .post(`/gateway/eth/group/add`) + .set('Authorization', `Basic ${base64Credentials}`) + .send({ names: ['EthGroup-Test'], ethAddresses: [testEthAddress] }) + .then((res) => { + try { + expect(res.statusCode).toEqual(200); + expect(res.body.success).toEqual(true) + } catch (err) { + console.error('POST /gateway/eth/group/add - ' + err); + } + }); + }); + test('It should return return the Groups the Ethereum Address is in', async () => { + await request(_app) + .get(`/gateway/eth/group/${testEthAddress}`) + .then((res) => { + try { + expect(res.statusCode).toEqual(200); + expect(res.body.status).toEqual('valid'); + } catch (err) { + console.error('GET /gateway/eth/group/:address -' + err) + } + }) + }) + test('It should edit an Ethereum Group to add Eth addresses and roomIds', async () => { + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); + await request(_app) + .post('/gateway/eth/group/edit') + .set('Authorization', `Basic ${base64Credentials}`) + .send({name: 'EthGroup-Test', ethAddresses: ['0x321321321'], roomIds: []}) + .then((res) => { + try { + expect(res.statusCode).toEqual(200) + expect(res.body.success).toEqual(true) + expect(res.body.updatedGroup.ethereumAddresses.length).toBeGreaterThan(1) + } catch (err) { + console.error('POST /gateway/eth/group/edit - ' + err) + } + }) + }) + + test('It should delete an Ethereum Group', async () => { + const base64Credentials = Buffer.from(`${username}:${password}`).toString( + 'base64' + ); + await request(_app) + .post('/gateway/eth/group/delete') + .set('Authorization', `Basic ${base64Credentials}`) + .send({ name: 'EthGroup-Test' }) + .then((res) => { + try { + expect(res.statusCode).toEqual(200) + expect(res.body.success).toEqual(true) + } catch (err) { + console.error('DELETE /gateway/eth/group/delete - ' + err) + } + }) + }) + describe('Messages', () => { let testRoom: RoomI; @@ -287,4 +422,83 @@ describe('Endpoints', () => { expect(1).toBe(1); }); }); + + describe('Discord', () => { + test('It should add roles to a Discord Role mapping', async () => { + const base64Credentials = Buffer.from(`${username}:${discordPassword}`).toString('base64') + await request(_app) + .post('/gateway/discord/addrole') + .set('Authorization', `Basic ${base64Credentials}`) + .send({ + roles: ['12345', '67890'], + roomId: roomByIdTest, + guildId: '87128718167878' + }) + .then((res) => { + try { + expect(res.body.message).toEqual('Discord roles added successfully') + } catch (error) { + console.error(`POST /gateway/discord/addrole - ${error}`) + } + }) + }) + test('It should add a Discord Server to the database', async () => { + const base64Credentials = Buffer.from(`${username}:${discordPassword}`).toString('base64') + await request(_app) + .post('/gateway/discord/addguild') + .set('Authorization', `Basic ${base64Credentials}`) + .send({guildId: '87128718167878'}) + .then((res) => { + try { + expect(res.body.message).toEqual('Discord guild added successfully') + } catch (error) { + console.error(`POST /gateway/discord/addguild - ${error}`) + } + }) + }) + test('It should get the rooms associated with a Discord Role mapping', async () => { + const base64Credentials = Buffer.from(`${username}:${discordPassword}`).toString('base64') + await request(_app) + .post('/gateway/discord/getrooms') + .set('Authorization', `Basic ${base64Credentials}`) + .send({roles: ['12345', '67890'], discordId: '53125497960'}) + .then((res) => { + try { + expect(res.body.rooms.length).toBeGreaterThan(0) + } catch (error) { + console.error(`GET /gateway/discord/getrooms - ${error}`) + } + }) + }) + + test('It should get the rooms associated with the discordId', async () => { + const base64Credentials = Buffer.from(`${username}:${discordPassword}`).toString('base64') + await request(_app) + .post('/gateway/discord/rooms') + .set('Authorization', `Basic ${base64Credentials}`) + .send({ discordUserId: '53125497960' }) + .then((res) => { + try { + expect(res.body.rooms.length).toBeGreaterThan(0) + } catch (error) { + console.error(`POST /gateway/discord/rooms - ${error}`) + } + }) + }) + + test('It should get the room mappings for a Discord Server ID', async () => { + const base64Credentials = Buffer.from(`${username}:${discordPassword}`).toString('base64') + await request(_app) + .post('/gateway/discord/checkrooms') + .set('Authorization', `Basic ${base64Credentials}`) + .send({ discordId: '87128718167878' }) + .then((res) => { + try { + expect(res.body.length).toBeGreaterThan(0) + } catch (error) { + console.error(`POST /gateway/discord/checkrooms - ${error}`) + } + }) + }) + }) });