Skip to content

Commit

Permalink
#2823 slack id to organization schema change, service funcs, and slac…
Browse files Browse the repository at this point in the history
…k router addition
  • Loading branch information
chpy04 committed Dec 20, 2024
1 parent acbb022 commit 811b608
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 3 deletions.
19 changes: 19 additions & 0 deletions src/backend/src/integrations/slack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,23 @@ export const getUserName = async (userId: string) => {
}
};

/**
* Get the workspace id of the workspace this slack api is registered with
* @returns the id of the workspace
*/
export const getWorkspaceId = async () => {
const { SLACK_BOT_TOKEN } = process.env;
if (!SLACK_BOT_TOKEN) return;

try {
const response = await slack.auth.test();
if (response.ok) {
return response.team_id;
}
throw new Error(response.error);
} catch (error) {
throw new HttpException(500, 'Error getting slack workspace id: ' + (error as any).data.error);
}
};

export default slack;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
-- AlterTable
ALTER TABLE "Organization" ADD COLUMN "logoImageId" TEXT;
ALTER TABLE "Organization" ADD COLUMN "logoImageId" TEXT,
ADD COLUMN "slackWorkspaceId" TEXT;

-- AlterTable
ALTER TABLE "Project" ADD COLUMN "organizationId" TEXT;
Expand Down
1 change: 1 addition & 0 deletions src/backend/src/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,7 @@ model Organization {
applyInterestImageId String? @unique
exploreAsGuestImageId String? @unique
logoImageId String?
slackWorkspaceId String?
// Relation references
wbsElements WBS_Element[]
Expand Down
10 changes: 8 additions & 2 deletions src/backend/src/routes/slack.routes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { createEventAdapter } from '@slack/events-api';
import slackServices from '../services/slack.services';
import OrganizationsService from '../services/organizations.services';
import { getWorkspaceId } from '../integrations/slack';

export const slackEvents = createEventAdapter(process.env.SLACK_SIGNING_SECRET || '');

slackEvents.on('message', async (event) => {
console.log('EVENT:', event);
slackServices.processMessageSent(event, process.env.DEV_ORGANIZATION_ID ?? '');
const organizations = await OrganizationsService.getAllOrganizations();
const nerSlackWorkspaceId = await getWorkspaceId();
const orgId = organizations.find((org) => org.slackWorkspaceId === nerSlackWorkspaceId)?.organizationId;
if (orgId) {
slackServices.processMessageSent(event, orgId);
}
});

slackEvents.on('error', (error) => {
Expand Down
34 changes: 34 additions & 0 deletions src/backend/src/services/organizations.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ import { getProjectQueryArgs } from '../prisma-query-args/projects.query-args';
import projectTransformer from '../transformers/projects.transformer';

export default class OrganizationsService {
/**
* Retrieve all the organizations
* @returns an array of every organization
*/
static async getAllOrganizations(): Promise<Organization[]> {
return prisma.organization.findMany();
}

/**
* Gets the current organization
* @param organizationId the organizationId to be fetched
Expand Down Expand Up @@ -275,4 +283,30 @@ export default class OrganizationsService {

return organization.featuredProjects.map(projectTransformer);
}

/**
* Sets the slack workspace id used to initialize slack bots for this organization
* @param slackWorkspaceId the id of the organization's slack workspace
* @param submitter the user making this submission (must be an admin)
* @param organization the organization being changed
* @returns the changed organization
*/
static async setOrganizationSlackWorkspaceId(
slackWorkspaceId: string,
submitter: User,
organization: Organization
): Promise<Organization> {
if (!(await userHasPermission(submitter.userId, organization.organizationId, isAdmin))) {
throw new AccessDeniedAdminOnlyException('set slack workspace id');
}
const updatedOrg = prisma.organization.update({
where: {
organizationId: organization.organizationId
},
data: {
slackWorkspaceId
}
});
return updatedOrg;
}
}
32 changes: 32 additions & 0 deletions src/backend/tests/mocked/organization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,4 +325,36 @@ describe('Organization Tests', () => {
expect(oldOrganization?.description).toBe(returnedOrganization.description);
});
});

describe('Set Organization slack id', () => {
it('Fails if user is not an admin', async () => {
await expect(
OrganizationsService.setOrganizationSlackWorkspaceId(
'test slack id',
await createTestUser(wonderwomanGuest, orgId),
organization
)
).rejects.toThrow(new AccessDeniedAdminOnlyException('set slack workspace id'));
});

it('Succeeds and updates the slack id', async () => {
const testBatman = await createTestUser(batmanAppAdmin, orgId);

const returnedOrganization = await OrganizationsService.setOrganizationSlackWorkspaceId(
'sample slack id',
testBatman,
organization
);

const oldOrganization = await prisma.organization.findUnique({
where: {
organizationId: orgId
}
});

expect(oldOrganization).not.toBeNull();
expect(oldOrganization?.slackWorkspaceId).toBe('sample slack id');
expect(oldOrganization?.slackWorkspaceId).toBe(returnedOrganization.slackWorkspaceId);
});
});
});

0 comments on commit 811b608

Please sign in to comment.