diff --git a/twake/backend/node/test/e2e/application/app-create-update.spec.ts b/twake/backend/node/test/e2e/application/app-create-update.spec.ts deleted file mode 100644 index 8b26d40a..00000000 --- a/twake/backend/node/test/e2e/application/app-create-update.spec.ts +++ /dev/null @@ -1,351 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { TestDbService } from "../utils.prepare.db"; -import { Api } from "../utils.api"; -import Application, { - PublicApplicationObject, -} from "../../../src/services/applications/entities/application"; -import { cloneDeep } from "lodash"; - -import { logger as log } from "../../../src/core/platform/framework"; -import { v1 as uuidv1 } from "uuid"; - -describe("Applications", () => { - const url = "/internal/services/applications/v1"; - - let platform: TestPlatform; - let testDbService: TestDbService; - let api: Api; - let appRepo; - - beforeAll(async ends => { - platform = await init(); - await platform.database.getConnector().drop(); - testDbService = await TestDbService.getInstance(platform, true); - await testDbService.createDefault(); - postPayload.company_id = platform.workspace.company_id; - api = new Api(platform); - appRepo = await testDbService.getRepository("application", Application); - ends(); - }); - - afterAll(done => { - platform.tearDown().then(() => done()); - }); - - const publishApp = async id => { - const entity = await appRepo.findOne({ id }); - if (!entity) throw new Error(`entity ${id} not found`); - entity.publication.published = true; - await appRepo.save(entity); - }; - - describe("Create application", function () { - it("should 403 if creator is not a company admin", async done => { - const payload = { resource: cloneDeep(postPayload) }; - - const user = await testDbService.createUser([testDbService.defaultWorkspace()], { - companyRole: "member", - }); - - const response = await api.post(`${url}/applications`, payload, user.id); - expect(response.statusCode).toBe(403); - done(); - }); - - it("should 200 on application create", async done => { - const payload = { resource: cloneDeep(postPayload) }; - const response = await api.post(`${url}/applications`, payload); - expect(response.statusCode).toBe(200); - - const r = response.resource; - - expect(r.company_id).toBe(payload.resource.company_id); - expect(!!r.is_default).toBe(false); - expect(r.identity).toMatchObject(payload.resource.identity); - expect(r.access).toMatchObject(payload.resource.access); - expect(r.display).toMatchObject(payload.resource.display); - expect(r.publication).toMatchObject(payload.resource.publication); - expect(r.stats).toMatchObject({ - created_at: expect.any(Number), - updated_at: expect.any(Number), - version: 0, - }); - - expect(r.api).toMatchObject({ - hooks_url: payload.resource.api.hooks_url, - allowed_ips: payload.resource.api.allowed_ips, - private_key: expect.any(String), - }); - - expect(r.api.private_key).not.toBe(""); - - const dbData = await appRepo.findOne({ id: response.resource.id }); - - expect(dbData.api).toMatchObject({ - allowed_ips: payload.resource.api.allowed_ips, - hooks_url: payload.resource.api.hooks_url, - private_key: expect.any(String), - }); - - done(); - }); - }); - describe("Update application", function () { - let createdApp: PublicApplicationObject; - - beforeAll(async done => { - const payload = { resource: cloneDeep(postPayload) }; - const response = await api.post(`${url}/applications`, payload); - createdApp = response.resource; - - done(); - }); - - it("should 403 if editor is not a company admin", async done => { - if (!createdApp) throw new Error("can't find created app"); - log.debug(createdApp); - - const user = await testDbService.createUser([testDbService.defaultWorkspace()], { - companyRole: "member", - }); - - const response = await api.post(`${url}/applications/${createdApp.id}`, postPayload, user.id); - expect(response.statusCode).toBe(403); - done(); - }); - - it("should 404 if application not found", async done => { - const response = await api.post(`${url}/applications/${uuidv1()}`, { resource: postPayload }); - expect(response.statusCode).toBe(404); - done(); - }); - - describe("Unpublished application", () => { - it("should 200 on application update", async done => { - const payload = { resource: cloneDeep(postPayload) }; - - payload.resource.is_default = true; - payload.resource.identity.name = "test2"; - payload.resource.api.hooks_url = "123123"; - payload.resource.access.read = []; - payload.resource.publication.requested = true; - - const response = await api.post(`${url}/applications/${createdApp.id}`, payload); - expect(response.statusCode).toBe(200); - - const r = response.resource; - - expect(r.company_id).toBe(payload.resource.company_id); - expect(!!r.is_default).toBe(false); - expect(r.identity).toMatchObject(payload.resource.identity); - - expect(r.access).toMatchObject(payload.resource.access); - expect(r.display).toMatchObject(payload.resource.display); - expect(r.publication).toMatchObject(payload.resource.publication); - expect(r.stats).toMatchObject({ - created_at: expect.any(Number), - updated_at: expect.any(Number), - version: 1, - }); - - expect(r.api).toBeTruthy(); - - const dbData = await appRepo.findOne({ id: response.resource.id }); - - expect(dbData.api).toMatchObject({ - allowed_ips: payload.resource.api.allowed_ips, - hooks_url: payload.resource.api.hooks_url, - private_key: expect.any(String), - }); - - done(); - }); - }); - - describe.skip("Published application", () => { - beforeAll(async done => { - const payload = { resource: cloneDeep(postPayload) }; - const response = await api.post(`${url}/applications`, payload); - createdApp = response.resource; - await publishApp(createdApp.id); - done(); - }); - - it("should 200 on update if allowed fields changed", async done => { - const payload = { resource: cloneDeep(createdApp) as Application }; - const entity = await appRepo.findOne({ id: createdApp.id }); - payload.resource.api = cloneDeep(entity.api); - payload.resource.publication.requested = true; - const response = await api.post(`${url}/applications/${createdApp.id}`, payload); - expect(response.statusCode).toBe(200); - - expect(response.resource.publication).toMatchObject({ - requested: true, - published: true, - }); - done(); - }); - - it("should 400 on update if not allowed fields changed", async done => { - const payload = { resource: cloneDeep(createdApp) as Application }; - const entity = await appRepo.findOne({ id: createdApp.id }); - payload.resource.api = cloneDeep(entity.api); - const response = await api.post(`${url}/applications/${createdApp.id}`, payload); - expect(response.statusCode).toBe(400); - done(); - }); - }); - }); - describe("Get applications", function () { - let firstApp: PublicApplicationObject; - let secondApp: PublicApplicationObject; - let thirdApp: PublicApplicationObject; - beforeAll(async done => { - const payload = { resource: cloneDeep(postPayload) }; - firstApp = (await api.post(`${url}/applications`, payload)).resource; - secondApp = (await api.post(`${url}/applications`, payload)).resource; - thirdApp = (await api.post(`${url}/applications`, payload)).resource; - - await publishApp(firstApp.id); - await publishApp(secondApp.id); - - done(); - }); - - it("should list published applications", async done => { - const response = await api.get(`${url}/applications`); - expect(response.statusCode).toBe(200); - - const published = response.resources.filter(a => a.publication.published).length; - const unpublished = response.resources.filter(a => a.publication.unpublished).length; - - expect(published).toBeGreaterThanOrEqual(2); - expect(unpublished).toEqual(0); - - expect(response.resources.map(a => a.id)).toEqual( - expect.arrayContaining([firstApp.id, secondApp.id]), - ); - - done(); - }); - - it("should return public object for published application to any user", async done => { - const response = await api.get(`${url}/applications/${firstApp.id}`, uuidv1()); - expect(response.statusCode).toBe(200); - expect(response.resource.id).toEqual(firstApp.id); - expect(response.resource.api).toBeFalsy(); - done(); - }); - - it("should return public object for unpublished application to any user", async done => { - const response = await api.get(`${url}/applications/${thirdApp.id}`, uuidv1()); - expect(response.statusCode).toBe(200); - expect(response.resource.id).toEqual(thirdApp.id); - expect(response.resource.api).toBeFalsy(); - done(); - }); - - it("should return whole object for published application to admin", async done => { - const response = await api.get(`${url}/applications/${firstApp.id}`); - expect(response.statusCode).toBe(200); - expect(response.resource.id).toEqual(firstApp.id); - expect(response.resource.api).toBeTruthy(); - - done(); - }); - - it("should return whole object for unpublished application to admin", async done => { - const response = await api.get(`${url}/applications/${thirdApp.id}`); - expect(response.statusCode).toBe(200); - expect(response.resource.id).toEqual(thirdApp.id); - expect(response.resource.api).toBeTruthy(); - done(); - }); - }); -}); - -const postPayload = { - is_default: true, - company_id: null, - identity: { - code: "code", - name: "name", - icon: "icon", - description: "description", - website: "website", - categories: [], - compatibility: [], - }, - api: { - hooks_url: "hooks_url", - allowed_ips: "allowed_ips", - }, - access: { - read: ["messages"], - write: ["messages"], - delete: ["messages"], - hooks: ["messages"], - }, - display: { - twake: { - version: 1, - - files: { - editor: { - preview_url: "string", //Open a preview inline (iframe) - edition_url: "string", //Url to edit the file (full screen) - extensions: [], //Main extensions app can read - // if file was created by the app, then the app is able to edit with or without extension - empty_files: [ - { - url: "string", // "https://[...]/empty.docx"; - filename: "string", // "Untitled.docx"; - name: "string", // "Word Document"; - }, - ], - }, - actions: [ - //List of action that can apply on a file - { - name: "string", - id: "string", - }, - ], - }, - - //Chat plugin - chat: { - input: true, - commands: [ - { - command: "string", // my_app mycommand - description: "string", - }, - ], - actions: [ - //List of action that can apply on a message - { - name: "string", - id: "string", - }, - ], - }, - - //Allow app to appear as a bot user in direct chat - direct: false, - - //Display app as a standalone application in a tab - tab: { url: "string" }, - - //Display app as a standalone application on the left bar - standalone: { url: "string" }, - - //Define where the app can be configured from - configuration: ["global", "channel"], - }, - }, - publication: { - requested: false, //Publication requested - }, -}; diff --git a/twake/backend/node/test/e2e/application/application-events.spec.ts b/twake/backend/node/test/e2e/application/application-events.spec.ts deleted file mode 100644 index 42c9bf81..00000000 --- a/twake/backend/node/test/e2e/application/application-events.spec.ts +++ /dev/null @@ -1,118 +0,0 @@ -import * as crypto from "crypto"; -import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; -import { FastifyInstance, FastifyPluginCallback, FastifyReply, FastifyRequest } from "fastify"; - -import { init, TestPlatform } from "../setup"; -import { TestDbService } from "../utils.prepare.db"; -import { Api } from "../utils.api"; - -import { logger as log } from "../../../src/core/platform/framework"; - -let signingSecret = ""; - -describe("Application events", () => { - const url = "/internal/services/applications/v1"; - let platform: TestPlatform; - let api: Api; - let appId: string; - - beforeAll(async ends => { - platform = await init(undefined, testAppHookRoute); - - await platform.database.getConnector().drop(); - - await TestDbService.getInstance(platform, true); - api = new Api(platform); - - postPayload.company_id = platform.workspace.company_id; - - const createdApplication = await api.post("/internal/services/applications/v1/applications", { - resource: postPayload, - }); - - appId = createdApplication.resource.id; - signingSecret = createdApplication.resource.api.private_key; - - ends(); - - afterAll(done => { - platform.tearDown().then(() => done()); - }); - }); - - it("Should 200 on sending well formed event", async done => { - const payload = { - company_id: platform.workspace.company_id, - workspace_id: platform.workspace.workspace_id, - type: "some type", - name: "name", - content: {}, - }; - - const response = await api.post(`${url}/applications/${appId}/event`, payload); - expect(response.statusCode).toBe(200); - expect(response.resource).toMatchObject({ a: "b" }); - done(); - }); -}); - -const postPayload = { - is_default: false, - company_id: null, - identity: { - code: "code", - name: "name", - icon: "icon", - description: "description", - website: "website", - categories: [], - compatibility: [], - }, - api: { - hooks_url: "http://localhost:3000/test/appHook", - allowed_ips: "allowed_ips", - }, - access: { - read: ["messages"], - write: ["messages"], - delete: ["messages"], - hooks: ["messages"], - }, - display: {}, - publication: { - requested: true, - }, -}; - -const testAppHookRoute = (fastify: FastifyInstance) => { - const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { - fastify.route({ - method: "POST", - url: "/test/appHook", - handler: (request: FastifyRequest, reply: FastifyReply): Promise => { - const signature = request.headers["x-twake-signature"]; - if (!signature) { - reply.status(403); - reply.send({ error: "Signature is missing" }); - return undefined; - } - - const expectedSignature = crypto - .createHmac("sha256", signingSecret) - .update(JSON.stringify(request.body)) - .digest("hex"); - if (expectedSignature != signature) { - reply.status(403); - reply.send({ error: "Wrong signature" }); - return undefined; - } - - log.debug({ signatureMatched: expectedSignature == signature }); - return Promise.resolve({ a: "b" }); - }, - }); - - next(); - }; - fastify.register(routes); -}; diff --git a/twake/backend/node/test/e2e/application/application-login.spec.ts b/twake/backend/node/test/e2e/application/application-login.spec.ts deleted file mode 100644 index e07e10dd..00000000 --- a/twake/backend/node/test/e2e/application/application-login.spec.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; - -import { init, TestPlatform } from "../setup"; -import { TestDbService } from "../utils.prepare.db"; -import { Api } from "../utils.api"; -import { logger as log } from "../../../src/core/platform/framework"; -import { ApplicationLoginResponse } from "../../../src/services/applicationsapi/web/types"; - -describe("Applications", () => { - let platform: TestPlatform; - let testDbService: TestDbService; - let api: Api; - let appId: string; - let private_key: string; - let accessToken: ApplicationLoginResponse["access_token"]; - - beforeAll(async ends => { - platform = await init(); - await platform.database.getConnector().drop(); - testDbService = await TestDbService.getInstance(platform, true); - api = new Api(platform); - - postPayload.company_id = platform.workspace.company_id; - - const createdApplication = await api.post("/internal/services/applications/v1/applications", { - resource: postPayload, - }); - - appId = createdApplication.resource.id; - private_key = createdApplication.resource.api.private_key; - - ends(); - }); - - afterAll(done => { - platform.tearDown().then(() => done()); - }); - - describe("Login", function () { - it("Should be ok on valid token", async done => { - expect(appId).toBeTruthy(); - - const response = await api.post("/api/console/v1/login", { - id: appId, - secret: private_key, - }); - expect(response.statusCode).toBe(200); - - const resource = (await response.json()).resource as ApplicationLoginResponse; - - expect(resource).toMatchObject({ - access_token: { - time: expect.any(Number), - expiration: expect.any(Number), - refresh_expiration: expect.any(Number), - value: expect.any(String), - refresh: expect.any(String), - type: expect.any(String), - }, - }); - - accessToken = resource.access_token; - - done(); - }); - }); - - describe("Get myself", function () { - it("Should be 401 on invalid token", async done => { - const response = await platform.app.inject({ - method: "GET", - url: "/api/console/v1/me", - headers: { - authorization: `Bearer ${accessToken.value + "!!"}`, - }, - }); - log.debug(response.json()); - expect(response.statusCode).toBe(401); - done(); - }); - - it("Should be 403 on auth by users (not company) token", async done => { - const userToken = await platform.auth.getJWTToken(); - - const response = await platform.app.inject({ - method: "GET", - url: "/api/console/v1/me", - headers: { - authorization: `Bearer ${userToken}`, - }, - }); - log.debug(response.json()); - expect(response.statusCode).toBe(403); - done(); - }); - - it("Should be ok on valid token", async done => { - const response = await platform.app.inject({ - method: "GET", - url: "/api/console/v1/me", - headers: { - authorization: `Bearer ${accessToken.value}`, - }, - }); - - expect(response.statusCode).toBe(200); - const resource = (await response.json()).resource; - log.debug(resource); - expect(resource).toMatchObject(postPayload); - done(); - }); - }); -}); - -const postPayload = { - is_default: false, - company_id: null, - identity: { - code: "code", - name: "name", - icon: "icon", - description: "description", - website: "website", - categories: [], - compatibility: [], - }, - api: { - hooks_url: "hooks_url", - allowed_ips: "allowed_ips", - }, - access: { - read: ["messages"], - write: ["messages"], - delete: ["messages"], - hooks: ["messages"], - }, - display: {}, - publication: { - requested: true, - }, -}; diff --git a/twake/backend/node/test/e2e/channels/channels.realtime.spec.ts b/twake/backend/node/test/e2e/channels/channels.realtime.spec.ts deleted file mode 100644 index d66cefe6..00000000 --- a/twake/backend/node/test/e2e/channels/channels.realtime.spec.ts +++ /dev/null @@ -1,176 +0,0 @@ -import "reflect-metadata"; -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; -import { ObjectId } from "mongodb"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -import io from "socket.io-client"; -import { Channel } from "../../../src/services/channels/entities/channel"; -import { - getChannelPath, - getPublicRoomName, -} from "../../../src/services/channels/services/channel/realtime"; -import { WorkspaceExecutionContext } from "../../../src/services/channels/types"; -import { init, TestPlatform } from "../setup"; -import { ChannelUtils, get as getChannelUtils } from "./utils"; -import gr from "../../../src/services/global-resolver"; - -describe("The Channels Realtime feature", () => { - const url = "/internal/services/channels/v1"; - let platform: TestPlatform; - let socket: SocketIOClient.Socket; - let channelUtils: ChannelUtils; - - beforeEach(async () => { - platform = await init({ - services: [ - "webserver", - "database", - "search", - "storage", - "message-queue", - "user", - "search", - "websocket", - "applications", - "webserver", - "channels", - "auth", - "search", - "realtime", - "counter", - "statistics", - "platform-services", - ], - }); - channelUtils = getChannelUtils(platform); - }); - - afterEach(async () => { - await platform.tearDown(); - platform = null; - socket && socket.close(); - socket = null; - }); - - function connect() { - socket = io.connect("http://localhost:3000", { path: "/socket" }); - socket.connect(); - } - - describe("On channel creation", () => { - it("should notify the client", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const roomToken = "twake"; - const channelName = new ObjectId().toString(); - - connect(); - socket.on("connect", () => { - socket - .emit("authenticate", { token: jwtToken }) - .on("authenticated", () => { - socket.emit("realtime:join", { - name: getPublicRoomName(platform.workspace), - token: roomToken, - }); - socket.on("realtime:join:error", () => done(new Error("Should not occur"))); - socket.on("realtime:join:success", async () => { - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - name: channelName, - }, - }, - }); - - expect(response.statusCode).toEqual(201); - }); - socket.on( - "realtime:resource", - (event: { type: any; action: any; resource: { name: any } }) => { - // we can also receive other types of events (channel_activity etc) - if (event.type === "channel") { - expect(event.type).toEqual("channel"); - expect(event.action).toEqual("saved"); - expect(event.resource.name).toEqual(channelName); - done(); - } - }, - ); - }) - .on("unauthorized", () => { - done(new Error("Should not occur")); - }); - }); - }); - }); - - describe("On channel removal", () => { - it("should notify the client", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const roomToken = "twake"; - const channelName = new ObjectId().toString(); - - const channel = channelUtils.getChannel(platform.currentUser.id); - channel.name = channelName; - - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - channelUtils.getContext({ id: channel.owner }), - ); - - connect(); - socket.on("connect", () => { - socket - .emit("authenticate", { token: jwtToken }) - .on("authenticated", () => { - socket.on( - "realtime:resource", - (event: { action: string; type: any; path: any; resource: { id: any } }) => { - if (event.action !== "deleted" || event.type !== "channel") { - // we can receive event when resource is created... - // we can also receive other types of events (channel_activity etc) - return; - } - - expect(event.type).toEqual("channel"); - expect(event.action).toEqual("deleted"); - expect(event.path).toEqual( - getChannelPath( - { id: creationResult.entity.id } as Channel, - { - workspace: platform.workspace, - } as WorkspaceExecutionContext, - ), - ); - expect(event.resource.id).toEqual(creationResult.entity.id); - done(); - }, - ); - socket.emit("realtime:join", { - name: getPublicRoomName(platform.workspace), - token: roomToken, - }); - socket.on("realtime:join:error", () => done(new Error("Should not occur"))); - socket.on("realtime:join:success", async () => { - await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${creationResult.entity.company_id}/workspaces/${creationResult.entity.workspace_id}/channels/${creationResult.entity.id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - }); - }) - .on("unauthorized", () => { - done(new Error("Should not occur")); - }); - }); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/channels/channels.rest.spec.ts b/twake/backend/node/test/e2e/channels/channels.rest.spec.ts deleted file mode 100644 index 2bf97a75..00000000 --- a/twake/backend/node/test/e2e/channels/channels.rest.spec.ts +++ /dev/null @@ -1,1350 +0,0 @@ -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; -import { v1 as uuidv1 } from "uuid"; -import { deserialize } from "class-transformer"; -import { init, TestPlatform } from "../setup"; -import { - ResourceGetResponse, - ResourceListResponse, - ResourceUpdateResponse, - User, - Workspace, -} from "../../../src/utils/types"; -import { Channel, ChannelMember } from "../../../src/services/channels/entities"; -import { - ChannelExecutionContext, - ChannelVisibility, - WorkspaceExecutionContext, -} from "../../../src/services/channels/types"; -import { - getPrivateRoomName, - getPublicRoomName, -} from "../../../src/services/channels/services/channel/realtime"; -import { ChannelUtils, get as getChannelUtils } from "./utils"; -import { TestDbService } from "../utils.prepare.db"; -import { ChannelObject } from "../../../src/services/channels/services/channel/types"; -import { Api } from "../utils.api"; -import gr from "../../../src/services/global-resolver"; -import { createMessage, e2e_createThread } from "../messages/utils"; - -describe("The /internal/services/channels/v1 API", () => { - const url = "/internal/services/channels/v1"; - let platform: TestPlatform; - let channelUtils: ChannelUtils; - let testDbService: TestDbService; - let api: Api; - - beforeAll(async end => { - // platform = await init(); - // await platform.database.getConnector().drop(); - end(); - }); - - beforeEach(async () => { - platform = await init(); - testDbService = new TestDbService(platform); - api = new Api(platform); - channelUtils = getChannelUtils(platform); - }); - - afterEach(async () => { - await platform?.tearDown(); - platform = null; - }); - - async function testAccess(url, method, done) { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method, - url, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toBe(400); - done(); - } - - function getContext(user?: User): WorkspaceExecutionContext { - return { - workspace: platform.workspace, - user: user || platform.currentUser, - }; - } - - /** - * Get a new channel instance - * - * @param owner will be a random uuidv4 if not defined - */ - function getChannel(owner: string = uuidv1()): Channel { - const channel = new Channel(); - - channel.name = "Test Channel"; - channel.company_id = platform.workspace.company_id; - channel.workspace_id = platform.workspace.workspace_id; - channel.is_default = false; - channel.visibility = ChannelVisibility.PRIVATE; - channel.archived = false; - channel.owner = owner; - - return channel; - } - - async function getChannelREST(channelId: string): Promise { - const response = await api.get( - `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${channelId}`, - ); - - expect(response.statusCode).toEqual(200); - - const channelGetResult: ResourceGetResponse = deserialize( - ResourceGetResponse, - response.body, - ); - - return channelGetResult.resource; - } - - describe("The GET /companies/:companyId/workspaces/:workspaceId/channels route", () => { - it("should 400 when companyId is not valid", async done => { - testAccess( - `${url}/companies/123/workspaces/${platform.workspace.workspace_id}/channels`, - "GET", - done, - ); - }); - - it("should 400 when workspaceId is not valid", async done => { - testAccess( - `${url}/companies/${platform.workspace.company_id}/workspaces/123/channels`, - "GET", - done, - ); - }); - - it("should return empty list of channels", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(0); - - done(); - }); - - it("should return list of workspace channels", async done => { - const channel = new Channel(); - channel.name = "Test Channel"; - const creationResult = await gr.services.channels.channels.save(channel, {}, getContext()); - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(1); - expect(result.resources[0]).toMatchObject({ - id: creationResult.entity.id, - name: channel.name, - }); - - result.resources.forEach(r => { - expect(r.stats).toMatchObject({ - members: 1, - messages: 0, - }); - }); - - done(); - }); - - it("should return list of channels the user is member of", async done => { - const ws0pk = { id: uuidv1(), company_id: platform.workspace.company_id }; - await testDbService.createWorkspace(ws0pk); - const newUser = await testDbService.createUser([ws0pk]); - - const channel1 = getChannel(); - const channel2 = getChannel(); - - channel1.name = "Test Channel1"; - channel2.name = "Test Channel2"; - - const creationResults = await Promise.all([ - gr.services.channels.channels.save(channel1, {}, getContext()), - gr.services.channels.channels.save(channel2, {}, getContext()), - ]); - - await gr.services.channels.members.save( - { - channel_id: channel1.id, - workspace_id: channel1.workspace_id, - company_id: channel1.company_id, - user_id: newUser.id, - } as ChannelMember, - channelUtils.getChannelContext(channel1, platform.currentUser), - ); - - const jwtToken = await platform.auth.getJWTToken({ sub: newUser.id }); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - mine: "true", - }, - }); - - console.log(response.body); - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(1); - expect(result.resources[0]).toMatchObject({ - id: creationResults[0].entity.id, - }); - - done(); - }); - - it("should return pagination information when not all channels are returned", async done => { - await Promise.all( - "0123456789".split("").map(name => { - const channel = new Channel(); - channel.name = name; - return gr.services.channels.channels.save(channel, {}, getContext()); - }), - ).catch(() => done(new Error("Failed on creation"))); - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - limit: "5", - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(5); - expect(result.next_page_token).toBeDefined; - - done(); - }); - - it("should be able to paginate over channels from pagination information", async done => { - await platform.database.getConnector().drop(); - - await Promise.all( - "0123456789".split("").map(name => { - const channel = new Channel(); - channel.name = name; - return gr.services.channels.channels.save(channel, {}, getContext()); - }), - ).catch(() => done(new Error("Failed on creation"))); - - const jwtToken = await platform.auth.getJWTToken(); - const firstPage = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - limit: "5", - }, - }); - - const firstPageChannels: ResourceListResponse = deserialize( - ResourceListResponse, - firstPage.body, - ); - - expect(firstPage.statusCode).toBe(200); - expect(firstPageChannels.resources.length).toEqual(5); - expect(firstPageChannels.next_page_token).toBeDefined; - - const nextPage = firstPageChannels.next_page_token; - const secondPage = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - limit: "5", - page_token: nextPage, - }, - }); - - const secondPageChannels: ResourceListResponse = deserialize( - ResourceListResponse, - secondPage.body, - ); - - expect(secondPage.statusCode).toBe(200); - expect(secondPageChannels.resources.length).toEqual(5); - - expect( - new Set([ - ...firstPageChannels.resources.map(resource => resource.id), - ...secondPageChannels.resources.map(resource => resource.id), - ]).size, - ).toEqual(10); - - done(); - }); - - it("should not return pagination information when all channels are returned", async done => { - await Promise.all( - "0123456789".split("").map(name => { - const channel = new Channel(); - channel.name = name; - return gr.services.channels.channels.save(channel, {}, getContext()); - }), - ).catch(() => done(new Error("Failed on creation"))); - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - limit: "11", - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(10); - expect(result.next_page_token).not.toBeDefined; - - done(); - }); - - it("should return websockets information", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - websockets: "true", - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.websockets).toMatchObject([ - { room: getPublicRoomName(platform.workspace) }, - // user id is randomly generated - { room: expect.stringContaining(getPrivateRoomName(platform.workspace, { id: "" })) }, - ]); - - done(); - }); - - it.skip("should return websockets and direct information", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - websockets: "true", - mine: "true", - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.websockets.length).toEqual(3); - - done(); - }); - }); - - describe("The GET /companies/:companyId/workspaces/:workspaceId/channels/:id route", () => { - it("should 400 when companyId is not valid", async done => { - const channelId = "1"; - - testAccess( - `${url}/companies/123/workspaces/${platform.workspace.workspace_id}/channels/${channelId}`, - "GET", - done, - ); - }); - - it("should 400 when workspaceId is not valid", async done => { - const channelId = "1"; - - testAccess( - `${url}/companies/${platform.workspace.company_id}/workspaces/123/channels/${channelId}`, - "GET", - done, - ); - }); - - it("should return the requested channel", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = new Channel(); - channel.name = "Test Channel"; - channel.company_id = platform.workspace.company_id; - channel.workspace_id = platform.workspace.workspace_id; - - const creationResult = await gr.services.channels.channels.save(channel, {}, getContext()); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${creationResult.entity.id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toEqual(200); - - const channelGetResult: ResourceGetResponse = deserialize( - ResourceGetResponse, - response.body, - ); - - expect(channelGetResult.resource).toBeDefined(); - expect(channelGetResult.resource).toMatchObject({ - id: String(creationResult.entity.id), - name: creationResult.entity.name, - }); - expect(channelGetResult.websocket).toBeDefined(); - expect(channelGetResult.websocket).toMatchObject({ - name: creationResult.entity.name, - room: `/channels/${creationResult.entity.id}`, - token: expect.any(String), - }); - - done(); - }); - - it("channel counters", async done => { - await platform.database.getConnector().drop(); - - await testDbService.createDefault(platform); - - const channel = new Channel(); - channel.name = "Test counters Channel"; - channel.company_id = platform.workspace.company_id; - channel.workspace_id = platform.workspace.workspace_id; - channel.is_default = true; - channel.visibility = ChannelVisibility.PUBLIC; - channel.description = "test counters"; - channel.channel_group = "my channel group"; - - const creationResult = await gr.services.channels.channels.save(channel, {}, getContext()); - - const channelId = creationResult.entity.id; - - let resource = await getChannelREST(channelId); - - expect(resource).toMatchObject({ - company_id: platform.workspace.company_id, - workspace_id: platform.workspace.workspace_id, - // type: expect.stringMatching(/workspace|direct/), // TODO - id: expect.any(String), - icon: expect.any(String), - name: channel.name, - description: channel.description, - channel_group: channel.channel_group, - visibility: channel.visibility, - default: channel.is_default, - owner: platform.currentUser.id, - last_activity: expect.any(Number), - archived: false, - archivation_date: 0, //Timestamp - user_member: expect.any(Object), - stats: expect.any(Object), - }); - - expect(resource.stats).toMatchObject({ - members: 1, - messages: 0, - }); - - expect(resource.user_member).toMatchObject({ - id: expect.any(String), - user_id: platform.currentUser.id, - type: expect.stringMatching(/member|guest|bot/), - last_access: 0, //Timestamp in seconds - last_increment: 0, //Number - favorite: false, - // notification_level: "all" | "none" | "group_mentions" | "user_mentions", // TODO - }); - - const anotherUserId = uuidv1(); - await gr.services.channels.members.addUsersToChannel( - [ - { id: anotherUserId }, - { id: uuidv1() }, - { id: uuidv1() }, - { id: uuidv1() }, - { id: uuidv1() }, - ], - creationResult.entity, - { - user: { id: platform.currentUser.id }, - }, - ); - - resource = await getChannelREST(channelId); - - expect(resource.stats).toMatchObject({ - members: 6, - messages: 0, - }); - - await gr.services.channels.members.delete( - { - ...platform.workspace, - channel_id: channelId, - user_id: anotherUserId, - }, - { channel: creationResult.entity, user: platform.currentUser } as ChannelExecutionContext, - ); - - resource = await getChannelREST(channelId); - - expect(resource.stats).toMatchObject({ - members: 5, - messages: 0, - }); - - done(); - }); - }); - - describe("The POST /companies/:companyId/workspaces/:workspaceId/channels route", () => { - it("should 400 when companyId is not valid", async done => { - testAccess( - `${url}/companies/123/workspaces/${platform.workspace.workspace_id}/channels`, - "POST", - done, - ); - }); - - it("should 400 when workspaceId is not valid", async done => { - testAccess( - `${url}/companies/${platform.workspace.company_id}/workspaces/123/channels`, - "POST", - done, - ); - }); - - it("should create a channel", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - name: "Test channel", - }, - }, - }); - - expect(response.statusCode).toEqual(201); - - const channelCreateResult: ResourceGetResponse = deserialize( - ResourceGetResponse, - response.body, - ); - - expect(channelCreateResult.resource).toBeDefined(); - expect(channelCreateResult.websocket).toBeDefined(); - - const res = channelCreateResult.resource; - - const createdChannel = await gr.services.channels.channels.get({ - company_id: res.company_id, - workspace_id: res.workspace_id, - id: res.id, - }); - - expect(channelCreateResult.websocket).toMatchObject({ - room: `/channels/${createdChannel.id}`, - token: expect.any(String), - }); - expect(createdChannel).toBeDefined(); - done(); - }); - - it("should fail when channel name is not defined", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - description: "The channel description", - }, - }, - }); - - expect(response.statusCode).toEqual(400); - done(); - }); - }); - - describe.skip("The POST /companies/:companyId/workspaces/:workspaceId/channels/:id route", () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - async function updateChannel(jwtToken: string, id: string, resource: any): Promise { - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource, - }, - }); - - const channelUpdateResult: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - - expect(channelUpdateResult.resource).toBeDefined(); - expect(channelUpdateResult.websocket).toBeDefined(); - - return await gr.services.channels.channels.get({ - id, - company_id: platform.workspace.company_id, - workspace_id: platform.workspace.workspace_id, - }); - } - - async function updateChannelFail( - jwtToken: string, - id: string, - resource: unknown, - expectedCode: number, - ): Promise { - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource, - }, - }); - - expect(response.statusCode).toEqual(expectedCode); - } - - it("should 400 when companyId is not valid", async done => { - testAccess( - `${url}/companies/123/workspaces/${platform.workspace.workspace_id}/channels/1`, - "POST", - done, - ); - }); - - it("should 400 when workspaceId is not valid", async done => { - testAccess( - `${url}/companies/${platform.workspace.company_id}/workspaces/123/channels/1`, - "POST", - done, - ); - }); - - describe("When user is workspace moderator and channel has been created by other user", () => { - beforeEach(() => { - platform.currentUser.isWorkspaceModerator = true; - }); - - it("should fail when resource is not defined", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - await updateChannelFail(jwtToken, creationResult.entity.id, {}, 400); - done(); - }); - - it("should be able to update the is_default field", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - const updatedChannel = await updateChannel(jwtToken, creationResult.entity.id, { - is_default: true, - }); - - expect(updatedChannel).toMatchObject({ - id: channel.id, - name: "Test Channel", - company_id: channel.company_id, - workspace_id: channel.workspace_id, - is_default: true, - visibility: channel.visibility, - archived: channel.archived, - owner: channel.owner, - }); - done(); - }); - - it("should be able to update the visibility field", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - const updatedChannel = await updateChannel(jwtToken, creationResult.entity.id, { - visibility: ChannelVisibility.PUBLIC, - }); - - expect(updatedChannel).toMatchObject({ - id: channel.id, - name: "Test Channel", - company_id: channel.company_id, - workspace_id: channel.workspace_id, - is_default: channel.is_default, - visibility: ChannelVisibility.PUBLIC, - archived: channel.archived, - owner: channel.owner, - }); - done(); - }); - - it("should be able to update the archived field", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - const updatedChannel = await updateChannel(jwtToken, creationResult.entity.id, { - archived: true, - }); - expect(updatedChannel).toMatchObject({ - id: channel.id, - name: "Test Channel", - company_id: channel.company_id, - workspace_id: channel.workspace_id, - is_default: channel.is_default, - visibility: channel.visibility, - archived: true, - owner: channel.owner, - }); - done(); - }); - - it("should be able to update all the fields at the same time", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - const updatedChannel = await updateChannel(jwtToken, creationResult.entity.id, { - visibility: ChannelVisibility.PUBLIC, - is_default: true, - archived: true, - }); - - expect(updatedChannel).toMatchObject({ - id: channel.id, - name: "Test Channel", - company_id: channel.company_id, - workspace_id: channel.workspace_id, - is_default: true, - visibility: ChannelVisibility.PUBLIC, - archived: true, - owner: channel.owner, - }); - - done(); - }); - }); - - describe("When user is channel owner", () => { - beforeEach(() => { - platform.currentUser.isWorkspaceModerator = false; - }); - - it("should be able to update the is_default field", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(platform.currentUser.id); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - const updatedChannel = await updateChannel(jwtToken, creationResult.entity.id, { - is_default: true, - }); - - expect(updatedChannel).toMatchObject({ - id: channel.id, - name: "Test Channel", - company_id: channel.company_id, - workspace_id: channel.workspace_id, - is_default: true, - visibility: channel.visibility, - archived: channel.archived, - owner: channel.owner, - }); - - done(); - }); - - it("should be able to update the visibility field", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(platform.currentUser.id); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - const updatedChannel = await updateChannel(jwtToken, creationResult.entity.id, { - visibility: ChannelVisibility.PUBLIC, - }); - - expect(updatedChannel).toMatchObject({ - id: channel.id, - name: "Test Channel", - company_id: channel.company_id, - workspace_id: channel.workspace_id, - is_default: channel.is_default, - visibility: ChannelVisibility.PUBLIC, - archived: channel.archived, - owner: channel.owner, - }); - - done(); - }); - - it("should be able to update the archived field", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(platform.currentUser.id); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - const updatedChannel = await updateChannel(jwtToken, creationResult.entity.id, { - archived: true, - }); - - expect(updatedChannel).toMatchObject({ - id: channel.id, - name: "Test Channel", - company_id: channel.company_id, - workspace_id: channel.workspace_id, - is_default: channel.is_default, - visibility: channel.visibility, - archived: true, - owner: channel.owner, - }); - done(); - }); - - it("should be able to update all the fields at the same time", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(platform.currentUser.id); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - const updatedChannel = await updateChannel(jwtToken, creationResult.entity.id, { - visibility: ChannelVisibility.PUBLIC, - is_default: true, - archived: true, - }); - - expect(updatedChannel).toMatchObject({ - id: channel.id, - name: "Test Channel", - company_id: channel.company_id, - workspace_id: channel.workspace_id, - is_default: true, - visibility: ChannelVisibility.PUBLIC, - archived: true, - owner: channel.owner, - }); - - done(); - }); - }); - - describe("When user is 'standard' user and is not channel owner", () => { - beforeEach(() => { - platform.currentUser.isWorkspaceModerator = false; - }); - - it("should not be able to update the is_default field", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - await updateChannelFail( - jwtToken, - creationResult.entity.id, - { - is_default: true, - }, - 400, - ); - - done(); - }); - - it("should not be able to update the visibility field", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - await updateChannelFail( - jwtToken, - creationResult.entity.id, - { - visibility: ChannelVisibility.PUBLIC, - }, - 400, - ); - - done(); - }); - - it("should not be able to update the archived field", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - await updateChannelFail( - jwtToken, - creationResult.entity.id, - { - archived: true, - }, - 400, - ); - - done(); - }); - - it("should be able to update the 'name', 'description', 'icon' fields", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - const updatedChannel = await updateChannel(jwtToken, creationResult.entity.id, { - name: "This is a new name", - description: "This is a new description", - icon: "This is a new icon", - }); - - expect(updatedChannel).toMatchObject({ - id: channel.id, - name: "This is a new name", - description: "This is a new description", - icon: "This is a new icon", - company_id: channel.company_id, - workspace_id: channel.workspace_id, - is_default: channel.is_default, - visibility: channel.visibility, - archived: channel.archived, - owner: channel.owner, - }); - - done(); - }); - }); - }); - - describe.skip("The DELETE /companies/:companyId/workspaces/:workspaceId/channels/:id route", () => { - async function expectDeleteResult( - jwtToken: string, - url: string, - status: number, - ): Promise { - const response = await platform.app.inject({ - method: "DELETE", - url, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toEqual(status); - } - - it("should 400 when companyId is not valid", async done => { - testAccess( - `${url}/companies/123/workspaces/${platform.workspace.workspace_id}/channels/1`, - "DELETE", - done, - ); - }); - - it("should 400 when workspaceId is not valid", async done => { - testAccess( - `${url}/companies/${platform.workspace.company_id}/workspaces/123/channels/1`, - "DELETE", - done, - ); - }); - - describe("When user is workspace moderator", () => { - beforeEach(() => { - platform.currentUser.isWorkspaceModerator = true; - }); - - it("should not be able to delete a direct channel", async done => { - platform.workspace.workspace_id = "direct"; - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - await expectDeleteResult( - jwtToken, - `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${creationResult.entity.id}`, - 400, - ); - done(); - }); - - it("should be able to delete any channel of the workspace", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - await expectDeleteResult( - jwtToken, - `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${creationResult.entity.id}`, - 204, - ); - done(); - }); - }); - - describe("When user is channel owner", () => { - beforeEach(() => { - platform.currentUser.isWorkspaceModerator = false; - }); - - it("should not be able to delete a direct channel", async done => { - platform.workspace.workspace_id = "direct"; - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(platform.currentUser.id); - - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - await expectDeleteResult( - jwtToken, - `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${creationResult.entity.id}`, - 400, - ); - done(); - }); - - it("should be able to delete the channel", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(platform.currentUser.id); - - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - await expectDeleteResult( - jwtToken, - `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${creationResult.entity.id}`, - 204, - ); - done(); - }); - }); - - describe("When user is not creator nor workspace moderator", () => { - beforeEach(() => { - platform.currentUser.isWorkspaceModerator = false; - }); - - it("should not be able to delete the channel", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - await expectDeleteResult( - jwtToken, - `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${creationResult.entity.id}`, - 400, - ); - done(); - }); - - it("should not be able to delete a direct channel", async done => { - platform.workspace.workspace_id = "direct"; - const jwtToken = await platform.auth.getJWTToken(); - - const channel = getChannel(); - - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - getContext({ id: channel.owner }), - ); - - await expectDeleteResult( - jwtToken, - `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${creationResult.entity.id}`, - 400, - ); - done(); - }); - }); - }); - - describe("The GET /companies/:companyId/workspaces/:workspaceId/recent route", () => { - it("should return list of recent channels for workspace", async done => { - await testDbService.createDefault(platform); - - const channels = []; - - for (let i = 0; i < 5; i++) { - const channel = new Channel(); - channel.name = `Regular Channel ${i}`; - channel.visibility = ChannelVisibility.PUBLIC; - const creationResult = await gr.services.channels.channels.save(channel, {}, getContext()); - channels.push(creationResult.entity); - } - - for (let i = 0; i < 5; i++) { - // const channel = channelUtils.getChannel(); - const directChannelIn = channelUtils.getDirectChannel(); - - const nextUser = await testDbService.createUser( - [{ id: platform.workspace.workspace_id, company_id: platform.workspace.company_id }], - { firstName: "FirstName" + i, lastName: "LastName" + i }, - ); - - const members = [platform.currentUser.id, nextUser.id]; - const directWorkspace: Workspace = { - company_id: platform.workspace.company_id, - workspace_id: ChannelVisibility.DIRECT, - }; - await Promise.all([ - // gr.services.channels.channels.save(channel, {}, getContext()), - gr.services.channels.channels.save( - directChannelIn, - { - members, - }, - { ...getContext(), ...{ workspace: directWorkspace } }, - ), - ]); - channels.push(directChannelIn); - } - - await new Promise(resolve => setTimeout(resolve, 2000)); - - console.log("done awaiting"); - - await e2e_createThread( - platform, - [ - { - company_id: platform.workspace.company_id, - created_at: 0, - created_by: "", - id: channels[2].id, - type: "channel", - workspace_id: platform.workspace.workspace_id, - }, - ], - createMessage({ text: "Initial thread message for regular channel" }), - ); - - await e2e_createThread( - platform, - [ - { - company_id: platform.workspace.company_id, - created_at: 0, - created_by: "", - id: channels[7].id, - type: "channel", - workspace_id: "direct", - }, - ], - createMessage({ text: "Some message" }), - ); - - await gr.services.channels.channels.markAsRead(channels[2], { id: platform.currentUser.id }); - await gr.services.channels.channels.markAsRead(channels[7], { id: platform.currentUser.id }); - - await new Promise(resolve => setTimeout(resolve, 2000)); - - const jwtToken = await platform.auth.getJWTToken(); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/channels/recent`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toBe(200); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - console.log(result.resources[0]); - console.log(result.resources.map(a => `${a.name} — ${a.last_activity}`)); - - expect(result.resources.length).toEqual(10); - - expect(result.resources[0].name).toEqual("FirstName2 LastName2"); - expect(result.resources[1].name).toEqual("Regular Channel 2"); - - done(); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/channels/channels.search.spec.ts b/twake/backend/node/test/e2e/channels/channels.search.spec.ts deleted file mode 100644 index bb1da691..00000000 --- a/twake/backend/node/test/e2e/channels/channels.search.spec.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; -import { v1 as uuidv1 } from "uuid"; -import { deserialize } from "class-transformer"; -import { init, TestPlatform } from "../setup"; -import { ResourceGetResponse, ResourceListResponse, User } from "../../../src/utils/types"; -import { Channel } from "../../../src/services/channels/entities"; -import { ChannelVisibility, WorkspaceExecutionContext } from "../../../src/services/channels/types"; -import { ChannelMember } from "../../../src/services/channels/entities"; -import { ChannelUtils, get as getChannelUtils } from "./utils"; -import { TestDbService } from "../utils.prepare.db"; -import { ChannelObject } from "../../../src/services/channels/services/channel/types"; -import { Api } from "../utils.api"; -import gr from "../../../src/services/global-resolver"; - -describe("The /internal/services/channels/v1 API", () => { - const url = "/internal/services/channels/v1"; - let platform: TestPlatform; - let channelUtils: ChannelUtils; - let testDbService: TestDbService; - let api: Api; - - beforeEach(async () => { - platform = await init(); - testDbService = new TestDbService(platform); - api = new Api(platform); - channelUtils = getChannelUtils(platform); - }); - - afterEach(async () => { - await platform?.tearDown(); - platform = null; - }); - - async function testAccess(url, method, done) { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method, - url, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toBe(400); - done(); - } - - function getContext(user?: User): WorkspaceExecutionContext { - return { - workspace: platform.workspace, - user: user || platform.currentUser, - }; - } - - /** - * Get a new channel instance - * - * @param owner will be a random uuidv4 if not defined - */ - function getChannel(owner: string = uuidv1()): Channel { - const channel = new Channel(); - - channel.name = "Test Channel"; - channel.company_id = platform.workspace.company_id; - channel.workspace_id = platform.workspace.workspace_id; - channel.is_default = false; - channel.visibility = ChannelVisibility.PRIVATE; - channel.archived = false; - channel.owner = owner; - - return channel; - } - - async function getChannelREST(channelId: string): Promise { - const response = await api.get( - `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${channelId}`, - ); - - expect(response.statusCode).toEqual(200); - - const channelGetResult: ResourceGetResponse = deserialize( - ResourceGetResponse, - response.body, - ); - - return channelGetResult.resource; - } - - describe("Channels search", () => { - it("Should find channels by name", async done => { - const ws0pk = { id: uuidv1(), company_id: platform.workspace.company_id }; - await testDbService.createWorkspace(ws0pk); - const newUser = await testDbService.createUser([ws0pk]); - - for (let i = 0; i < 10; i++) { - const channel = getChannel(); - channel.name = `test channel ${i}`; - await gr.services.channels.channels.save(channel, {}, getContext()); - - if (i == 0) continue; - await gr.services.channels.members.save( - { - channel_id: channel.id, - workspace_id: channel.workspace_id, - company_id: channel.company_id, - user_id: newUser.id, - } as ChannelMember, - channelUtils.getChannelContext(channel, platform.currentUser), - ); - } - - await new Promise(r => setTimeout(() => r(true), 1000)); - - const jwtToken = await platform.auth.getJWTToken({ sub: newUser.id }); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/search`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - q: "test", - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(9); - done(); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/channels/direct-channels.spec.ts b/twake/backend/node/test/e2e/channels/direct-channels.spec.ts deleted file mode 100644 index 8c49e156..00000000 --- a/twake/backend/node/test/e2e/channels/direct-channels.spec.ts +++ /dev/null @@ -1,420 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; -import { v1 as uuidv1 } from "uuid"; -import { deserialize } from "class-transformer"; -import { init, TestPlatform } from "../setup"; -import { - ResourceCreateResponse, - ResourceListResponse, - User, - Workspace, -} from "../../../src/utils/types"; -import { Channel } from "../../../src/services/channels/entities"; -import { ChannelVisibility, WorkspaceExecutionContext } from "../../../src/services/channels/types"; -import { ChannelUtils, get as getChannelUtils } from "./utils"; -import { DirectChannel } from "../../../src/services/channels/entities/direct-channel"; -import gr from "../../../src/services/global-resolver"; - -describe("The direct channels API", () => { - const url = "/internal/services/channels/v1"; - let platform: TestPlatform; - let channelUtils: ChannelUtils; - - beforeEach(async () => { - platform = await init({ - services: [ - "webserver", - "database", - "search", - "storage", - "message-queue", - "user", - "applications", - "websocket", - "channels", - "auth", - "storage", - "counter", - "statistics", - ], - }); - channelUtils = getChannelUtils(platform); - }); - - afterEach(async () => { - await platform.tearDown(); - }); - - function getContext(user?: User): WorkspaceExecutionContext { - return { - workspace: platform.workspace, - user: user || platform.currentUser, - }; - } - - describe("Channel List - GET /channels", () => { - it("should return empty list of direct channels", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/direct/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(0); - - done(); - }); - - it("should return list of direct channels the user is member of", async done => { - const channel = channelUtils.getChannel(); - const directChannelIn = channelUtils.getDirectChannel(); - const directChannelNotIn = channelUtils.getDirectChannel(); - const members = [platform.currentUser.id, uuidv1()]; - const directWorkspace: Workspace = { - company_id: platform.workspace.company_id, - workspace_id: ChannelVisibility.DIRECT, - }; - - const creationResult = await Promise.all([ - gr.services.channels.channels.save(channel, {}, getContext()), - gr.services.channels.channels.save( - directChannelIn, - { - members, - }, - { ...getContext(), ...{ workspace: directWorkspace } }, - ), - gr.services.channels.channels.save( - directChannelNotIn, - { - members: [uuidv1(), uuidv1()], - }, - { ...getContext({ id: uuidv1() }), ...{ workspace: directWorkspace } }, - ), - ]); - - const jwtToken = await platform.auth.getJWTToken(); - const directResponse = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/direct/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const directResult: ResourceListResponse = deserialize( - ResourceListResponse, - directResponse.body, - ); - - expect(directResponse.statusCode).toBe(200); - expect(directResult.resources.length).toEqual(1); - - expect(directResult.resources[0]).toMatchObject({ - id: creationResult[1].entity.id, - workspace_id: ChannelVisibility.DIRECT, - user_member: { - user_id: platform.currentUser.id, - }, - }); - - expect(directResult.resources[0].members).toContain(members[0]); - expect(directResult.resources[0].members).toContain(members[1]); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(1); - expect(result.resources[0]).toMatchObject({ - id: creationResult[0].entity.id, - }); - - done(); - }); - - it("should not return direct channels in workspace list", async done => { - const channel = channelUtils.getChannel(); - const directChannelIn = channelUtils.getDirectChannel(); - const directChannelIn2 = channelUtils.getDirectChannel(); - const directChannelNotIn = channelUtils.getDirectChannel(); - const members = [platform.currentUser.id, uuidv1()]; - const directWorkspace: Workspace = { - company_id: platform.workspace.company_id, - workspace_id: ChannelVisibility.DIRECT, - }; - - const creationResult = await Promise.all([ - //This channel will automatically contains the requester because it is added automatically in it - gr.services.channels.channels.save(channel, {}, getContext()), - - //It will contain the currentUser - gr.services.channels.channels.save( - directChannelIn, - { - members, - }, - { ...getContext({ id: uuidv1() }), ...{ workspace: directWorkspace } }, - ), - - //This channel will automatically contains the requester because it is added automatically in it - gr.services.channels.channels.save( - directChannelIn2, - { - members: [uuidv1(), uuidv1()], - }, - { ...getContext(), ...{ workspace: directWorkspace } }, - ), - - //This channel will not contain the currentUser - gr.services.channels.channels.save( - directChannelNotIn, - { - members: [uuidv1(), uuidv1()], - }, - { ...getContext({ id: uuidv1() }), ...{ workspace: directWorkspace } }, - ), - ]); - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(1); - expect(result.resources[0]).toMatchObject({ - id: creationResult[0].entity.id, - }); - expect(result.resources[0].visibility).not.toEqual(ChannelVisibility.DIRECT); - - done(); - }); - - it("should not return direct channels in workspace list with mine parameter", async done => { - const channel = channelUtils.getChannel(); - const channel2 = channelUtils.getChannel(); - const directChannelIn = channelUtils.getDirectChannel(); - const directChannelNotIn = channelUtils.getDirectChannel(); - const members = [platform.currentUser.id, uuidv1()]; - const directWorkspace: Workspace = { - company_id: platform.workspace.company_id, - workspace_id: ChannelVisibility.DIRECT, - }; - - await Promise.all([ - //This channel will automatically contains the requester because it is added automatically in it - gr.services.channels.channels.save(channel, {}, getContext()), - - //This channel will not contain currentUser - gr.services.channels.channels.save(channel2, {}, getContext({ id: uuidv1() })), - - //This channel will automatically contains the requester because it is added automatically in it - gr.services.channels.channels.save( - directChannelIn, - { - members, - }, - { ...getContext(), ...{ workspace: directWorkspace } }, - ), - - gr.services.channels.channels.save( - directChannelNotIn, - { - members: [uuidv1(), uuidv1(), uuidv1()], - }, - { ...getContext(), ...{ workspace: directWorkspace } }, - ), - ]); - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - mine: "true", - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(1); - - done(); - }); - }); - - describe("Create direct channel - POST /channels", () => { - it("should be able to create a direct channel with members", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const members = [uuidv1(), platform.currentUser.id]; - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/direct/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - options: { - members, - }, - resource: { - description: "A direct channel description", - visibility: "direct", - }, - }, - }); - - expect(response.statusCode).toEqual(201); - - const channelCreateResult: ResourceCreateResponse = deserialize( - ResourceCreateResponse, - response.body, - ); - - expect(channelCreateResult.resource).toBeDefined(); - - const createdChannel = await gr.services.channels.channels.get({ - id: channelCreateResult.resource.id, - company_id: channelCreateResult.resource.company_id, - workspace_id: ChannelVisibility.DIRECT, - }); - expect(createdChannel).toBeDefined(); - - const directChannelEntity = await gr.services.channels.channels.getDirectChannel({ - channel_id: createdChannel.id, - company_id: createdChannel.company_id, - users: DirectChannel.getUsersAsString(members), - }); - expect(directChannelEntity).toBeDefined(); - - const directChannelsInCompany = await gr.services.channels.channels.getDirectChannelInCompany( - createdChannel.company_id, - members, - ); - expect(directChannelsInCompany).toBeDefined(); - - done(); - }); - - it("should not be able to create the same direct channel twice (with same users)", async done => { - function createChannel(members: string[]) { - return platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/direct/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - options: { - members, - }, - resource: { - name: "Hello", - visibility: "direct", - }, - }, - }); - } - - const jwtToken = await platform.auth.getJWTToken(); - const members = [uuidv1(), platform.currentUser.id]; - const ids = new Set(); - - let response = await createChannel(members); - expect(response.statusCode).toEqual(201); - let channelCreateResult: ResourceCreateResponse = deserialize( - ResourceCreateResponse, - response.body, - ); - ids.add(channelCreateResult.resource.id); - - response = await createChannel(members); - expect(response.statusCode).toEqual(201); - channelCreateResult = deserialize(ResourceCreateResponse, response.body); - ids.add(channelCreateResult.resource.id); - - expect(ids.size).toEqual(1); - - done(); - }); - - it("should not be able to create the same direct channel twice (with same users not in the same order)", async done => { - function createChannel(members: string[]) { - return platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/direct/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - options: { - members, - }, - resource: { - name: "Hello", - visibility: "direct", - }, - }, - }); - } - - const jwtToken = await platform.auth.getJWTToken(); - const members = [uuidv1(), platform.currentUser.id]; - const ids = new Set(); - - let response = await createChannel(members); - expect(response.statusCode).toEqual(201); - let channelCreateResult: ResourceCreateResponse = deserialize( - ResourceCreateResponse, - response.body, - ); - ids.add(channelCreateResult.resource.id); - - response = await createChannel(members.reverse()); - expect(response.statusCode).toEqual(201); - channelCreateResult = deserialize(ResourceCreateResponse, response.body); - ids.add(channelCreateResult.resource.id); - - expect(ids.size).toEqual(1); - - done(); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/channels/skip-channel-members.realtime.spec.ts b/twake/backend/node/test/e2e/channels/skip-channel-members.realtime.spec.ts deleted file mode 100644 index eede90a7..00000000 --- a/twake/backend/node/test/e2e/channels/skip-channel-members.realtime.spec.ts +++ /dev/null @@ -1,177 +0,0 @@ -import "reflect-metadata"; -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -import io from "socket.io-client"; -import { Channel, ChannelMember } from "../../../src/services/channels/entities"; -import { init, TestPlatform } from "../setup"; -import { ChannelUtils, get as getChannelUtils } from "./utils"; -import { getPublicRoomName } from "../../../src/services/channels/services/member/realtime"; -import { SaveResult } from "../../../src/core/platform/framework/api/crud-service"; -import gr from "../../../src/services/global-resolver"; - -describe.skip("The Channels Members Realtime feature", () => { - const url = "/internal/services/channels/v1"; - let platform: TestPlatform; - let socket: SocketIOClient.Socket; - let channelUtils: ChannelUtils; - - beforeEach(async () => { - platform = await init({ - services: [ - "message-queue", - "user", - "search", - "websocket", - "webserver", - "channels", - "auth", - "database", - "search", - "realtime", - ], - }); - channelUtils = getChannelUtils(platform); - }); - - afterEach(async () => { - await platform.tearDown(); - platform = null; - socket && socket.close(); - socket = null; - }); - - function connect() { - socket = io.connect("http://localhost:3000", { path: "/socket.io" }); - socket.connect(); - } - - describe("On channel member creation", () => { - let channel; - let createdChannel: SaveResult; - - beforeEach(async () => { - channel = channelUtils.getChannel(); - createdChannel = await gr.services.channels.channels.save( - channel, - {}, - channelUtils.getContext({ id: channel.owner }), - ); - }); - - it("should notify the client", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const roomToken = "twake"; - - connect(); - socket.on("connect", () => { - socket - .emit("authenticate", { token: jwtToken }) - .on("authenticated", () => { - socket.emit("realtime:join", { - name: getPublicRoomName(createdChannel.entity), - token: roomToken, - }); - socket.on("realtime:join:error", () => done(new Error("Should not occur"))); - socket.on("realtime:join:success", async () => { - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - user_id: platform.currentUser.id, - }, - }, - }); - - expect(response.statusCode).toEqual(201); - }); - socket.on("realtime:resource", event => { - expect(event.type).toEqual("channel_member"); - expect(event.action).toEqual("saved"); - expect(event.resource).toMatchObject({ - company_id: platform.workspace.company_id, - workspace_id: platform.workspace.workspace_id, - user_id: platform.currentUser.id, - channel_id: createdChannel.entity.id, - }); - done(); - }); - }) - .on("unauthorized", () => { - done(new Error("Should not occur")); - }); - }); - }); - }); - - describe("On channel member removal", () => { - it("should notify the client", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const roomToken = "twake"; - - const channel = channelUtils.getChannel(platform.currentUser.id); - - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - channelUtils.getContext({ id: channel.owner }), - ); - const member = { - channel_id: creationResult.entity.id, - workspace_id: platform.workspace.workspace_id, - company_id: platform.workspace.company_id, - user_id: platform.currentUser.id, - } as ChannelMember; - - await gr.services.channels.members.save(member, { - channel: creationResult.entity, - user: platform.currentUser, - }); - - connect(); - socket.on("connect", () => { - socket - .emit("authenticate", { token: jwtToken }) - .on("authenticated", () => { - socket.on("realtime:resource", event => { - if (event.action !== "deleted") { - // we can receive event when resource is created... - return; - } - - expect(event.type).toEqual("channel_member"); - expect(event.action).toEqual("deleted"); - expect(event.resource).toMatchObject({ - company_id: platform.workspace.company_id, - workspace_id: platform.workspace.workspace_id, - user_id: platform.currentUser.id, - channel_id: creationResult.entity.id, - }); - done(); - }); - socket.emit("realtime:join", { - name: getPublicRoomName(creationResult.entity), - token: roomToken, - }); - socket.on("realtime:join:error", () => done(new Error("Should not occur"))); - socket.on("realtime:join:success", async () => { - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${creationResult.entity.company_id}/workspaces/${creationResult.entity.workspace_id}/channels/${creationResult.entity.id}/members/${platform.currentUser.id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - }); - }) - .on("unauthorized", () => { - done(new Error("Should not occur")); - }); - }); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/channels/skip-channel-members.rest.spec.ts b/twake/backend/node/test/e2e/channels/skip-channel-members.rest.spec.ts deleted file mode 100644 index 10e6ece9..00000000 --- a/twake/backend/node/test/e2e/channels/skip-channel-members.rest.spec.ts +++ /dev/null @@ -1,401 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; -import { v1 as uuidv1, v4 as uuidv4 } from "uuid"; -import { deserialize } from "class-transformer"; -import { init, TestPlatform } from "../setup"; -import { Channel } from "../../../src/services/channels/entities/channel"; -import { ChannelMember } from "../../../src/services/channels/entities/channel-member"; -import { - ChannelExecutionContext, - ChannelVisibility, - WorkspaceExecutionContext, -} from "../../../src/services/channels/types"; -import { ResourceGetResponse, ResourceListResponse, User } from "../../../src/utils/types"; -import gr from "../../../src/services/global-resolver"; - -describe.skip("The ChannelMembers REST API", () => { - const url = "/internal/services/channels/v1"; - let platform: TestPlatform; - - beforeEach(async () => { - platform = await init({ - services: ["websocket", "webserver", "channels", "auth", "database"], - }); - }); - - afterEach(async () => { - await platform.tearDown(); - platform = null; - }); - - function getWorkspaceContext(user?: User): WorkspaceExecutionContext { - return { - workspace: platform.workspace, - user: user || platform.currentUser, - }; - } - - function getContext(channel: Channel, user?: User): ChannelExecutionContext { - return { - channel, - user, - }; - } - - /** - * Get a new channel instance - * - * @param owner will be a random uuidv4 if not defined - */ - function getChannel(owner: string = uuidv1()): Channel { - const channel = new Channel(); - - channel.name = "Test Channel"; - channel.company_id = platform.workspace.company_id; - channel.workspace_id = platform.workspace.workspace_id; - channel.is_default = false; - channel.visibility = ChannelVisibility.PRIVATE; - channel.archived = false; - channel.owner = owner; - - return channel; - } - - function getMember(channel: Channel, user: User): ChannelMember { - const member = new ChannelMember(); - - member.company_id = platform.workspace.company_id; - member.workspace_id = platform.workspace.workspace_id; - member.channel_id = channel?.id; - member.user_id = user?.id; - - return member; - } - - describe("The GET / - Get members list", () => { - let channel; - let createdChannel; - - beforeEach(async () => { - channel = getChannel(); - createdChannel = await gr.services.channels.channels.save(channel, {}, getWorkspaceContext()); - }); - - it("should 404 when channel does not exists", done => { - done(); - }); - - it("should return empty list of members", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(0); - - done(); - }); - - it("should return list of members the user has access to", async done => { - const member = getMember(createdChannel.entity, platform.currentUser); - const memberCreationResult = await gr.services.channels.members.save( - member, - getContext(channel), - ); - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toEqual(1); - expect(result.resources[0]).toMatchObject({ - channel_id: memberCreationResult.entity.channel_id, - workspace_id: memberCreationResult.entity.workspace_id, - company_id: memberCreationResult.entity.company_id, - user_id: memberCreationResult.entity.user_id, - }); - - done(); - }); - }); - - describe("The POST / - Add member", () => { - let channel; - let createdChannel; - - beforeEach(async () => { - channel = getChannel(); - createdChannel = await gr.services.channels.channels.save(channel, {}, getWorkspaceContext()); - }); - - it("should fail when user_id is not defined", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: {}, - }, - }); - - expect(response.statusCode).toEqual(400); - - done(); - }); - - it("should be able to add current member", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - user_id: platform.currentUser.id, - }, - }, - }); - - expect(response.statusCode).toEqual(201); - - done(); - }); - - it("should be able to add another member", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - user_id: uuidv1(), - }, - }, - }); - - expect(response.statusCode).toEqual(201); - done(); - }); - }); - - describe("The GET /:member_id - Get a member", () => { - let channel; - let createdChannel; - - beforeEach(async () => { - channel = getChannel(); - createdChannel = await gr.services.channels.channels.save(channel, {}, getWorkspaceContext()); - }); - - it("should 404 when member does not exist", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${ - platform.workspace.workspace_id - }/channels/${createdChannel.entity.id}/members/${uuidv1()}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toEqual(404); - done(); - }); - - it("should send back member", async done => { - const member = getMember(createdChannel.entity, platform.currentUser); - const memberCreationResult = await gr.services.channels.members.save( - member, - getContext(channel), - ); - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members/${memberCreationResult.entity.user_id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toEqual(200); - const result: ResourceGetResponse = deserialize( - ResourceGetResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resource).toMatchObject({ - channel_id: memberCreationResult.entity.channel_id, - workspace_id: memberCreationResult.entity.workspace_id, - company_id: memberCreationResult.entity.company_id, - user_id: memberCreationResult.entity.user_id, - }); - - done(); - }); - }); - - describe("The POST /:member_id - Update a member", () => { - let channel; - let createdChannel; - - beforeEach(async () => { - channel = getChannel(); - createdChannel = await gr.services.channels.channels.save(channel, {}, getWorkspaceContext()); - }); - - it("should not be able to update a member when current user is not the member", async done => { - const member = getMember(createdChannel.entity, { id: uuidv4() }); - const memberCreationResult = await gr.services.channels.members.save( - member, - getContext(channel), - ); - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members/${memberCreationResult.entity.user_id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - favorite: true, - }, - }, - }); - - expect(response.statusCode).toEqual(400); - done(); - }); - - it("should be able to update member when current user is the member", async done => { - const member = getMember(createdChannel.entity, platform.currentUser); - const memberCreationResult = await gr.services.channels.members.save( - member, - getContext(channel), - ); - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members/${memberCreationResult.entity.user_id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - favorite: true, - }, - }, - }); - - expect(response.statusCode).toEqual(200); - - const channelMember: ChannelMember = await gr.services.channels.members.get(member); - - expect(channelMember).toMatchObject({ - channel_id: memberCreationResult.entity.channel_id, - workspace_id: memberCreationResult.entity.workspace_id, - company_id: memberCreationResult.entity.company_id, - user_id: memberCreationResult.entity.user_id, - favorite: true, - }); - - done(); - }); - }); - - describe("The DELETE /:member_id - Remove a member", () => { - let channel; - let createdChannel; - - beforeEach(async () => { - channel = getChannel(); - createdChannel = await gr.services.channels.channels.save(channel, {}, getWorkspaceContext()); - }); - - it("should 404 when member does not exist", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${ - platform.workspace.workspace_id - }/channels/${createdChannel.entity.id}/members/${uuidv1()}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - favorite: true, - }, - }, - }); - - expect(response.statusCode).toEqual(404); - done(); - }); - - it("should not be able to remove the member when current user does not have enough rights", async done => { - // const member = getMember(createdChannel.entity, { id: uuidv4() }); - // const memberCreationResult = await gr.services.channels.members.save(member); - // const jwtToken = await platform.auth.getJWTToken(); - // const response = await platform.app.inject({ - // method: "DELETE", - // url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members/${memberCreationResult.entity.user_id}`, - // headers: { - // authorization: `Bearer ${jwtToken}`, - // }, - // }); - // - // expect(response.statusCode).toEqual(400); - // done(); - }); - - it("should be able to remove the member when current user is the member", async done => { - const member = getMember(createdChannel.entity, platform.currentUser); - const memberCreationResult = await gr.services.channels.members.save( - member, - getContext(channel), - ); - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members/${memberCreationResult.entity.user_id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toEqual(204); - done(); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/channels/utils.ts b/twake/backend/node/test/e2e/channels/utils.ts deleted file mode 100644 index b68024a6..00000000 --- a/twake/backend/node/test/e2e/channels/utils.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { v1 as uuidv1 } from "uuid"; -import { ChannelMember } from "../../../src/services/channels/entities"; -import { Channel } from "../../../src/services/channels/entities/channel"; -import { - ChannelExecutionContext, - ChannelVisibility, - WorkspaceExecutionContext, -} from "../../../src/services/channels/types"; -import { User } from "../../../src/utils/types"; -import { TestPlatform } from "../setup"; - -export interface ChannelUtils { - getContext(user?: User): WorkspaceExecutionContext; - getChannel(owner?: string): Channel; - getDirectChannel(owner?: string): Channel; - getChannelContext(channel: Channel, user: User): ChannelExecutionContext; -} - -export interface ChannelMemberUtils { - getMember(channel: Channel, user: User): ChannelMember; -} - -export function getMemberUtils(platform: TestPlatform): ChannelMemberUtils { - return { - getMember, - }; - - function getMember(channel: Channel, user: User): ChannelMember { - const member = new ChannelMember(); - - member.company_id = platform.workspace.company_id; - member.workspace_id = platform.workspace.workspace_id; - member.channel_id = channel?.id; - member.user_id = user?.id; - - return member; - } -} - -export function get(platform: TestPlatform): ChannelUtils { - return { - getContext, - getChannel, - getDirectChannel, - getChannelContext, - }; - - function getContext(user?: User): WorkspaceExecutionContext { - return { - workspace: platform.workspace, - user: user || platform.currentUser, - }; - } - - function getChannelContext(channel: Channel, user?: User): ChannelExecutionContext { - return { - channel, - user, - }; - } - - /** - * Get a new channel instance - * - * @param owner will be a random uuidv4 if not defined - */ - function getChannel(owner: string = uuidv1()): Channel { - const channel = new Channel(); - - channel.name = "Test Channel"; - channel.company_id = platform.workspace.company_id; - channel.workspace_id = platform.workspace.workspace_id; - channel.is_default = false; - channel.visibility = ChannelVisibility.PUBLIC; - channel.archived = false; - channel.owner = owner; - - return channel; - } - - function getDirectChannel(owner: string = uuidv1()): Channel { - const channel = getChannel(owner); - - channel.visibility = ChannelVisibility.DIRECT; - channel.workspace_id = ChannelVisibility.DIRECT; - channel.name = "A direct channel"; - - return channel; - } -} diff --git a/twake/backend/node/test/e2e/console/console-auth.spec.ts b/twake/backend/node/test/e2e/console/console-auth.spec.ts deleted file mode 100644 index f542f795..00000000 --- a/twake/backend/node/test/e2e/console/console-auth.spec.ts +++ /dev/null @@ -1,272 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it as _it, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { TestDbService } from "../utils.prepare.db"; -import { v1 as uuidv1 } from "uuid"; -import gr from "../../../src/services/global-resolver"; - -export const itRemote = (name: string, cb: (a: any) => void) => { - _it(name, async done => { - if (gr.services.console.consoleType === "remote") { - cb(done); - } else { - console.warn(`[skipped]: ${name} (console-mode only)`); - done(); - } - }); -}; - -describe("The console API auth", () => { - const loginUrl = "/internal/services/console/v1/login"; - const tokenRefreshUrl = "/internal/services/console/v1/token"; - - let platform: TestPlatform; - - let testDbService: TestDbService; - const companyId = uuidv1(); - - const firstEmail = "superman@email.com"; - - const firstUserPassword = "superPassw0rd"; - - beforeAll(async ends => { - platform = await init({ - services: [ - "database", - "message-queue", - "search", - "applications", - "webserver", - "user", - "workspaces", - "auth", - "console", - "storage", - "counter", - "statistics", - "platform-services", - ], - }); - - await platform.database.getConnector().init(); - testDbService = await TestDbService.getInstance(platform); - await testDbService.createCompany(companyId); - const ws0pk = { id: uuidv1(), company_id: companyId }; - // const ws1pk = { id: uuidv1(), company_id: companyId }; - await testDbService.createWorkspace(ws0pk); - // await testDbService.createWorkspace(ws1pk); - await testDbService.createUser([ws0pk], { - companyRole: "member", - workspaceRole: "moderator", - email: firstEmail, - firstName: "superman", - password: firstUserPassword, - }); - // await testDbService.createUser([ws0pk], "member", "member"); - // await testDbService.createUser([ws1pk], "member", "member", emailForExistedUser); - - await new Promise(r => setTimeout(r, 1000)); - - ends(); - }); - - afterAll(async ends => { - await platform.tearDown(); - ends(); - }); - - describe("Common checks", () => { - it("should 400 when required params are missing ", async done => { - const response = await platform.app.inject({ - method: "POST", - url: `${loginUrl}`, - payload: { - email: "", - password: "", - remote_access_token: "", - }, - }); - expect(response.statusCode).toBe(400); - expect(response.json()).toMatchObject({ - statusCode: 400, - error: "Bad Request", - message: "remote_access_token or email+password are required", - }); - done(); - }); - }); - describe("Auth using token", () => { - itRemote("should 403 when token is invalid", async done => { - const response = await platform.app.inject({ - method: "POST", - url: `${loginUrl}`, - payload: { - remote_access_token: "12345", - }, - }); - expect(response.json()).toMatchObject({ - error: "Forbidden", - message: "Bad access token credentials", - statusCode: 403, - }); - expect(response.statusCode).toBe(403); - - done(); - }); - - itRemote("should 200 when token is valid", async done => { - const response = await platform.app.inject({ - method: "POST", - url: `${loginUrl}`, - payload: { - email: "", - password: "", - remote_access_token: "a550c8b8b942bd92e447271343ac6b29", - }, - }); - expect(response.json()).toMatchObject({ - access_token: { - time: expect.any(Number), - expiration: expect.any(Number), - refresh_expiration: expect.any(Number), - value: expect.any(String), - refresh: expect.any(String), - type: "Bearer", - }, - }); - expect(response.statusCode).toBe(200); - done(); - }); - }); - describe("Auth using email/password", () => { - it("should 403 when user doesn't exists", async done => { - const response = await platform.app.inject({ - method: "POST", - url: `${loginUrl}`, - payload: { - email: "randomEmail", - password: "randomPass", - }, - }); - expect(response.statusCode).toBe(403); - expect(response.json()).toMatchObject({ - error: "Forbidden", - message: "User doesn't exists", - statusCode: 403, - }); - done(); - }); - - it("should 403 when password doesn't match", async done => { - const user = testDbService.users[0]; - - const response = await platform.app.inject({ - method: "POST", - url: `${loginUrl}`, - payload: { - email: user.email_canonical, - password: "randomPass", - }, - }); - expect(response.statusCode).toBe(403); - expect(response.json()).toMatchObject({ - error: "Forbidden", - message: "Password doesn't match", - statusCode: 403, - }); - done(); - }); - - it("should 200 when credentials is valid", async done => { - const user = testDbService.users[0]; - - const response = await platform.app.inject({ - method: "POST", - url: `${loginUrl}`, - payload: { - email: user.email_canonical, - password: firstUserPassword, - }, - }); - expect(response.statusCode).toBe(200); - expect(response.json()).toMatchObject({ - access_token: { - time: expect.any(Number), - expiration: expect.any(Number), - refresh_expiration: expect.any(Number), - value: expect.any(String), - refresh: expect.any(String), - type: "Bearer", - }, - }); - - done(); - }); - }); - describe("Token renewal", () => { - it("should 200 when refresh from access_token", async done => { - const user = testDbService.users[0]; - - const firstResponse = await platform.app.inject({ - method: "POST", - url: `${loginUrl}`, - payload: { - email: user.email_canonical, - password: firstUserPassword, - }, - }); - - const firstRes = firstResponse.json().access_token; - expect(firstRes.value).toBeTruthy(); - - setTimeout(async () => { - const response = await platform.app.inject({ - method: "POST", - url: `${tokenRefreshUrl}`, - headers: { - authorization: `Bearer ${firstRes.value}`, - }, - }); - - const secondRes = response.json().access_token; - - expect(secondRes.expiration).toBeGreaterThan(firstRes.expiration); - expect(secondRes.refresh_expiration).toBeGreaterThan(firstRes.refresh_expiration); - - done(); - }, 2000); - }); - - it("should 200 when refresh from refresh_token", async done => { - const user = testDbService.users[0]; - - const firstResponse = await platform.app.inject({ - method: "POST", - url: `${loginUrl}`, - payload: { - email: user.email_canonical, - password: firstUserPassword, - }, - }); - - const firstRes = firstResponse.json().access_token; - expect(firstRes.refresh).toBeTruthy(); - - setTimeout(async () => { - const response = await platform.app.inject({ - method: "POST", - url: `${tokenRefreshUrl}`, - headers: { - authorization: `Bearer ${firstRes.refresh}`, - }, - }); - - const secondRes = response.json().access_token; - - expect(secondRes.expiration).toBeGreaterThan(firstRes.expiration); - expect(secondRes.refresh_expiration).toBeGreaterThan(firstRes.refresh_expiration); - - done(); - }, 2000); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/console/console-hooks.spec.ts b/twake/backend/node/test/e2e/console/console-hooks.spec.ts deleted file mode 100644 index fadbbec9..00000000 --- a/twake/backend/node/test/e2e/console/console-hooks.spec.ts +++ /dev/null @@ -1,545 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it as _it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { TestDbService } from "../utils.prepare.db"; -import { v1 as uuidv1 } from "uuid"; -import { sign as cryptoSign } from "crypto"; -import gr from "../../../src/services/global-resolver"; -import { ConsoleServiceImpl } from "../../../src/services/console/service"; -/* - THIS TESTS RUNS ONLY FOR THE CONSOLE-MODE (CONSOLE TYPE: REMOTE) -*/ - -export const it = (name: string, cb: (a: any) => void) => { - _it(name, async done => { - if (gr.services.console.consoleType === "remote") { - cb(done); - } else { - console.warn(`[skipped]: ${name} (console-mode only)`); - done(); - } - }); -}; - -describe("The console API hooks", () => { - const url = "/internal/services/console/v1/hook"; - - let platform: TestPlatform; - - let testDbService: TestDbService; - const companyId = uuidv1(); - - const firstEmail = "superman@email.com"; - const secondEmail = "C.o.n.sole_created-user@email.com"; - const thirdEmail = "superman@someogherservice.com"; - - const secret = "ohquoo1fohzeigitochaJeepoowug4Yuqueite6etojieg1oowaeraeshiW8ku8g"; - - beforeAll(async ends => { - platform = await init({ - services: [ - "database", - "message-queue", - "webserver", - "search", - "user", - "workspaces", - "auth", - "console", - "applications", - "storage", - "counter", - "statistics", - "platform-services", - ], - }); - - await platform.database.getConnector().init(); - testDbService = await TestDbService.getInstance(platform); - await testDbService.createCompany(companyId); - const ws0pk = { id: uuidv1(), company_id: companyId }; - - await testDbService.createWorkspace(ws0pk); - - await testDbService.createUser([ws0pk], { - companyRole: "member", - workspaceRole: "moderator", - username: "superman", - }); - - const console = platform.platform.getProvider("console"); - - ends(); - }); - - afterAll(async ends => { - await platform.tearDown(); - ends(); - }); - - const getPayload = (type: string, content: Record) => { - const data = { - content: content, - type: type, - } as any; - - const sign = cryptoSign( - "RSA-SHA512", - Buffer.from(JSON.stringify(data)), - "-----BEGIN PRIVATE KEY-----\nMIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQD15kALIEHoe1bt\nADG/oOqHLRgnzNoiGl8aQ6LD/9c4F5+IVP9gPxGm26haSMW2Z9doJeTucvV8syQV\nbdwc9z0NUhNhFG1RLsj0+ePgpuBfKv+uzEICrRedP7wsmWC37K1NmGZ+LzO21oeu\nLO0L39kNk+qspJnqqx8PIfUmeQ6DDkEKW/J0ISeOsBOetKiJC2n5F4Fkifh1Bq2T\nsFfW9Tz47hfLAKkNUyoulBbqX/xViUhlhFb59sxhoMesCL/VJf7OmTLvryXBW/TU\nCYFssAZXXSWOOzc2k+X2VX3QslKfCHsnCO75I+FPFd9YtFWKlaHeq36ZHlYxnYqp\nRcdixzhjAgMBAAECggEANtvoe9L1gUVLDlLVxnfC+udflTmJjMQvZW+jd3Czdisn\nB0ZXNwS7DmvA8mt72IbwMqcJnPz+sZRRv4oj6j5qW3dtJWJmRQ9X+/doFG2GbxTr\nt/aP34L4WremZpjNUBs4SrBuZUZolijkWkJhnB2Tkgjm+R87y3Pj2P9tbujhCPGM\nMQf+s5lOh/AXDyqYGyEJAZBJT3DevrB9Cl3uhYWZ0fFUz4hwATeB0Va8YT8ZJea2\nXwajg/NnOOpdSGVgv0+7zhPYvkvg8bMZeH24VxYkAfdww8vANPuk4wUwDvnh39+Q\nI4uHQGXgjf8SJ5Z7G7A5Q4r7Ma4drJDbCOfNTi84+QKBgQD+ar48b7c5ffMT/ta7\nGUfMiHCjLfauHt/1f1CkFN1OpJW2ZrS34jYusqBXos32X2gx+wsOGtzOrhkkpvgp\nL7jaZmUnQTwfn6Sx4Duq+LVVMH/uj+W/Zj24AKnoylzM9XC6D2kwKAfHs4Mg6+fe\no6VRBR/yw01ShR+YDVAEN0B7ZwKBgQD3bfCIlp1DpTjFKEBFaC4jRNJPaf8OLt/U\nYHOBwwltb406I4s13M3A1N74Btk5ycx6n/a6RHIGB6+E2xn9AnYI51M/+n9vBLPc\nnnqjOZP/7FdK7qL/g4JtXae/CyroXYaYXUNsdJttQC62QRW+xhp6fYxWt/nAcc9R\nvXmninx5pQJ/CPG3vmgvCNZktU9APVOmMoqZayMyiOyM8xSGwT36ick/eioiMFTD\nkuC0wl/23bJ890TcHqLTIHD+cUttbgU/em4fIEIq2vHB2H8JmfkkZtpNpRVp/lCZ\n2t4rGwQCPzJhxCjGiereWyb0dTPV8v3N0gtcFCzJix0i/zV4mq1WlwKBgGfV1F6N\nznun57YdmTNHcC1O4W+ATRA3rakjvPWU0u0BJmRirDYzbolhDB1MSncM7+n6HYG3\n3Z4YNZlslXBvSveblH1B8560e4K3Y0IClNCO72c71F2kY+Tfq9jpp90R+r0QTo5C\nNUPY7oF/uM9xtYT4ESAHXyFa4aUs/dPIs0odAoGBAKYqeAsbLIsb2ruMkeH5itbe\nxdgVHZ8d2Pxk1h+52SGyptuBzlt7c6Gb3KNxpIc61tZklOn5yj+QmJHN82rXGdIE\nCkdrkEmqZU52X2OInozV1Py8L7akH9wijzy5ULWqxapIE2ItnPkgcC7+x6vglkfd\nI0VcGHm8cgqCpzRaIZjH\n-----END PRIVATE KEY-----", - ); - - data.signature = sign.toString("base64"); - - return data; - }; - - describe("Common checks", () => { - it("should 404 when not POST ", async done => { - const response = await platform.app.inject({ - method: "GET", - url: `${url}`, - }); - expect(response.statusCode).toBe(404); - done(); - }); - - it("should 400 when secret key is missing", async done => { - const response = await platform.app.inject({ - method: "POST", - url: `${url}`, - payload: getPayload("a", {}), - }); - expect(response.statusCode).toBe(400); - expect(response.json()).toMatchObject({ - statusCode: 400, - error: "Bad Request", - message: "querystring should have required property 'secret_key'", - }); - done(); - }); - - it("should 403 when secret key is not valid ", async done => { - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=wrongOne`, - payload: getPayload("a", {}), - }); - expect(response.statusCode).toBe(403); - expect(response.json()).toMatchObject({ - statusCode: 403, - error: "Forbidden", - message: "Wrong secret", - }); - done(); - }); - - it("should 501 when type is not implemented", async done => { - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("unknown_type", {}), - }); - expect(response.statusCode).toBe(501); - done(); - }); - }); - - describe("User related hooks", () => { - describe("User created/updated", () => { - it("should 200 when updated existing user", async done => { - const user = testDbService.users[0]; - - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("user_updated", { - user: { - _id: user.identity_provider_id, - roles: [ - { targetCode: companyId, roleCode: "owner", applications: [{ code: "twake" }] }, - ], - email: firstEmail, - firstName: "firstName", - lastName: "lastName", - isVerified: true, - preference: { - locale: "en", - timeZone: 2, - }, - avatar: { - type: "unknown", - value: "123456.jpg", - }, - }, - }), - }); - - expect(response.statusCode).toBe(200); - - const updatedUser = await testDbService.getUserFromDb({ - id: user.id, - }); - - expect(updatedUser).toMatchObject({ - id: user.id, - email_canonical: firstEmail, - first_name: "firstName", - last_name: "lastName", - mail_verified: true, - timezone: 2, - language: "en", - picture: - gr.services.console.consoleOptions.url.replace(/\/$/, "") + "/avatars/123456.jpg", - }); - - const userRoles = await testDbService.getCompanyUser(companyId, updatedUser.id); - - expect(userRoles).toEqual( - expect.objectContaining({ - role: "owner", - }), - ); - - done(); - }); - - it("should 200 when creating new user", async done => { - const newUserConsoleId = String(testDbService.rand()); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("user_updated", { - user: { - _id: newUserConsoleId, - roles: [ - { targetCode: companyId, roleCode: "admin", applications: [{ code: "twake" }] }, - ], - email: secondEmail, - firstName: "consoleFirst", - lastName: "consoleSecond", - isVerified: true, - preference: { - locale: "ru", - timeZone: 3, - }, - avatar: { - type: "unknown", - value: "5678.jpg", - }, - }, - }), - }); - - expect(response.statusCode).toBe(200); - - const updatedUser = await testDbService.getUserFromDb({ - identity_provider_id: newUserConsoleId, - }); - - expect(updatedUser).toMatchObject({ - first_name: "consoleFirst", - last_name: "consoleSecond", - mail_verified: true, - timezone: 3, - language: "ru", - creation_date: expect.any(String), - deleted: false, - email_canonical: secondEmail.toLocaleLowerCase(), - identity_provider: "console", - identity_provider_id: newUserConsoleId, - username_canonical: "consolecreateduser", - picture: gr.services.console.consoleOptions.url.replace(/\/$/, "") + "/avatars/5678.jpg", - }); - - const userRoles = await testDbService.getCompanyUser(companyId, updatedUser.id); - - expect(userRoles).toEqual( - expect.objectContaining({ - role: "moderator", - }), - ); - done(); - }); - - it("should 200 when creating new user with same username (generating new one)", async done => { - const newUserConsoleId = String(testDbService.rand()); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("user_updated", { - user: { - _id: newUserConsoleId, - roles: [ - { targetCode: companyId, roleCode: "member", applications: [{ code: "twake" }] }, - ], - email: thirdEmail, - firstName: "superman", - lastName: "superman-lastname", - isVerified: true, - preference: { - locale: "ru", - timeZone: 3, - }, - avatar: { - type: "unknown", - value: "5679.jpg", - }, - }, - }), - }); - - expect(response.statusCode).toBe(200); - - const updatedUser = await testDbService.getUserFromDb({ - identity_provider_id: newUserConsoleId, - }); - - expect(updatedUser).toMatchObject({ - first_name: "superman", - last_name: "superman-lastname", - mail_verified: true, - timezone: 3, - language: "ru", - creation_date: expect.any(String), - deleted: false, - email_canonical: thirdEmail.toLocaleLowerCase(), - identity_provider: "console", - identity_provider_id: newUserConsoleId, - username_canonical: "superman1", - picture: gr.services.console.consoleOptions.url.replace(/\/$/, "") + "/avatars/5679.jpg", - }); - - const userRoles = await testDbService.getCompanyUser(companyId, updatedUser.id); - - expect(userRoles).toEqual( - expect.objectContaining({ - role: "member", - }), - ); - done(); - }); - - it("should 400 when creating user with email that already exists", async done => { - const newUserConsoleId = String(testDbService.rand()); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("user_updated", { - user: { - _id: newUserConsoleId, - email: firstEmail, - }, - }), - }); - - expect(response.statusCode).toBe(400); - expect(response.json()).toMatchObject({ - error: "Console user not created because email already exists", - }); - done(); - }); - }); - describe("User removed", () => { - it("should 200 when deleting", async done => { - const company = testDbService.company; - let users = await testDbService.getCompanyUsers(company.id); - let user = users.find(a => a.username_canonical == "consolecreateduser"); - expect(user).toBeTruthy(); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("company_user_deactivated", { - company: { code: company.identity_provider_id }, - user: { - _id: user.identity_provider_id, - }, - }), - }); - - expect(response.statusCode).toBe(200); - - users = await testDbService.getCompanyUsers(company.id); - user = users.find(a => a.username_canonical == "consolecreateduser"); - expect(user).toBeFalsy(); - - done(); - }); - - it("should 400 when user not found", async done => { - const company = testDbService.company; - - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("company_user_deactivated", { - company: { code: company.identity_provider_id }, - user: { - _id: 123456789, - }, - }), - }); - - expect(response.statusCode).toBe(400); - - done(); - }); - }); - }); - - describe("Company related hooks", () => { - describe("Company added", () => { - it("should 200 when company created", async done => { - const newCompanyCode = String(testDbService.rand()); - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("company_created", { - company: { - code: newCompanyCode, - stats: "stats", - plan: { name: "plan name", limits: {} }, - value: "value", - details: { - logo: "logo", - avatar: { - value: "avatar.jpg", - type: "type", - }, - name: "company name", - }, - }, - }), - }); - - expect(response.statusCode).toBe(200); - - const createdCompany = await testDbService.getCompanyFromDbByCode(newCompanyCode); - expect(createdCompany).toEqual( - expect.objectContaining({ - id: expect.any(String), - name: "company name", - plan: { name: "plan name", limits: {} }, - stats: "stats", - logo: "logo", - dateAdded: expect.any(Number), - identity_provider: "console", - identity_provider_id: newCompanyCode, - // details: - }), - ); - - done(); - }); - }); - describe("Company updated", () => { - it("should 200 when company updated", async done => { - const company = testDbService.company; - expect(company).toBeTruthy(); - expect(company.identity_provider_id).toBeTruthy(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("company_updated", { - company: { - code: company.identity_provider_id, - stats: "stats", - plan: { name: "plan name", limits: {} }, - value: "value", - details: { - logo: "logo", - avatar: { - value: "avatar.jpg", - type: "type", - }, - name: "new company name", - }, - }, - }), - }); - - expect(response.statusCode).toBe(200); - - const createdCompany = await testDbService.getCompanyFromDb(company.id); - expect(createdCompany).toEqual( - expect.objectContaining({ - id: company.id, - name: "new company name", - plan: { name: "plan name", limits: {} }, - stats: "stats", - logo: "logo", - dateAdded: expect.any(Number), - identity_provider: "console", - identity_provider_id: company.identity_provider_id, - // details: - }), - ); - - done(); - }); - }); - describe("Plan updated", () => { - it("should 200 when plan updated", async done => { - const company = testDbService.company; - expect(company).toBeTruthy(); - expect(company.identity_provider_id).toBeTruthy(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("plan_updated", { - company: { - code: company.identity_provider_id, - plan: { name: "another plan name", limits: {} }, - }, - }), - }); - - expect(response.statusCode).toBe(200); - - const createdCompany = await testDbService.getCompanyFromDb(company.id); - expect(createdCompany).toEqual( - expect.objectContaining({ - id: company.id, - name: "new company name", - plan: { name: "another plan name", limits: {} }, - stats: "stats", - logo: "logo", - dateAdded: expect.any(Number), - identity_provider: "console", - identity_provider_id: company.identity_provider_id, - // details: - }), - ); - - done(); - }); - }); - - describe("Company removed", () => { - it("should 200 when company removed", async done => { - const company = testDbService.company; - expect(company).toBeTruthy(); - expect(company.identity_provider_id).toBeTruthy(); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}?secret_key=${secret}`, - payload: getPayload("company_deleted", { - company: { - code: company.identity_provider_id, - }, - }), - }); - - expect(response.statusCode).toBe(200); - const deletedCompany = await testDbService.getCompanyFromDb(company.id); - expect(deletedCompany).toBeFalsy(); - - done(); - }); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/messages/messages.files.search.spec.ts b/twake/backend/node/test/e2e/messages/messages.files.search.spec.ts deleted file mode 100644 index 5da6fcb5..00000000 --- a/twake/backend/node/test/e2e/messages/messages.files.search.spec.ts +++ /dev/null @@ -1,165 +0,0 @@ -import "reflect-metadata"; -import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { createMessage, createParticipant, e2e_createThread } from "./utils"; -import { MessageFile } from "../../../src/services/messages/entities/message-files"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -import fs from "fs"; -import formAutoContent from "form-auto-content"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -import uuid from "node-uuid"; -import { ChannelUtils, get as getChannelUtils } from "../channels/utils"; -import gr from "../../../src/services/global-resolver"; -import User from "../../../src/services/user/entities/user"; -import { WorkspaceExecutionContext } from "../../../src/services/channels/types"; - -describe("Search files", () => { - const filesUrl = "/internal/services/files/v1"; - const messagesUrl = "/internal/services/messages/v1"; - let platform: TestPlatform; - let channelUtils: ChannelUtils; - - beforeAll(async () => { - platform = await init({ - services: ["webserver", "database", "storage", "message-queue", "files", "previews"], - }); - await platform.database.getConnector().drop(); - channelUtils = getChannelUtils(platform); - }); - - afterAll(async done => { - await platform?.tearDown(); - platform = null; - done(); - }); - - const files = [ - "../files/assets/sample.png", - "../files/assets/sample.gif", - "../files/assets/sample.pdf", - "../files/assets/sample.doc", - "../files/assets/sample.zip", - ].map(p => `${__dirname}/${p}`); - - function getContext(user?: User): WorkspaceExecutionContext { - return { - workspace: platform.workspace, - user: user || platform.currentUser, - }; - } - - it("should return uploaded files", async done => { - let channel = channelUtils.getChannel(); - channel = (await gr.services.channels.channels.save(channel, {}, getContext())).entity; - const channelId = channel.id; - - const uploadedFiles = []; - for (const i in files) { - const file = files[i]; - - const form = formAutoContent({ file: fs.createReadStream(file) }); - form.headers["authorization"] = `Bearer ${await platform.auth.getJWTToken()}`; - - const uploadedFile = await platform.app.inject({ - method: "POST", - url: `${filesUrl}/companies/${platform.workspace.company_id}/files?thumbnail_sync=1`, - ...form, - }); - - const resource = uploadedFile.json().resource; - - const messageFile: Partial = { - id: uuid.v1(), - company_id: platform.workspace.company_id, - metadata: { - source: "internal", - external_id: { - company_id: platform.workspace.company_id, - id: resource.id, - }, - ...resource.metadata, - }, - }; - - await e2e_createThread( - platform, - [ - createParticipant( - { - type: "channel", - id: channelId, - }, - platform, - ), - ], - createMessage({ text: "Some message", files: [messageFile] }), - ); - - uploadedFiles.push(uploadedFile.json().resource); - } - - await new Promise(r => setTimeout(r, 2000)); - - let resources = await search("sample"); - expect(resources.length).toEqual(5); - - resources = await search("sample", { extension: "png" }); - expect(resources.length).toEqual(1); - - resources = await search("sample", { is_file: true }); - expect(resources.length).toEqual(3); - - resources = await search("sample", { is_media: true }); - expect(resources.length).toEqual(2); - - resources = await search("sam"); - expect(resources.length).toEqual(5); - - done(); - }); - - async function search( - searchString: string, - options?: { - company_id?: string; - workspace_id?: string; - channel_id?: string; - limit?: number; - sender?: string; - is_file?: boolean; - is_media?: boolean; - extension?: string; - }, - ): Promise { - const jwtToken = await platform.auth.getJWTToken(); - - const query: any = options || {}; - - const response = await platform.app.inject({ - method: "GET", - url: `${messagesUrl}/companies/${platform.workspace.company_id}/files/search`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - ...query, - q: searchString, - }, - }); - - expect(response.statusCode).toBe(200); - const json = response.json(); - expect(json).toMatchObject({ resources: expect.any(Array) }); - const resources = json.resources; - return resources; - } -}); - -function getContext(platform: TestPlatform) { - return { - company: { id: platform.workspace.company_id }, - user: { id: platform.currentUser.id }, - }; -} diff --git a/twake/backend/node/test/e2e/messages/messages.files.spec.ts b/twake/backend/node/test/e2e/messages/messages.files.spec.ts deleted file mode 100644 index 01b50f79..00000000 --- a/twake/backend/node/test/e2e/messages/messages.files.spec.ts +++ /dev/null @@ -1,364 +0,0 @@ -import "reflect-metadata"; -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { ResourceUpdateResponse } from "../../../src/utils/types"; -import { deserialize } from "class-transformer"; -import { Thread } from "../../../src/services/messages/entities/threads"; -import { createMessage, e2e_createThread } from "./utils"; -import { MessageFile } from "../../../src/services/messages/entities/message-files"; -import { Message } from "../../../src/services/messages/entities/messages"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -import fs from "fs"; -import formAutoContent from "form-auto-content"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -import uuid, { v1 } from "node-uuid"; - -describe("The Messages Files feature", () => { - const url = "/internal/services/messages/v1"; - let platform: TestPlatform; - - beforeEach(async () => { - platform = await init({ - services: [ - "webserver", - "database", - "applications", - "search", - "storage", - "message-queue", - "user", - "search", - "files", - "websocket", - "messages", - "auth", - "realtime", - "channels", - "counter", - "statistics", - "platform-services", - ], - }); - }); - - afterEach(async () => { - await platform.tearDown(); - }); - - describe("On user send files", () => { - it("did add the files when full information is given (external source)", async done => { - const file: MessageFile = { - cache: { channel_id: "", company_id: "", user_id: "", workspace_id: "" }, - company_id: "", - created_at: 0, - id: "", - metadata: { - source: "linshare", - external_id: "1234", - name: "My LinShare File", - thumbnails: [], - }, - }; - - const response = await e2e_createThread( - platform, - [], - createMessage({ text: "Some message", files: [file] }), - ); - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - - expect(result.resource.message.files.length).toBe(1); - expect(result.resource.message.files[0].id).not.toBeFalsy(); - expect(result.resource.message.files[0].message_id).not.toBeFalsy(); - expect(result.resource.message.files[0].metadata.external_id).toBe("1234"); - expect(result.resource.message.files[0].metadata.source).toBe("linshare"); - - done(); - }); - - it("did not deduplicate files", async done => { - const file: MessageFile = { - cache: { channel_id: "", company_id: "", user_id: "", workspace_id: "" }, - company_id: "", - created_at: 0, - id: "", - metadata: { - source: "linshare", - external_id: "1234", - name: "My LinShare File", - thumbnails: [], - }, - }; - - const file2: MessageFile = { - cache: { channel_id: "", company_id: "", user_id: "", workspace_id: "" }, - company_id: "", - created_at: 0, - id: "", - metadata: { - source: "linshare2", - external_id: "5678", - name: "My LinShare 2 File", - thumbnails: [], - }, - }; - - const response = await e2e_createThread( - platform, - [], - createMessage({ text: "Some message", files: [file] }), - ); - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - - const message = result.resource.message; - const firstFileId = message.files[0].id; - - message.files.push(file2); - - const messageUpdatedRaw = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/threads/${message.thread_id}/messages/${message.id}`, - headers: { - authorization: `Bearer ${await platform.auth.getJWTToken()}`, - }, - payload: { - resource: message, - }, - }); - const messageUpdated: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - messageUpdatedRaw.body, - ); - - expect(messageUpdated.resource.files.length).toBe(2); - expect(messageUpdated.resource.files.filter(f => f.id === firstFileId).length).toBe(1); - - done(); - }); - }); -}); - -describe("List user files", () => { - const filesUrl = "/internal/services/files/v1"; - const messagesUrl = "/internal/services/messages/v1"; - let platform: TestPlatform; - - beforeAll(async () => { - platform = await init({ - services: ["webserver", "database", "storage", "message-queue", "files", "previews"], - }); - await platform.database.getConnector().drop(); - }); - - afterAll(async done => { - await platform?.tearDown(); - platform = null; - done(); - }); - - const files = [ - "../files/assets/sample.png", - "../files/assets/sample.gif", - "../files/assets/sample.pdf", - "../files/assets/sample.doc", - "../files/assets/sample.zip", - ].map(p => `${__dirname}/${p}`); - - it("should return uploaded files", async done => { - const jwtToken = await platform.auth.getJWTToken(); - - const uploadedFiles = []; - - for (const i in files) { - const file = files[i]; - - const form = formAutoContent({ file: fs.createReadStream(file) }); - form.headers["authorization"] = `Bearer ${await platform.auth.getJWTToken()}`; - - const uploadedFile = await platform.app.inject({ - method: "POST", - url: `${filesUrl}/companies/${platform.workspace.company_id}/files?thumbnail_sync=1`, - ...form, - }); - - expect(uploadedFile.statusCode).toBe(200); - - const resource = uploadedFile.json().resource; - - const messageFile: MessageFile = { - cache: { channel_id: "", company_id: "", user_id: "", workspace_id: "" }, - created_at: 0, - id: uuid.v1(), - company_id: platform.workspace.company_id, - metadata: { - source: "internal", - external_id: { - company_id: platform.workspace.company_id, - id: resource.id, - }, - ...resource.metadata, - }, - }; - - await e2e_createThread( - platform, - [], - createMessage({ text: "Some message", files: [messageFile] }), - ); - - uploadedFiles.push(uploadedFile.json().resource); - } - - function checkResource(resource) { - expect(resource).toMatchObject({ - company_id: expect.any(String), - id: expect.any(String), - created_at: expect.any(Number), - metadata: expect.any(Object), - }); - } - - let response = await platform.app.inject({ - method: "GET", - url: `${messagesUrl}/companies/${platform.workspace.company_id}/files?type=user_upload&limit=3`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - await new Promise(resolve => setTimeout(resolve, 1000)); - - expect(response.statusCode).toBe(200); - - let resources = response.json().resources; - expect(resources.length).toBe(3); - - resources.forEach(checkResource); - - const nextPageToken = response.json().next_page_token; - - response = await platform.app.inject({ - method: "GET", - url: `${messagesUrl}/companies/${platform.workspace.company_id}/files?type=user_upload&page_token=${nextPageToken}limit=100`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - await new Promise(resolve => setTimeout(resolve, 1000)); - - expect(response.statusCode).toBe(200); - - resources = response.json().resources; - expect(resources.length).toBe(5); - - expect(response.json().resources[0]).toMatchObject({ - company_id: expect.any(String), - id: expect.any(String), - created_at: expect.any(Number), - metadata: expect.any(Object), - user: expect.any(Object), - context: expect.any(Object), - }); - - resources.forEach(checkResource); - - done(); - }); - - it("should return downloaded files", async done => { - const jwtToken = await platform.auth.getJWTToken({ sub: v1() }); - const uploadedFiles = []; - for (const i in files) { - const file = files[i]; - - const form = formAutoContent({ file: fs.createReadStream(file) }); - form.headers["authorization"] = `Bearer ${await platform.auth.getJWTToken()}`; - - const uploadedFile = await platform.app.inject({ - method: "POST", - url: `${filesUrl}/companies/${platform.workspace.company_id}/files?thumbnail_sync=1`, - ...form, - }); - - const resource = uploadedFile.json().resource; - - const messageFile: MessageFile = { - cache: { channel_id: "", company_id: "", user_id: "", workspace_id: "" }, - created_at: 0, - id: uuid.v1(), - company_id: platform.workspace.company_id, - metadata: { - source: "internal", - external_id: { - company_id: platform.workspace.company_id, - id: resource.id, - }, - ...resource.metadata, - }, - }; - - const thread = await e2e_createThread( - platform, - [], - createMessage({ text: "Some message", files: [messageFile] }), - ); - - uploadedFiles.push(uploadedFile.json().resource); - - await platform.app.inject({ - method: "POST", - url: `${messagesUrl}/companies/${platform.workspace.company_id}/threads/${ - thread.json().resource.message.thread_id - }/messages/${thread.json().resource.message.id}/download/${ - thread.json().resource.message.files[0].id - }`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - } - - await new Promise(resolve => setTimeout(resolve, 1000)); - - const response = await platform.app.inject({ - method: "GET", - url: `${messagesUrl}/companies/${platform.workspace.company_id}/files?type=user_download`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - await new Promise(resolve => setTimeout(resolve, 1000)); - - expect(response.statusCode).toBe(200); - - expect(response.json().resources.length).toBe(5); - - expect(response.json().resources[0]).toMatchObject({ - company_id: expect.any(String), - id: expect.any(String), - created_at: expect.any(Number), - metadata: expect.any(Object), - user: expect.any(Object), - context: expect.any(Object), - }); - - done(); - }); -}); - -function getContext(platform: TestPlatform) { - return { - company: { id: platform.workspace.company_id }, - user: { id: platform.currentUser.id }, - }; -} diff --git a/twake/backend/node/test/e2e/messages/messages.messages.spec.ts b/twake/backend/node/test/e2e/messages/messages.messages.spec.ts deleted file mode 100644 index 2d30b256..00000000 --- a/twake/backend/node/test/e2e/messages/messages.messages.spec.ts +++ /dev/null @@ -1,199 +0,0 @@ -import "reflect-metadata"; -import { afterEach, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { - ResourceListResponse, - ResourceUpdateResponse, - User, - Workspace, -} from "../../../src/utils/types"; -import { deserialize } from "class-transformer"; -import { ParticipantObject, Thread } from "../../../src/services/messages/entities/threads"; -import { - createMessage, - createParticipant, - e2e_createChannel, - e2e_createMessage, - e2e_createThread, -} from "./utils"; -import { Message } from "../../../src/services/messages/entities/messages"; -import { v1 as uuidv1 } from "uuid"; -import { MessageWithReplies } from "../../../src/services/messages/types"; -import { TestDbService } from "../utils.prepare.db"; -import gr from "../../../src/services/global-resolver"; -import { ChannelVisibility, WorkspaceExecutionContext } from "../../../src/services/channels/types"; -import { ChannelSaveOptions } from "../../../src/services/channels/web/types"; -import { ChannelUtils, get as getChannelUtils } from "../channels/utils"; - -describe("The Messages feature", () => { - const url = "/internal/services/messages/v1"; - let platform: TestPlatform; - let testDbService: TestDbService; - let channelUtils: ChannelUtils; - - function getContext(user?: User): WorkspaceExecutionContext { - return { - workspace: platform.workspace, - user: user || platform.currentUser, - }; - } - - beforeAll(async () => { - platform = await init({ - services: [ - "webserver", - "database", - "search", - "storage", - "message-queue", - "applications", - "user", - "websocket", - "webserver", - "messages", - "files", - "auth", - "search", - "realtime", - "channels", - "counter", - "statistics", - "platform-services", - ], - }); - await gr.database.getConnector().drop(); - - channelUtils = getChannelUtils(platform); - }); - - afterEach(async () => { - await platform.tearDown(); - }); - - describe("On user use messages in a thread", () => { - it("should create a message in a thread", async () => { - const response = await e2e_createThread( - platform, - [], - createMessage({ text: "Initial thread message" }), - ); - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - const threadId = result.resource.id; - - await e2e_createMessage(platform, threadId, createMessage({ text: "Reply 1" })); - - await e2e_createMessage(platform, threadId, createMessage({ text: "Reply 2" })); - - const jwtToken = await platform.auth.getJWTToken(); - const listResponse = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/threads/${threadId}/messages`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const listResult: ResourceListResponse = deserialize( - ResourceListResponse, - listResponse.body, - ); - - expect(listResponse.statusCode).toBe(200); - expect(listResult.resources.length).toBe(3); - }); - }); - - describe("Inbox", () => { - it("Should get recent user messages", async done => { - const directChannelIn = channelUtils.getDirectChannel(); - const members = [platform.currentUser.id, uuidv1()]; - const directWorkspace: Workspace = { - company_id: platform.workspace.company_id, - workspace_id: ChannelVisibility.DIRECT, - }; - - await Promise.all([ - gr.services.channels.channels.save( - directChannelIn, - { - members, - }, - { ...getContext(), ...{ workspace: directWorkspace } }, - ), - ]); - - const recipient: ParticipantObject = { - created_at: 0, - created_by: "", - type: "channel", - company_id: directChannelIn.company_id, - workspace_id: "direct", - id: directChannelIn.id, - }; - - for (let i = 0; i < 6; i++) { - const response = await e2e_createThread( - platform, - [recipient], - createMessage({ text: `Initial thread message ${i}` }), - ); - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - const threadId = result.resource.id; - - const replies = []; - for (let j = 0; j < 3; j++) { - replies.push( - e2e_createMessage( - platform, - threadId, - createMessage({ text: `Reply ${j} to message ${i}` }), - ), - ); - } - await Promise.all(replies); - } - - const jwtToken = await platform.auth.getJWTToken({ sub: members[0] }); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/inbox?limit=5`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toEqual(200); - - const inbox: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(inbox.resources.length).toEqual(5); - - for (const resource of inbox.resources) { - expect(resource).toMatchObject({ - id: expect.any(String), - thread_id: expect.any(String), - created_at: expect.any(Number), - updated_at: expect.any(Number), - user_id: platform.currentUser.id, - application_id: null, - text: expect.any(String), - cache: { - company_id: directChannelIn.company_id, - channel_id: directChannelIn.id, - }, - }); - } - - done(); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/messages/messages.search.spec.ts b/twake/backend/node/test/e2e/messages/messages.search.spec.ts deleted file mode 100644 index f1c3afde..00000000 --- a/twake/backend/node/test/e2e/messages/messages.search.spec.ts +++ /dev/null @@ -1,264 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { TestDbService } from "../utils.prepare.db"; -import { v1 as uuidv1 } from "uuid"; -import { createMessage, e2e_createChannel, e2e_createMessage, e2e_createThread } from "./utils"; -import { ResourceUpdateResponse } from "../../../src/utils/types"; -import { ParticipantObject, Thread } from "../../../src/services/messages/entities/threads"; -import { deserialize } from "class-transformer"; -import { Channel } from "../../../src/services/channels/entities"; -import { ChannelUtils, get as getChannelUtils } from "../channels/utils"; -import { MessageFile } from "../../../src/services/messages/entities/message-files"; -import gr from "../../../src/services/global-resolver"; - -describe("The /messages API", () => { - const url = "/internal/services/messages/v1"; - let platform: TestPlatform; - let channelUtils: ChannelUtils; - - beforeAll(async ends => { - platform = await init({ - services: [ - "database", - "search", - "message-queue", - "websocket", - "webserver", - "user", - "auth", - "applications", - "storage", - "counter", - "workspaces", - "console", - "statistics", - "platform-services", - ], - }); - - await platform.database.getConnector().drop(); - channelUtils = getChannelUtils(platform); - - const testDbService = new TestDbService(platform); - await testDbService.createCompany(platform.workspace.company_id); - - const workspacePk = { - id: platform.workspace.workspace_id, - company_id: platform.workspace.company_id, - }; - - const workspacePk2 = { - id: uuidv1(), - company_id: uuidv1(), - }; - await testDbService.createWorkspace(workspacePk); - - const user = await testDbService.createUser([workspacePk], {}); - - platform.currentUser.id = user.id; - - ends(); - }); - - afterAll(async ends => { - platform && (await platform.tearDown()); - platform = null; - ends(); - }); - - describe("The GET /messages/?search=... route", () => { - it("Should find the searched messages", async done => { - // await testDbService.createWorkspace(workspacePk2); - - const channel = await createChannel(); - - const participant = { - type: "channel", - id: channel.id, - company_id: platform.workspace.company_id, - workspace_id: platform.workspace.workspace_id, - } as ParticipantObject; - - const firstThreadId = await createThread("First thread", [participant]); - await createReply(firstThreadId, "First reply of first thread"); - await createReply(firstThreadId, "Second reply of first thread"); - - const secondThreadId = await createThread("Another thread", [participant]); - await createReply(secondThreadId, "First reply of second thread"); - await createReply(secondThreadId, "Second reply of second thread is also a message"); - - //Wait for indexation to happen - await new Promise(r => setTimeout(r, 3000)); - - let resources = await search("Reply"); - expect(resources.length).toEqual(4); - - resources = await search("fdfsd"); - expect(resources.length).toEqual(0); - - resources = await search("first"); - expect(resources.length).toEqual(4); - - resources = await search("second"); - expect(resources.length).toEqual(3); - - resources = await search("another"); - expect(resources.length).toEqual(1); - - resources = await search("also"); - expect(resources.length).toEqual(1); - - resources = await search("of"); - expect(resources.length).toEqual(4); - - resources = await search("a"); - - //sleep 1s - await new Promise(r => setTimeout(r, 2000)); - - expect(resources.length).toEqual(1); - - done(); - }); - it("Filter out messages from channels we are not member of", async done => { - const anotherUserId = uuidv1(); - const channel = await e2e_createChannel(platform, [platform.currentUser.id, anotherUserId]); - const anotherChannel = await e2e_createChannel(platform, [anotherUserId], anotherUserId); //Test user is not the owner - - const participant = { - type: "channel", - id: channel.resource.id, - company_id: channel.resource.company_id, - workspace_id: channel.resource.workspace_id, - } as ParticipantObject; - - const participant2 = { - type: "channel", - id: anotherChannel.resource.id, - company_id: anotherChannel.resource.company_id, - workspace_id: anotherChannel.resource.workspace_id, - } as ParticipantObject; - - const file = new MessageFile(); - file.metadata = { external_id: undefined, source: undefined, name: "test" }; - - const firstThreadId = await createThread("Filtered thread", [participant]); - await createReply(firstThreadId, "Filtered message 1-1"); - await createReply(firstThreadId, "Filtered message 1-2"); - await createReply(firstThreadId, "Filtered message 1-3"); - await createReply(firstThreadId, "Filtered message 1-4", { files: [file] }); - - const secondThreadId = await createThread("Filtered thread 2", [participant2], anotherUserId); - await createReply(secondThreadId, "Filtered message 2-1"); - await createReply(secondThreadId, "Filtered message 2-2"); - await createReply(secondThreadId, "Filtered message 2-3"); - await createReply(secondThreadId, "Filtered message 2-4"); - - const thirdThreadId = await createThread("Filtered thread 3", [participant]); - await createReply(thirdThreadId, "Filtered message 3-1"); - await createReply(thirdThreadId, "Filtered message 3-2", { userId: anotherUserId }); - await createReply(thirdThreadId, "Filtered message 3-3", { userId: anotherUserId }); - await createReply(thirdThreadId, "Filtered message 3-4", { - userId: anotherUserId, - files: [file], - }); - - //Wait for indexation to happen - await new Promise(r => setTimeout(r, 3000)); - - // no limit - const resources0 = await search("Filtered", { limit: 10000 }); - expect(resources0.length).toEqual(10); - - const resources = await search("Filtered", { limit: 9 }); - expect(resources.length).toEqual(9); - - // check for the empty result set - const resources2 = await search("Nothing", { limit: 10 }); - expect(resources2.length).toEqual(0); - - // check for the user - const resources3 = await search("Filtered", { sender: anotherUserId }); - expect(resources3.length).toEqual(3); - - // check for the files - const resources4 = await search("Filtered", { has_files: true }); - expect(resources4.length).toEqual(2); - - // check for the user and files - const resources5 = await search("Filtered", { sender: anotherUserId, has_files: true }); - expect(resources5.length).toEqual(1); - - done(); - }); - }); - - async function createChannel(userId = platform.currentUser.id): Promise { - const channel = channelUtils.getChannel(userId); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - channelUtils.getContext({ id: userId }), - ); - - return creationResult.entity; - } - - async function createThread(text, participants: ParticipantObject[], owner?: string) { - const response = await e2e_createThread( - platform, - participants, - createMessage({ text: text, user_id: owner }), - owner, - ); - - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - return result.resource.id; - } - - async function createReply(threadId, text, options?: { userId?: string; files?: MessageFile[] }) { - const cr = options?.userId ? { currentUser: { id: options?.userId } } : undefined; - - const message = { text, ...(options?.files ? { files: options.files } : {}) }; - - return e2e_createMessage(platform, threadId, createMessage(message, cr as TestPlatform)); - } - - async function search( - searchString: string, - options?: { - company_id?: string; - workspace_id?: string; - channel_id?: string; - limit?: number; - sender?: string; - has_files?: boolean; - }, - ): Promise { - const jwtToken = await platform.auth.getJWTToken(); - - const query: any = options || {}; - - const response = await platform.app.inject({ - method: "GET", - // url: `${url}/companies/${platform.workspace.company_id}/woskpaces/`, - url: `${url}/companies/${platform.workspace.company_id}/search`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - query: { - ...query, - q: searchString, - }, - }); - - expect(response.statusCode).toBe(200); - const json = response.json(); - expect(json).toMatchObject({ resources: expect.any(Array) }); - const resources = json.resources; - return resources; - } -}); diff --git a/twake/backend/node/test/e2e/messages/messages.threads.spec.ts b/twake/backend/node/test/e2e/messages/messages.threads.spec.ts deleted file mode 100644 index 98d798a2..00000000 --- a/twake/backend/node/test/e2e/messages/messages.threads.spec.ts +++ /dev/null @@ -1,249 +0,0 @@ -import "reflect-metadata"; -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { ResourceUpdateResponse } from "../../../src/utils/types"; -import { deserialize } from "class-transformer"; -import { v1 as uuidv1, v4 as uuidv4 } from "uuid"; -import { Thread } from "../../../src/services/messages/entities/threads"; -import { createMessage, createParticipant, e2e_createThread } from "./utils"; -import gr from "../../../src/services/global-resolver"; - -describe("The Messages Threads feature", () => { - const url = "/internal/services/messages/v1"; - let platform: TestPlatform; - - beforeEach(async () => { - platform = await init({ - services: [ - "webserver", - "database", - "applications", - "search", - "storage", - "message-queue", - "user", - "search", - "files", - "websocket", - "messages", - "auth", - "realtime", - "channels", - "counter", - "statistics", - "platform-services", - ], - }); - }); - - afterEach(async () => { - await platform.tearDown(); - }); - - describe("On user manage threads", () => { - it("should create new thread", async done => { - const response = await e2e_createThread( - platform, - [ - createParticipant( - { - type: "user", - id: platform.currentUser.id, - }, - platform, - ), - ], - createMessage( - { - text: "Hello!", - }, - platform, - ), - ); - - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resource?.created_by).toBe(platform.currentUser.id); - expect(result.resource.participants.length).toBe(1); - expect(result.resource.participants[0]).toMatchObject({ - type: "user", - id: platform.currentUser.id, - created_by: platform.currentUser.id, - }); - expect(result.resource.participants[0].created_at).toBeDefined(); - - done(); - }); - - it("should enforce requester in thread participants", async done => { - const response = await e2e_createThread( - platform, - [ - createParticipant( - { - type: "user", - id: uuidv1(), - }, - platform, - ), - ], - createMessage( - { - text: "Hello!", - }, - platform, - ), - ); - - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resource).toMatchObject({ - created_by: platform.currentUser.id, - }); - expect(result.resource.participants.length).toBe(2); - expect( - result.resource.participants.filter(p => p.id === platform.currentUser.id)[0], - ).toMatchObject({ - type: "user", - id: platform.currentUser.id, - }); - - done(); - }); - - it("should update thread participants when add participant", async done => { - //Create thread - const thread = await gr.services.messages.threads.save( - { - id: undefined, - participants: [ - { - type: "user", - id: platform.currentUser.id, - company_id: platform.workspace.company_id, - }, - ], - }, - { - message: createMessage( - { - text: "Hello!", - }, - platform, - ), - }, - getContext(platform), - ); - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/threads/${thread.entity.id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: {}, - options: { - participants: { - add: [ - { - type: "user", - id: uuidv1(), - }, - ], - }, - }, - }, - }); - - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resource.participants.length).toBe(2); - - done(); - }); - - it("should update thread participants when remove participant", async done => { - //Create thread - const thread = await gr.services.messages.threads.save( - { - id: undefined, - participants: [ - { - type: "user", - id: platform.currentUser.id, - company_id: platform.workspace.company_id, - }, - { - type: "channel", - id: uuidv4(), - workspace_id: platform.workspace.workspace_id, - company_id: platform.workspace.company_id, - }, - ], - }, - { - message: createMessage( - { - text: "Hello!", - }, - platform, - ), - }, - getContext(platform), - ); - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/threads/${thread.entity.id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: {}, - options: { - participants: { - remove: [ - { - type: "user", - id: platform.currentUser.id, - }, - ], - }, - }, - }, - }); - - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resource.participants.length).toBe(1); - - done(); - }); - }); -}); - -function getContext(platform: TestPlatform) { - return { - company: { id: platform.workspace.company_id }, - user: { id: platform.currentUser.id }, - }; -} diff --git a/twake/backend/node/test/e2e/messages/messages.user-bookmarks.realtime.spec.ts b/twake/backend/node/test/e2e/messages/messages.user-bookmarks.realtime.spec.ts deleted file mode 100644 index a407e009..00000000 --- a/twake/backend/node/test/e2e/messages/messages.user-bookmarks.realtime.spec.ts +++ /dev/null @@ -1,143 +0,0 @@ -import "reflect-metadata"; -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -import io from "socket.io-client"; -import { init, TestPlatform } from "../setup"; -import gr from "../../../src/services/global-resolver"; - -describe("The Bookmarks Realtime feature", () => { - const url = "/internal/services/messages/v1"; - let platform: TestPlatform; - let socket: SocketIOClient.Socket; - - beforeEach(async () => { - platform = await init({ - services: [ - "webserver", - "database", - "search", - "storage", - "message-queue", - "files", - "user", - "websocket", - "webserver", - "messages", - "applications", - "auth", - "search", - "realtime", - "channels", - "counter", - "statistics", - "platform-services", - ], - }); - }); - - afterEach(async () => { - await platform.tearDown(); - platform = null; - }); - - function connect() { - socket = io.connect("http://localhost:3000", { path: "/socket" }); - socket.connect(); - } - - describe("On bookmark creation", () => { - it("should notify the client", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const roomToken = "twake"; - - connect(); - socket.on("connect", () => { - socket - .emit("authenticate", { token: jwtToken }) - .on("authenticated", () => { - socket.on("realtime:join:error", () => done(new Error("Should not occur"))); - socket.on("realtime:join:success", async () => { - await gr.services.messages.userBookmarks.save( - { - company_id: platform.workspace.company_id, - user_id: platform.currentUser.id, - name: "mybookmarksaved", - id: undefined, - }, - getContext(platform), - ); - }); - socket.on("realtime:resource", (event: any) => { - expect(event.type).toEqual("user_message_bookmark"); - expect(event.action).toEqual("saved"); - expect(event.resource.name).toEqual("mybookmarksaved"); - done(); - }); - socket.emit("realtime:join", { - name: `/companies/${platform.workspace.company_id}/messages/bookmarks`, - token: roomToken, - }); - }) - .on("unauthorized", () => { - done(new Error("Should not occur")); - }); - }); - }); - }); - - describe("On bookmark removal", () => { - it("should notify the client", async done => { - const instance = await gr.services.messages.userBookmarks.save( - { - company_id: platform.workspace.company_id, - user_id: platform.currentUser.id, - name: "mybookmark", - id: undefined, - }, - getContext(platform), - ); - - const jwtToken = await platform.auth.getJWTToken(); - const roomToken = "twake"; - - connect(); - socket.on("connect", () => { - socket - .emit("authenticate", { token: jwtToken }) - .on("authenticated", () => { - socket.on("realtime:join:error", () => done(new Error("Should not occur"))); - socket.on("realtime:join:success", async () => { - await gr.services.messages.userBookmarks.delete( - { - company_id: platform.workspace.company_id, - user_id: platform.currentUser.id, - id: instance.entity.id, - }, - getContext(platform), - ); - }); - socket.on("realtime:resource", (event: any) => { - expect(event.type).toEqual("user_message_bookmark"); - expect(event.action).toEqual("deleted"); - done(); - }); - socket.emit("realtime:join", { - name: `/companies/${platform.workspace.company_id}/messages/bookmarks`, - token: roomToken, - }); - }) - .on("unauthorized", () => { - done(new Error("Should not occur")); - }); - }); - }); - }); -}); - -function getContext(platform: TestPlatform) { - return { - company: { id: platform.workspace.company_id }, - user: { id: platform.currentUser.id }, - }; -} diff --git a/twake/backend/node/test/e2e/messages/messages.user-bookmarks.spec.ts b/twake/backend/node/test/e2e/messages/messages.user-bookmarks.spec.ts deleted file mode 100644 index 68cb0240..00000000 --- a/twake/backend/node/test/e2e/messages/messages.user-bookmarks.spec.ts +++ /dev/null @@ -1,217 +0,0 @@ -import "reflect-metadata"; -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { UserMessageBookmark } from "../../../src/services/messages/entities/user-message-bookmarks"; -import { ResourceListResponse, ResourceUpdateResponse } from "../../../src/utils/types"; -import { deserialize } from "class-transformer"; -import { v4 as uuidv4 } from "uuid"; -import gr from "../../../src/services/global-resolver"; - -describe("The Messages User Bookmarks feature", () => { - const url = "/internal/services/messages/v1"; - let platform: TestPlatform; - - beforeEach(async () => { - platform = await init({ - services: [ - "webserver", - "database", - "search", - "files", - "storage", - "applications", - "message-queue", - "user", - "search", - "websocket", - "messages", - "auth", - "realtime", - "channels", - "counter", - "statistics", - "platform-services", - ], - }); - }); - - afterEach(async () => { - await platform.tearDown(); - }); - - describe("On user manage bookmmarks", () => { - it("should create new bookmark", async done => { - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/preferences/bookmarks/`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - name: "mybookmark", - }, - }, - }); - - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resource).toMatchObject({ - user_id: platform.currentUser.id, - name: "mybookmark", - }); - - const context = getContext(platform); - - const list = await gr.services.messages.userBookmarks.list({ - user_id: context.user.id, - company_id: context.company.id, - }); - expect(list.getEntities().length).toBe(1); - - done(); - }); - - it("should prevent duplicated bookmark", async done => { - // const uuid = uuidv4(); - - const context = getContext(platform); - - const data = await gr.services.messages.userBookmarks.save( - { - company_id: platform.workspace.company_id, - user_id: platform.currentUser.id, - name: "mybookmark", - test: "123", - }, - context, - ); - const uuid = data.entity.id; - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/preferences/bookmarks/`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - name: "mybookmark", - }, - }, - }); - - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resource).toMatchObject({ - id: uuid, - user_id: platform.currentUser.id, - name: "mybookmark", - }); - - const list = await gr.services.messages.userBookmarks.list({ - user_id: context.user.id, - company_id: context.company.id, - }); - expect(list.getEntities().length).toBe(1); - - done(); - }); - - it("should remove bookmark", async done => { - const id = uuidv4(); - const context = getContext(platform); - - await gr.services.messages.userBookmarks.save( - { - id, - company_id: platform.workspace.company_id, - user_id: platform.currentUser.id, - name: "mybookmark", - }, - context, - ); - - let list = await gr.services.messages.userBookmarks.list({ - user_id: context.user.id, - company_id: context.company.id, - }); - expect(list.getEntities().length).toBe(1); - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${platform.workspace.company_id}/preferences/bookmarks/${id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toBe(200); - - list = await gr.services.messages.userBookmarks.list({ - user_id: context.user.id, - company_id: context.company.id, - }); - expect(list.getEntities().length).toBe(0); - - done(); - }); - - it("should list bookmarks", async done => { - const context = getContext(platform); - - await gr.services.messages.userBookmarks.save( - { - id: uuidv4(), - company_id: platform.workspace.company_id, - user_id: platform.currentUser.id, - name: "mybookmark", - }, - context, - ); - - const list = await gr.services.messages.userBookmarks.list({ - user_id: context.user.id, - company_id: context.company.id, - }); - expect(list.getEntities().length).toBe(1); - - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/preferences/bookmarks`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const result: ResourceListResponse = deserialize( - ResourceListResponse, - response.body, - ); - - expect(response.statusCode).toBe(200); - expect(result.resources.length).toBe(1); - expect(result.resources[0].name).toBe("mybookmark"); - done(); - }); - }); -}); - -function getContext(platform: TestPlatform) { - return { - company: { id: platform.workspace.company_id }, - user: { id: platform.currentUser.id }, - }; -} diff --git a/twake/backend/node/test/e2e/messages/messages.views.channel.spec.ts b/twake/backend/node/test/e2e/messages/messages.views.channel.spec.ts deleted file mode 100644 index 14b00298..00000000 --- a/twake/backend/node/test/e2e/messages/messages.views.channel.spec.ts +++ /dev/null @@ -1,144 +0,0 @@ -import "reflect-metadata"; -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { ResourceListResponse, ResourceUpdateResponse } from "../../../src/utils/types"; -import { deserialize } from "class-transformer"; -import { v4 as uuidv4 } from "uuid"; -import { Thread } from "../../../src/services/messages/entities/threads"; -import { - createMessage, - createParticipant, - e2e_createChannel, - e2e_createMessage, - e2e_createThread, -} from "./utils"; -import { MessageWithReplies } from "../../../src/services/messages/types"; - -describe("The Messages feature", () => { - const url = "/internal/services/messages/v1"; - let platform: TestPlatform; - - beforeEach(async () => { - platform = await init({ - services: [ - "webserver", - "database", - "search", - "storage", - "files", - "applications", - "message-queue", - "user", - "websocket", - "messages", - "auth", - "search", - "realtime", - "channels", - "counter", - "statistics", - "platform-services", - ], - }); - }); - - afterEach(async () => { - await platform.tearDown(); - }); - - describe("On user use messages in channel view", () => { - it("should create a message and retrieve it in channel view", async () => { - const channel = await e2e_createChannel(platform, [platform.currentUser.id]); - - const response = await e2e_createThread( - platform, - [ - createParticipant( - { - type: "channel", - id: channel.resource.id, - workspace_id: channel.resource.workspace_id, - company_id: channel.resource.company_id, - }, - platform, - ), - ], - createMessage({ text: "Initial thread 1 message" }), - ); - const result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - response.body, - ); - const threadId = result.resource.id; - - await e2e_createMessage(platform, threadId, createMessage({ text: "Reply 1" })); - - await e2e_createMessage(platform, threadId, createMessage({ text: "Reply 2" })); - - await e2e_createThread( - platform, - [ - createParticipant( - { - type: "channel", - id: channel.resource.id, - workspace_id: channel.resource.workspace_id, - company_id: channel.resource.company_id, - }, - platform, - ), - ], - createMessage({ text: "Initial thread 2 message" }), - ); - - await e2e_createMessage(platform, threadId, createMessage({ text: "Reply 3" })); - - await e2e_createThread( - platform, - [ - createParticipant( - { - type: "channel", - id: channel.resource.id, - workspace_id: channel.resource.workspace_id, - company_id: channel.resource.company_id, - }, - platform, - ), - ], - createMessage({ text: "Initial thread 3 message" }), - ); - - const jwtToken = await platform.auth.getJWTToken(); - const listResponse = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${channel.resource.company_id}/workspaces/${channel.resource.workspace_id}/channels/${channel.resource.id}/feed?replies_per_thread=3&include_users=1`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - const listResult: ResourceListResponse = deserialize( - ResourceListResponse, - listResponse.body, - ); - - await new Promise(resolve => setTimeout(resolve, 5000)); - - expect(listResponse.statusCode).toBe(200); - expect(listResult.resources.length).toBe(3); - - expect(listResult.resources[0].text).toBe("Initial thread 2 message"); - expect(listResult.resources[1].text).toBe("Initial thread 1 message"); - expect(listResult.resources[2].text).toBe("Initial thread 3 message"); - - expect(listResult.resources[0].stats.replies).toBe(1); - expect(listResult.resources[1].stats.replies).toBe(4); //Thread initial message + 3 replies - expect(listResult.resources[2].stats.replies).toBe(1); - - expect(listResult.resources[1].last_replies.length).toBe(3); //We requested 3 replies per posts - expect(listResult.resources[1].last_replies[0].text).toBe("Reply 1"); //Check order is OK - expect(listResult.resources[1].last_replies[2].text).toBe("Reply 3"); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/messages/utils.ts b/twake/backend/node/test/e2e/messages/utils.ts deleted file mode 100644 index 6a5380ec..00000000 --- a/twake/backend/node/test/e2e/messages/utils.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { deserialize } from "class-transformer"; -import { - getInstance as getMessageInstance, - Message, -} from "../../../src/services/messages/entities/messages"; -import { ParticipantObject } from "../../../src/services/messages/entities/threads"; -import { Channel, ResourceCreateResponse } from "../../../src/utils/types"; -import { TestPlatform } from "../setup"; - -const url = "/internal/services/messages/v1"; - -export const e2e_createChannel = async ( - platform: TestPlatform, - members: string[], - owner?: string, -) => { - const jwtToken = await platform.auth.getJWTToken({ sub: owner || platform.currentUser.id }); - const response = await platform.app.inject({ - method: "POST", - url: `/internal/services/channels/v1/companies/${platform.workspace.company_id}/workspaces/direct/channels`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - options: { - members, - }, - resource: { - description: "A direct channel description", - visibility: "direct", - }, - }, - }); - const channelCreateResult: ResourceCreateResponse = deserialize( - ResourceCreateResponse, - response.body, - ); - return channelCreateResult; -}; - -export const e2e_createThread = async ( - platform: TestPlatform, - participants: ParticipantObject[], - message: Message, - owner?: string, -) => { - const jwtToken = await platform.auth.getJWTToken({ sub: owner || platform.currentUser.id }); - const res = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/threads`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: { - participants: participants || [], - }, - options: { - message: message, - }, - }, - }); - await new Promise(resolve => setTimeout(resolve, 200)); - return res; -}; - -export const e2e_createMessage = async ( - platform: TestPlatform, - threadId: string, - message: Message, -) => { - const jwtToken = await platform.auth.getJWTToken( - message.user_id ? { sub: message.user_id } : undefined, - ); - const res = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/threads/${threadId}/messages`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - payload: { - resource: message, - }, - }); - await new Promise(resolve => setTimeout(resolve, 200)); - return res; -}; - -export const createMessage = (message: Partial, platform?: TestPlatform): Message => { - return getMessageInstance({ - //Default values - created_at: new Date().getTime(), - user_id: platform?.currentUser.id || undefined, - - ...message, - }); -}; - -export const createParticipant = ( - participant: Partial, - platform?: TestPlatform, -): ParticipantObject => { - return { - //Default values: - created_at: new Date().getTime(), - created_by: platform?.currentUser.id || "", - company_id: platform?.workspace.company_id || "", - workspace_id: platform?.workspace.workspace_id || "", - id: platform?.currentUser.id || "", - type: "user", - - ...participant, - }; -}; diff --git a/twake/backend/node/test/e2e/notifications/mention.spec.ts b/twake/backend/node/test/e2e/notifications/mention.spec.ts deleted file mode 100644 index bc3ae7d8..00000000 --- a/twake/backend/node/test/e2e/notifications/mention.spec.ts +++ /dev/null @@ -1,381 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; -import { v1 as uuidv1 } from "uuid"; -import { init, TestPlatform } from "../setup"; -import { Channel } from "../../../src/services/channels/entities/channel"; -import { ChannelMemberNotificationLevel } from "../../../src/services/channels/types"; -import { User } from "../../../src/utils/types"; -import { - ChannelMemberUtils, - ChannelUtils, - get as getChannelUtils, - getMemberUtils, -} from "../channels/utils"; -import { MessageNotification } from "../../../src/services/messages/types"; -import { - IncomingPubsubMessage, - MessageQueueServiceAPI, -} from "../../../src/core/platform/services/message-queue/api"; -import { ChannelMember } from "../../../src/services/channels/entities"; -import { MentionNotification } from "../../../src/services/notifications/types"; -import gr from "../../../src/services/global-resolver"; - -describe("The notification for user mentions", () => { - let platform: TestPlatform; - let channelUtils: ChannelUtils; - let channelMemberUtils: ChannelMemberUtils; - let pubsubService: MessageQueueServiceAPI; - // eslint-disable-next-line @typescript-eslint/no-empty-function - let pubsubHandler: (message: IncomingPubsubMessage) => void = _ => {}; - - beforeAll(async () => { - platform = await init({ - services: [ - "webserver", - "database", - "search", - "storage", - "message-queue", - "user", - "websocket", - "channels", - "auth", - "search", - "applications", - "files", - "push", - "notifications", - "counter", - "statistics", - "platform-services", - ], - }); - channelUtils = getChannelUtils(platform); - channelMemberUtils = getMemberUtils(platform); - pubsubService = platform.platform.getProvider("message-queue"); - pubsubService.subscribe("notification:mentions", message => { - pubsubHandler(message); - }); - }); - - afterAll(async () => { - await platform?.tearDown(); - platform = null; - }); - - async function createChannel(): Promise { - const channel = channelUtils.getChannel(platform.currentUser.id); - const creationResult = await gr.services.channels.channels.save( - channel, - {}, - channelUtils.getContext(), - ); - - return creationResult.entity; - } - - async function joinChannel( - userId: string, - channel: Channel, - notificationLevel?: ChannelMemberNotificationLevel, - ): Promise { - const user: User = { id: userId }; - const member = channelMemberUtils.getMember(channel, user); - - if (notificationLevel) member.notification_level = notificationLevel; - - const memberCreationResult = await gr.services.channels.members.save( - member, - channelUtils.getChannelContext(channel, user), - ); - return memberCreationResult.entity; - } - - async function updateNotificationLevel( - channel: Channel, - member: ChannelMember, - level: ChannelMemberNotificationLevel, - ): Promise { - member.notification_level = level; - await gr.services.channels.members.save( - member, - channelUtils.getChannelContext(channel, { id: member.user_id }), - ); - - return; - } - - function pushMessage(message: MessageNotification): Promise { - return pubsubService.publish("message:created", { - data: message, - }); - } - - it("should mention all users when preferences are MENTION", async done => { - const threadId = uuidv1(); - const messageId = uuidv1(); - const unknownUser = uuidv1(); - const channel = await createChannel(); - const member = await joinChannel( - platform.currentUser.id, - channel, - ChannelMemberNotificationLevel.MENTIONS, - ); - const member2 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.MENTIONS); - const member3 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.MENTIONS); - - pushMessage({ - channel_id: channel.id, - company_id: channel.company_id, - creation_date: Date.now(), - id: messageId, - sender: platform.currentUser.id, - thread_id: threadId, - workspace_id: channel.workspace_id, - mentions: { - users: [member.user_id, member2.user_id, unknownUser, member3.user_id], - }, - title: "test", - text: "should mention all users when preferences are MENTION ones", - }); - - const message = await new Promise>( - resolve => (pubsubHandler = resolve), - ); - expect(message.data.mentions.users).not.toContain(member.user_id); //The sender is not in the notified users - expect(message.data.mentions.users).toContain(member2.user_id); - expect(message.data.mentions.users).toContain(member3.user_id); - expect(message.data.mentions.users).not.toContain(unknownUser); - - done(); - }); - - it("should mention all users when preferences are default ones (ALL)", async done => { - const messageId = uuidv1(); - const unknownUser = uuidv1(); - const channel = await createChannel(); - const member = await joinChannel(platform.currentUser.id, channel); - const member2 = await joinChannel(uuidv1(), channel); - const member3 = await joinChannel(uuidv1(), channel); - - await new Promise(resolve => setTimeout(resolve, 500)); //Wait for the channel members to be created on all services - - pushMessage({ - channel_id: channel.id, - company_id: channel.company_id, - creation_date: Date.now(), - id: messageId, - sender: platform.currentUser.id, - thread_id: messageId, //Only thread initial messages generate notifications - workspace_id: channel.workspace_id, - title: "test", - text: "should mention all users when preferences are default ones (ALL)", - }); - - const message = await new Promise>( - resolve => (pubsubHandler = resolve), - ); - expect(message.data.mentions.users).not.toContain(member.user_id); //The sender is not in the notified users - expect(message.data.mentions.users).toContain(member2.user_id); - expect(message.data.mentions.users).toContain(member3.user_id); - expect(message.data.mentions.users).not.toContain(unknownUser); - - done(); - }); - - it("should not mention users with preferences ALL for replies of threads there are not member of", async done => { - const threadId = uuidv1(); - const messageId = uuidv1(); - const channel = await createChannel(); - const member = await joinChannel(platform.currentUser.id, channel); - const member2 = await joinChannel(uuidv1(), channel); - const member3 = await joinChannel(uuidv1(), channel); - - await new Promise(resolve => setTimeout(resolve, 500)); //Wait for the channel members to be created on all services - - pushMessage({ - channel_id: channel.id, - company_id: channel.company_id, - creation_date: Date.now(), - id: messageId, - sender: platform.currentUser.id, - thread_id: threadId, - workspace_id: channel.workspace_id, - mentions: { - users: [member.user_id, member2.user_id], - }, - title: "test", - text: "should mention all users when preferences are default ones (ALL)", - }); - - const message = await new Promise>( - resolve => (pubsubHandler = resolve), - ); - expect(message.data.mentions.users).not.toContain(member.user_id); //The sender is not in the notified users - expect(message.data.mentions.users).not.toContain(member3.user_id); - - done(); - }); - - it("should not mention user when notification level is set to NONE", async done => { - const threadId = uuidv1(); - const messageId = uuidv1(); - const unknownUser = uuidv1(); - const channel = await createChannel(); - const member = await joinChannel( - platform.currentUser.id, - channel, - ChannelMemberNotificationLevel.MENTIONS, - ); - const member2 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.NONE); - const member3 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.MENTIONS); - - await new Promise(resolve => setTimeout(resolve, 500)); //Wait for the channel members to be created on all services - - pushMessage({ - channel_id: channel.id, - company_id: channel.company_id, - creation_date: Date.now(), - id: messageId, - sender: platform.currentUser.id, - thread_id: threadId, - workspace_id: channel.workspace_id, - mentions: { - users: [member.user_id, member2.user_id, unknownUser, member3.user_id], - }, - title: "test", - text: "should not mention user when notification level is set to NONE", - }); - - const message = await new Promise>( - resolve => (pubsubHandler = resolve), - ); - expect(message.data.mentions.users).not.toContain(member.user_id); - expect(message.data.mentions.users).toContain(member3.user_id); - expect(message.data.mentions.users).not.toContain(member2.user_id); - - done(); - }); - - it("should mention user when notification level is set to channel mention and notification is for @all", async done => { - const threadId = uuidv1(); - const messageId = uuidv1(); - const channel = await createChannel(); - const member = await joinChannel( - platform.currentUser.id, - channel, - ChannelMemberNotificationLevel.MENTIONS, - ); - const member2 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.MENTIONS); - const member3 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.ME); - - await new Promise(resolve => setTimeout(resolve, 500)); //Wait for the channel members to be created on all services - - pushMessage({ - channel_id: channel.id, - company_id: channel.company_id, - creation_date: Date.now(), - id: messageId, - sender: platform.currentUser.id, - thread_id: threadId, - workspace_id: channel.workspace_id, - mentions: { - users: [], - specials: ["all"], - }, - title: "test", - text: "should mention user when notification level is set to channel mention and notification is for @all", - }); - - const message = await new Promise>( - resolve => (pubsubHandler = resolve), - ); - expect(message.data.mentions.users).not.toContain(member.user_id); - expect(message.data.mentions.users).toContain(member2.user_id); - expect(message.data.mentions.users).not.toContain(member3.user_id); - - done(); - }); - - it("should mention user when notification level is set to channel mention and notification is for @here", async done => { - const threadId = uuidv1(); - const messageId = uuidv1(); - const channel = await createChannel(); - const member = await joinChannel(platform.currentUser.id, channel); - const member2 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.MENTIONS); - const member3 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.ME); - - await new Promise(resolve => setTimeout(resolve, 500)); //Wait for the channel members to be created on all services - - pushMessage({ - channel_id: channel.id, - company_id: channel.company_id, - creation_date: Date.now(), - id: messageId, - sender: platform.currentUser.id, - thread_id: threadId, - workspace_id: channel.workspace_id, - mentions: { - users: [], - specials: ["here"], - }, - title: "test", - text: "should mention user when notification level is set to channel mention and notification is for @here", - }); - - const message = await new Promise>( - resolve => (pubsubHandler = resolve), - ); - - //Sender dont get notified - expect(message.data.mentions.users).not.toContain(member.user_id); - expect(message.data.mentions.users).toContain(member2.user_id); - expect(message.data.mentions.users).not.toContain(member3.user_id); - - done(); - }); - - it("should mention user when notification level is set to ME and updated notification later", async done => { - const threadId = uuidv1(); - const messageId = uuidv1(); - const channel = await createChannel(); - const member = await joinChannel( - platform.currentUser.id, - channel, - ChannelMemberNotificationLevel.NONE, - ); - const member2 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.NONE); - const member3 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.NONE); - - await new Promise(resolve => setTimeout(resolve, 1000)); //Wait for the channel members to be created - - await updateNotificationLevel(channel, member, ChannelMemberNotificationLevel.MENTIONS); - await updateNotificationLevel(channel, member2, ChannelMemberNotificationLevel.ME); - await updateNotificationLevel(channel, member3, ChannelMemberNotificationLevel.MENTIONS); - - await new Promise(resolve => setTimeout(resolve, 1000)); //Wait for the channel members to be created - - pushMessage({ - channel_id: channel.id, - company_id: channel.company_id, - creation_date: Date.now(), - id: messageId, - sender: platform.currentUser.id, - thread_id: threadId, - workspace_id: channel.workspace_id, - mentions: { - users: [member2.user_id], - }, - title: "test", - text: "should mention user when notification level is set to ME and updated notification later", - }); - - const message = await new Promise>( - resolve => (pubsubHandler = resolve), - ); - expect(message.data.mentions.users).not.toContain(member.user_id); - expect(message.data.mentions.users).not.toContain(member3.user_id); - expect(message.data.mentions.users).toContain(member2.user_id); - - done(); - }); -}); diff --git a/twake/backend/node/test/e2e/workspaces/workspace-pending-users.spec.ts b/twake/backend/node/test/e2e/workspaces/workspace-pending-users.spec.ts deleted file mode 100644 index cc021fcb..00000000 --- a/twake/backend/node/test/e2e/workspaces/workspace-pending-users.spec.ts +++ /dev/null @@ -1,437 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it as _it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { TestDbService } from "../utils.prepare.db"; -import { v1 as uuidv1 } from "uuid"; -import gr from "../../../src/services/global-resolver"; -/* - THIS TESTS RUNS ONLY FOR THE CONSOLE-MODE (CONSOLE TYPE: INTERNAL) -*/ - -export const it = (name: string, cb: (a: any) => void) => { - _it(name, async done => { - if (gr.services.console.consoleType === "internal") { - cb(done); - } else { - console.warn(`[skipped]: ${name} (no-console mode only)`); - done(); - } - }); -}; - -describe("The /workspace/pending users API", () => { - const url = "/internal/services/workspaces/v1"; - let platform: TestPlatform; - - let testDbService: TestDbService; - - const nonExistentId = uuidv1(); - const companyId = uuidv1(); - - const firstEmail = "first@test-user.com"; - const secondEmail = "second@test-user.com"; - const thirdEmail = "third@test-user.com"; - const fourthUser = "fourth@test-user.com"; - const emailForExistedUser = "exist@email.com"; - - async function doTheTest() { - return Promise.resolve(gr.services.console.consoleType === "remote"); - } - - beforeAll(async ends => { - platform = await init({ - services: [ - "user", - "database", - "message-queue", - "webserver", - "search", - "workspaces", - "applications", - "auth", - "console", - "storage", - "counter", - "statistics", - "platform-services", - ], - }); - - await platform.database.getConnector().drop(); - await platform.database.getConnector().init(); - testDbService = new TestDbService(platform); - await testDbService.createCompany(companyId); - const ws0pk = { id: uuidv1(), company_id: companyId }; - const ws1pk = { id: uuidv1(), company_id: companyId }; - const ws2pk = { id: uuidv1(), company_id: companyId }; - await testDbService.createWorkspace(ws0pk); - await testDbService.createWorkspace(ws1pk); - await testDbService.createWorkspace(ws2pk); - await testDbService.createUser([ws0pk], { companyRole: "member", workspaceRole: "moderator" }); - await testDbService.createUser([ws0pk], { companyRole: "member", workspaceRole: "member" }); - await testDbService.createUser([ws1pk], { - companyRole: "member", - workspaceRole: "member", - email: emailForExistedUser, - }); - await testDbService.createUser([ws2pk], { - companyRole: "guest", - workspaceRole: "member", - email: fourthUser, - }); - - ends(); - }); - - afterAll(async ends => { - await platform.tearDown(); - ends(); - }); - - describe("Invite users to a workspace by email", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/users/invite`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 404 when workspace not found", async done => { - const userId = testDbService.users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/users/invite`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - invitations: [ - { - email: firstEmail, - role: "member", - company_role: "member", - }, - ], - }, - }); - - expect(response.statusCode).toBe(404); - done(); - }); - - it("should 403 when requester is not at least workspace member", async done => { - const workspace_id = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspace_id}/users/invite`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - invitations: [ - { - email: firstEmail, - role: "member", - company_role: "member", - }, - ], - }, - }); - expect(response.statusCode).toBe(403); - done(); - }); - - it("should 200 when ok", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/invite`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - invitations: [ - { - email: firstEmail, - role: "member", - company_role: "member", - }, - { - email: secondEmail, - role: "member", - company_role: "member", - }, - { - email: "exist@email.com", - role: "member", - company_role: "member", - }, - ], - }, - }); - expect(response.statusCode).toBe(200); - - const resources = response.json()["resources"]; - - expect(resources.length).toBe(3); - - for (const item of resources) { - expect(item).toMatchObject({ - email: expect.stringMatching(/first@test-user.com|second@test-user.com|exist@email.com/), - status: "ok", - }); - } - - done(); - }); - - it("should fail in response with already added users", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/invite`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - invitations: [ - { - email: firstEmail, - role: "member", - company_role: "member", - }, - { - email: thirdEmail, - role: "member", - company_role: "member", - }, - ], - }, - }); - expect(response.statusCode).toBe(200); - - const resources = response.json()["resources"]; - - expect(resources.length).toBe(2); - - expect(resources[0]).toMatchObject({ - email: "first@test-user.com", - status: "error", - }); - - expect(resources[1]).toMatchObject({ - email: "third@test-user.com", - status: "ok", - }); - - done(); - }); - }); - - describe("Delete a pending user from a workspace", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - const email = "first@test-user.com"; - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/pending/${email}`, - }); - - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 404 when workspace not found", async done => { - const companyId = testDbService.company.id; - const email = "first@test-user.com"; - - const userId = testDbService.users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/pending/${email}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(404); - done(); - }); - - it("should 403 when requester is not at least workspace member", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[0].id; - const email = "first@test-user.com"; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/pending/${email}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(403); - done(); - }); - - it("should {status:error} when email is absent in pending list", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/pending/non-exist-email`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(200); - expect(response.json()).toMatchObject({ - status: "error", - }); - - done(); - }); - - it("should 200 when ok", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - const email = "first@test-user.com"; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/pending/${email}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(200); - expect(response.json()).toMatchObject({ - status: "success", - }); - - done(); - }); - }); - - describe("Get list of pending users in workspace", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - const email = "first@test-user.com"; - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/pending`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 404 when workspace not found", async done => { - const companyId = testDbService.company.id; - const email = "first@test-user.com"; - - const userId = testDbService.users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/pending`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(404); - done(); - }); - - it("should 403 when requester is not at least workspace member", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[0].id; - const email = "first@test-user.com"; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/pending`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(403); - done(); - }); - - it("should 200 when ok", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/pending`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(200); - - const resources = response.json()["resources"]; - console.log("resources A: ", resources); - expect(resources.length).toBe(2); - - expect(resources[0]).toMatchObject({ - email: "second@test-user.com", - role: "member", - company_role: "member", - }); - - expect(resources[1]).toMatchObject({ - email: "third@test-user.com", - role: "member", - company_role: "member", - }); - - done(); - }); - - it("existed user should be added instantly", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - const email = "first@test-user.com"; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(200); - - const resources = response.json()["resources"]; - - console.log("resources B: ", resources); - expect(resources.find((a: any) => a.user.email === emailForExistedUser)).toBeDefined(); - - done(); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/workspaces/workspace-users.spec.ts b/twake/backend/node/test/e2e/workspaces/workspace-users.spec.ts deleted file mode 100644 index c70f2e83..00000000 --- a/twake/backend/node/test/e2e/workspaces/workspace-users.spec.ts +++ /dev/null @@ -1,469 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { TestDbService, uuid } from "../utils.prepare.db"; -import { v1 as uuidv1 } from "uuid"; - -describe("The /workspace users API", () => { - const url = "/internal/services/workspaces/v1"; - let platform: TestPlatform; - - let testDbService: TestDbService; - - const nonExistentId = uuidv1(); - let companyId = ""; - - const checkUserObject = (resource: any) => { - expect(resource).toMatchObject({ - id: expect.any(String), - company_id: expect.any(String), - workspace_id: expect.any(String), - user_id: expect.any(String), - created_at: expect.any(Number), - role: expect.stringMatching(/moderator|member/), - user: { - id: expect.any(String), - provider: expect.any(String), - provider_id: expect.any(String), - email: expect.any(String), - is_verified: expect.any(Boolean), - picture: expect.any(String), - first_name: expect.any(String), - last_name: expect.any(String), - created_at: expect.any(Number), - deleted: expect.any(Boolean), - status: expect.any(String), - last_activity: expect.any(Number), - }, - }); - }; - - beforeAll(async ends => { - platform = await init({ - services: [ - "database", - "message-queue", - "search", - "webserver", - "user", - "workspaces", - "applications", - "auth", - "console", - "counter", - "storage", - "statistics", - "platform-services", - ], - }); - - companyId = platform.workspace.company_id; - - await platform.database.getConnector().init(); - testDbService = new TestDbService(platform); - await testDbService.createCompany(companyId); - const ws0pk = { id: uuidv1(), company_id: companyId }; - const ws1pk = { id: uuidv1(), company_id: companyId }; - const ws2pk = { id: uuidv1(), company_id: companyId }; - const ws3pk = { id: uuidv1(), company_id: companyId }; - await testDbService.createWorkspace(ws0pk); - await testDbService.createWorkspace(ws1pk); - await testDbService.createWorkspace(ws2pk); - await testDbService.createWorkspace(ws3pk); - await testDbService.createUser([ws0pk, ws1pk]); - await testDbService.createUser([ws2pk], { companyRole: "admin" }); - await testDbService.createUser([ws2pk], { workspaceRole: "moderator" }); - await testDbService.createUser([ws2pk], { workspaceRole: "member" }); - await testDbService.createUser([ws2pk], { workspaceRole: "member" }); - await testDbService.createUser([], { companyRole: "member" }); - await testDbService.createUser([ws3pk], { companyRole: "guest", workspaceRole: "member" }); - ends(); - }); - - afterAll(async ends => { - await platform.tearDown(); - ends(); - }); - - describe("The GET /workspaces/users route", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/users`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 404 when workspace not found", async done => { - const userId = testDbService.users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/users`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(404); - done(); - }); - - it("should 200 when ok", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(200); - - const resources = response.json()["resources"]; - - expect(resources.length).toBeGreaterThan(0); - - for (const resource of resources) { - checkUserObject(resource); - } - - done(); - }); - }); - - describe("The GET /workspaces/users/:user_id route", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - const userId = testDbService.users[0].id; - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/users/${userId}`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 404 when workspace not found", async done => { - const userId = testDbService.users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/users/${userId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(404); - done(); - }); - - it("should 200 when ok", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/${userId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(200); - - const resource = response.json()["resource"]; - checkUserObject(resource); - done(); - }); - }); - - describe("The POST /workspaces/users route (add)", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/users`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 403 user is not workspace moderator", async done => { - const userId = testDbService.users[0].id; - const anotherUserId = testDbService.users[1].id; - const workspaceId = testDbService.workspaces[0].workspace.id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - user_id: anotherUserId, - role: "moderator", - }, - }, - }); - expect(response.statusCode).toBe(403); - done(); - }); - - it("should 400 when requested user not in company", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[1].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - user_id: nonExistentId, - role: "moderator", - }, - }, - }); - expect(response.statusCode).toBe(400); - done(); - }); - - it("should 201 when requested already in workspace (ignore)", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[1].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - user_id: userId, - role: "moderator", - }, - }, - }); - expect(response.statusCode).toBe(201); - done(); - }); - - it("should 200 when ok", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[1].id; - const anotherUserId = testDbService.workspaces[0].users[0].id; - - let workspaceUsersCount = await testDbService.getWorkspaceUsersCountFromDb(workspaceId); - let companyUsersCount = await testDbService.getCompanyUsersCountFromDb(companyId); - - console.log(testDbService.workspaces[2].users); - console.log(workspaceUsersCount); - - expect(workspaceUsersCount).toBe(4); - // expect(companyUsersCount).toBe(6); - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - user_id: anotherUserId, - role: "moderator", - }, - }, - }); - - expect(response.statusCode).toBe(201); - const resource = response.json()["resource"]; - checkUserObject(resource); - - workspaceUsersCount = await testDbService.getWorkspaceUsersCountFromDb(workspaceId); - companyUsersCount = await testDbService.getCompanyUsersCountFromDb(companyId); - expect(workspaceUsersCount).toBe(5); - // expect(companyUsersCount).toBe(6); - - done(); - }); - }); - - describe("The POST /workspaces/users/:user_id route (update)", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - const userId = testDbService.users[0].id; - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/users/${userId}`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 403 user is not workspace moderator", async done => { - const userId = testDbService.users[0].id; - const anotherUserId = testDbService.users[1].id; - const workspaceId = testDbService.workspaces[0].workspace.id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/${userId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - user_id: anotherUserId, - role: "moderator", - }, - }, - }); - expect(response.statusCode).toBe(403); - done(); - }); - - it("should 404 when user not found in workspace", async done => { - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[1].id; - const anotherWorkspaceUserId = testDbService.workspaces[3].users[0].id; - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/${anotherWorkspaceUserId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - role: "moderator", - }, - }, - }); - - expect(response.statusCode).toBe(404); - done(); - }); - - it("should 200 when ok", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[1].id; - const anotherUserId = testDbService.workspaces[2].users[2].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/${anotherUserId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - role: "moderator", - }, - }, - }); - - expect(response.statusCode).toBe(201); - const resource = response.json()["resource"]; - checkUserObject(resource); - - expect(resource["role"]).toBe("moderator"); - - const usersCount = await testDbService.getWorkspaceUsersCountFromDb(workspaceId); - expect(usersCount).toBe(5); - - done(); - }); - }); - - describe("The DELETE /workspaces/users/:user_id route", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - const anotherUserId = testDbService.users[1].id; - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/users/${anotherUserId}`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 403 user is not workspace moderator", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[3].id; - const anotherUserId = testDbService.workspaces[2].users[1].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/${anotherUserId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - console.log(response.body); - - expect(response.statusCode).toBe(403); - done(); - }); - - it("should 404 when user not found in workspace", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[1].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/${nonExistentId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(404); - - done(); - }); - - it("should 200 when ok", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[1].id; - const anotherUserId = testDbService.workspaces[2].users[2].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - let response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/${anotherUserId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(204); - - response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(200); - const resources = response.json()["resources"]; - expect(resources.find((a: { user_id: uuid }) => a.user_id === anotherUserId)).toBeUndefined(); - - const usersCount = await testDbService.getWorkspaceUsersCountFromDb(workspaceId); - expect(usersCount).toBe(4); - - done(); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/workspaces/workspaces.invite-tokens.spec.ts b/twake/backend/node/test/e2e/workspaces/workspaces.invite-tokens.spec.ts deleted file mode 100644 index 90853467..00000000 --- a/twake/backend/node/test/e2e/workspaces/workspaces.invite-tokens.spec.ts +++ /dev/null @@ -1,521 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { TestDbService } from "../utils.prepare.db"; -import { v1 as uuidv1 } from "uuid"; -import AuthService from "../../../src/core/platform/services/auth/provider"; -import { InviteTokenObject } from "../../../src/services/workspaces/web/types"; -import gr from "../../../src/services/global-resolver"; - -describe("The /workspaces API (invite tokens)", () => { - const url = "/internal/services/workspaces/v1"; - let platform: TestPlatform; - - let testDbService: TestDbService; - let authServiceApi: AuthService; - - let companyId = uuidv1(); - - const startup = async () => { - platform = await init({ - services: [ - "database", - "message-queue", - "webserver", - "user", - "search", - "workspaces", - "auth", - "console", - "counter", - "storage", - "applications", - "statistics", - "platform-services", - ], - }); - - companyId = platform.workspace.company_id; - - await platform.platform.getProvider("auth"); - testDbService = new TestDbService(platform); - await resetDatabase(); - }; - - const shutdown = async () => { - await platform.tearDown(); - }; - - const resetDatabase = async () => { - // await platform.database.getConnector().init(); - await platform.database.getConnector().drop(); - await testDbService.createCompany(companyId, "TestJoinCompany"); - const ws0pk = { id: uuidv1(), company_id: companyId }; - const ws1pk = { id: uuidv1(), company_id: companyId }; - const ws2pk = { id: uuidv1(), company_id: companyId }; - await testDbService.createWorkspace(ws0pk, "FirstWorkspace"); - await testDbService.createWorkspace(ws1pk, "SecondWorkspace"); - await testDbService.createWorkspace(ws2pk, "ThirdWorkspace"); - await testDbService.createUser([ws0pk, ws1pk]); - await testDbService.createUser([ws2pk], { companyRole: "admin" }); - await testDbService.createUser([ws2pk], { companyRole: undefined, workspaceRole: "moderator" }); - await testDbService.createUser([], { companyRole: "guest" }); - }; - - const decodeToken = (token: string): InviteTokenObject => { - return gr.services.workspaces.decodeInviteToken(token); - }; - - describe("The GET /tokens/ route", () => { - beforeAll(startup); - afterAll(shutdown); - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - - const workspaceId = testDbService.workspaces[0].workspace.id; - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 403 when user is not a workspace member", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userIdFromAnotherWorkspace = platform.currentUser.id; - const companyId = testDbService.company.id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userIdFromAnotherWorkspace }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(403); - - done(); - }); - - it("should 404 when token doesn't exists yet", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - const companyId = testDbService.company.id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(404); - - done(); - }); - - it("should 200 when user is a workspace member", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - const companyId = testDbService.company.id; - - await gr.services.workspaces.createInviteToken(companyId, workspaceId, userId); - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(200); - - expect(response.json()).toMatchObject({ - resources: [ - { - token: expect.any(String), - }, - ], - }); - - done(); - }); - }); - - describe("The POST /tokens/ route", () => { - beforeAll(startup); - afterAll(shutdown); - - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - - const workspaceId = testDbService.workspaces[0].workspace.id; - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 403 when user is not a workspace member", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userIdFromAnotherWorkspace = platform.currentUser.id; - const companyId = testDbService.company.id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userIdFromAnotherWorkspace }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - channels: ["test"], - }, - }); - expect(response.statusCode).toBe(403); - - done(); - }); - - it("should 200 when user is a workspace member", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - const companyId = testDbService.company.id; - const channel = await testDbService.createChannel(userId); - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const beforeResponse = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(beforeResponse.statusCode).toBe(404); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - channels: [channel.id], - }, - }); - - expect(response.statusCode).toBe(200); - - expect(response.json()).toMatchObject({ - resource: { - token: expect.any(String), - }, - }); - - const createToken = decodeToken(response.json().resource.token); - - const afterResponse = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(afterResponse.statusCode).toBe(200); - - expect(afterResponse.json()).toMatchObject({ - resources: [ - { - token: expect.any(String), - }, - ], - }); - - const getToken = decodeToken(afterResponse.json().resources[0].token); - - expect(createToken.t).toEqual(getToken.t); - - done(); - }); - - it("should 200 when when recreate token", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - const companyId = testDbService.company.id; - const channel = await testDbService.createChannel(userId); - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const beforeResponse = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(beforeResponse.statusCode).toBe(200); - - const beforeResponseResource = beforeResponse.json()["resources"][0]; - - expect(beforeResponseResource).toMatchObject({ - token: expect.any(String), - }); - - const beforeResponseToken = decodeToken(beforeResponseResource.token).t; - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - channels: [channel.id], - }, - }); - - expect(response.statusCode).toBe(200); - - const responseResource = response.json()["resource"]; - - expect(responseResource).toMatchObject({ - token: expect.any(String), - }); - - const responseToken = decodeToken(responseResource.token).t; - - expect(responseToken).not.toEqual(beforeResponseToken); - - const afterResponse = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(afterResponse.statusCode).toBe(200); - - const afterResponseResource = afterResponse.json()["resources"][0]; - - expect(afterResponseResource).toMatchObject({ - token: expect.any(String), - }); - - const afterResponseToken = decodeToken(afterResponseResource.token).t; - - expect(responseToken).toEqual(afterResponseToken); - expect(afterResponseToken).not.toEqual(beforeResponseToken); - - done(); - }); - }); - - describe("The DELETE /tokens/ route", () => { - beforeAll(startup); - afterAll(shutdown); - - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - - const workspaceId = testDbService.workspaces[0].workspace.id; - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens/fake1-${new Date().getTime()}`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 403 when user is not a workspace member", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userIdFromAnotherWorkspace = platform.currentUser.id; - const companyId = testDbService.company.id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userIdFromAnotherWorkspace }); - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens/fake2-${new Date().getTime()}`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: {}, - }); - expect(response.statusCode).toBe(403); - - done(); - }); - - it("should 204 when user is a workspace member", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - const companyId = testDbService.company.id; - - await gr.services.workspaces.createInviteToken(companyId, workspaceId, userId); - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const beforeResponse = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(beforeResponse.statusCode).toBe(200); - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens/${ - beforeResponse.json().resources[0].token - }`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(204); - - const afterResponse = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(afterResponse.statusCode).toBe(404); - - done(); - }); - - it("should 404 when deleting token that doesn't exists", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - const companyId = testDbService.company.id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens/fake3-${new Date().getTime()}`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: {}, - }); - expect(response.statusCode).toBe(404); - - done(); - }); - }); - - describe("Join workspace using token", () => { - let workspaceId; - let userId; - let companyId; - let inviteToken; - - beforeAll(async () => { - await startup(); - companyId = testDbService.company.id; - workspaceId = testDbService.workspaces[0].workspace.id; - userId = testDbService.workspaces[2].users[0].id; - inviteToken = await gr.services.workspaces.createInviteToken(companyId, workspaceId, userId); - }); - afterAll(shutdown); - - it("should 404 when when token not found", async done => { - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/join`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - join: false, - token: "SOME FAKE TOKEN", - }, - }); - expect(response.statusCode).toBe(404); - done(); - }); - - it("should 200 when user is not authorized", async done => { - const response = await platform.app.inject({ - method: "POST", - url: `${url}/join`, - // headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - join: false, - token: inviteToken.token, - }, - }); - expect(response.statusCode).toBe(200); - - const resource = response.json()["resource"]; - - expect(resource).toMatchObject({ - company: { - name: "TestJoinCompany", - }, - workspace: { - name: "FirstWorkspace", - }, - auth_required: true, - }); - - done(); - }); - - it("should 200 when user is authorized and not joining", async done => { - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/join`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - join: false, - token: inviteToken.token, - }, - }); - expect(response.statusCode).toBe(200); - - const resource = response.json()["resource"]; - - expect(resource).toMatchObject({ - company: { - name: "TestJoinCompany", - }, - workspace: { - name: "FirstWorkspace", - }, - auth_required: false, - }); - - done(); - }); - - it("should 200 when user is authorized and joining", async done => { - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/join`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - join: true, - token: inviteToken.token, - }, - }); - expect(response.statusCode).toBe(200); - - const resource = response.json()["resource"]; - - expect(resource).toMatchObject({ - company: { - id: companyId, - name: "TestJoinCompany", - }, - workspace: { - id: workspaceId, - name: "FirstWorkspace", - }, - auth_required: false, - }); - - done(); - }); - }); -}); diff --git a/twake/backend/node/test/e2e/workspaces/workspaces.spec.ts b/twake/backend/node/test/e2e/workspaces/workspaces.spec.ts deleted file mode 100644 index d251e304..00000000 --- a/twake/backend/node/test/e2e/workspaces/workspaces.spec.ts +++ /dev/null @@ -1,513 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; -import { init, TestPlatform } from "../setup"; -import { TestDbService } from "../utils.prepare.db"; -import { v1 as uuidv1 } from "uuid"; - -describe("The /workspaces API", () => { - const url = "/internal/services/workspaces/v1"; - let platform: TestPlatform; - - let testDbService: TestDbService; - - const nonExistentId = uuidv1(); - let companyId = ""; - - beforeAll(async ends => { - platform = await init({ - services: [ - "database", - "message-queue", - "webserver", - "user", - "search", - "workspaces", - "auth", - "console", - "counter", - "storage", - "applications", - "statistics", - "platform-services", - ], - }); - - companyId = platform.workspace.company_id; - - await platform.database.getConnector().init(); - testDbService = new TestDbService(platform); - await testDbService.createCompany(companyId); - const ws0pk = { id: uuidv1(), company_id: companyId }; - const ws1pk = { id: uuidv1(), company_id: companyId }; - const ws2pk = { id: uuidv1(), company_id: companyId }; - await testDbService.createWorkspace(ws0pk); - await testDbService.createWorkspace(ws1pk); - await testDbService.createWorkspace(ws2pk); - await testDbService.createUser([ws0pk, ws1pk]); - await testDbService.createUser([ws2pk], { companyRole: "admin" }); - await testDbService.createUser([ws2pk], { companyRole: undefined, workspaceRole: "moderator" }); - await testDbService.createUser([], { companyRole: "guest" }); - ends(); - }); - - afterAll(async ends => { - await platform.tearDown(); - ends(); - }); - - describe("The GET /workspaces/ route", () => { - it("should 401 when not authenticated", async done => { - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${nonExistentId}/workspaces`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 404 when company not found", async done => { - const userId = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${nonExistentId}/workspaces`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(404); - done(); - }); - - it("should 200 when company belongs to user", async done => { - const userId = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const companyId = testDbService.company.id; - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(200); - - const resources = response.json()["resources"]; - - expect(resources.length).toBe(2); - - for (const resource of resources) { - expect(resource).toMatchObject({ - id: expect.any(String), - company_id: expect.any(String), - name: expect.any(String), - logo: expect.any(String), - default: expect.any(Boolean), - archived: expect.any(Boolean), - role: expect.stringMatching(/moderator|member/), - }); - - if (resource.stats) { - expect(resource.stats).toMatchObject({ - created_at: expect.any(Number), - total_members: 1, - }); - } - } - - done(); - }); - }); - - describe("The GET /workspaces/:workspace_id route", () => { - it("should 401 when not authenticated", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${nonExistentId}/workspaces/${workspaceId}`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 404 when workspace not found", async done => { - const userId = testDbService.workspaces[0].users[0].id; - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${uuidv1()}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(404); - done(); - }); - - it("should 403 when user not belong to workspace and not company_admin", async done => { - const workspaceId = testDbService.workspaces[2].workspace.id; - const userIdFromAnotherWorkspace = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userIdFromAnotherWorkspace }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(403); - - expect(response.json()).toEqual({ - error: "Forbidden", - message: `You are not belong to workspace ${workspaceId}`, - statusCode: 403, - }); - - done(); - }); - - it("should 200 when user is company_admin", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userIdFromAnotherWorkspace = testDbService.workspaces[2].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userIdFromAnotherWorkspace }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(200); - - const resource = response.json()["resource"]; - - expect(resource).toMatchObject({ - id: expect.any(String), - company_id: expect.any(String), - name: expect.any(String), - logo: expect.any(String), - default: expect.any(Boolean), - archived: expect.any(Boolean), - }); - - if (resource.stats) { - expect(resource.stats).toMatchObject({ - created_at: expect.any(Number), - total_members: 1, - }); - } - - done(); - }); - - it("should 200 when user is belong to workspace", async done => { - const workspaceId = testDbService.workspaces[0].workspace.id; - const userIdFromThisWorkspace = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userIdFromThisWorkspace }); - - const response = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - expect(response.statusCode).toBe(200); - - const resource = response.json()["resource"]; - - expect(resource).toMatchObject({ - id: expect.any(String), - company_id: expect.any(String), - name: expect.any(String), - logo: expect.any(String), - default: expect.any(Boolean), - archived: expect.any(Boolean), - role: expect.stringMatching(/moderator|member/), - }); - - if (resource.stats) { - expect(resource.stats).toMatchObject({ - created_at: expect.any(Number), - total_members: 1, - }); - } - - done(); - }); - }); - - // create - - describe("The POST /workspaces route (creating workspace)", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 403 when user is not (company member or company admin) ", async done => { - const companyId = testDbService.company.id; - const userId = testDbService.users[3].id; - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - name: "Some channel name", - logo: "", - default: false, - }, - }, - }); - - expect(response.statusCode).toBe(403); - done(); - }); - - it("should 201 when workspace created well", async done => { - const companyId = testDbService.company.id; - const userId = testDbService.users[0].id; - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - name: "Random channel name", - logo: "logo", - default: false, - }, - }, - }); - - expect(response.statusCode).toBe(201); - - const resource = response.json()["resource"]; - - expect(resource).toMatchObject({ - id: expect.any(String), - company_id: expect.any(String), - name: expect.any(String), - logo: expect.any(String), - default: expect.any(Boolean), - archived: expect.any(Boolean), - role: expect.stringMatching(/moderator/), - }); - - done(); - }); - }); - - // update - - describe("The POST /workspaces/:workspace_id route (updating workspace)", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}`, - payload: { resource: {} }, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 403 when not workspace not found", async done => { - const companyId = testDbService.company.id; - const userId = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { resource: {} }, - }); - - expect(response.statusCode).toBe(403); - - done(); - }); - - it("should 403 when not belong to workspace", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[1].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { resource: {} }, - }); - - expect(response.statusCode).toBe(403); - - done(); - }); - - it("should 403 when not workspace moderator", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[1].workspace.id; - const userId = testDbService.workspaces[0].users[0].id; - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { resource: {} }, - }); - - expect(response.statusCode).toBe(403); - - done(); - }); - - it("should 200 when admin of company (full update)", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[0].id; // company owner - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - name: "Another workspace name", - logo: "logo", - default: false, - archived: false, - }, - }, - }); - - expect(response.statusCode).toBe(200); - - const resource = response.json()["resource"]; - - expect(resource).toMatchObject({ - id: workspaceId, - company_id: companyId, - name: "Another workspace name", - logo: expect.any(String), - default: false, - archived: false, - role: "moderator", //Company admin is a moderator - }); - - done(); - }); - - it("should 200 when moderator of workspace (partial update)", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[1].id; // workspace admin - - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - payload: { - resource: { - name: "My awesome workspace", - default: true, - logo: "", - }, - }, - }); - - expect(response.statusCode).toBe(200); - - const resource = response.json()["resource"]; - - expect(resource).toMatchObject({ - id: workspaceId, - company_id: companyId, - name: "My awesome workspace", - logo: expect.any(String), - default: true, - archived: false, - role: "moderator", - }); - - done(); - }); - }); - - // delete - - describe("The DELETE /workspaces route", () => { - it("should 401 when not authenticated", async done => { - const companyId = testDbService.company.id; - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}`, - }); - expect(response.statusCode).toBe(401); - done(); - }); - - it("should 403 when user is not (company member or company admin) ", async done => { - const companyId = testDbService.company.id; - const userId = testDbService.users[3].id; - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const workspaceId = testDbService.workspaces[0].workspace.id; - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(403); - done(); - }); - - it("should 204 when workspace deleted", async done => { - const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[0].id; - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - expect(response.statusCode).toBe(204); - - const checkResponse = await platform.app.inject({ - method: "GET", - url: `${url}/companies/${companyId}/workspaces`, - headers: { authorization: `Bearer ${jwtToken}` }, - }); - - const checkResponseJson = checkResponse.json(); - - expect(checkResponseJson.resources.find((a: any) => a.id === workspaceId)).toBe(undefined); - - done(); - }); - }); -});