mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-01-17 07:10:03 +00:00
- Updated comments in Probe/Config.ts to use block comments for proxy configuration. - Refactored comments in PortMonitor.ts, SyntheticMonitor.ts, and OnlineCheck.ts to block comments for better readability. - Adjusted comments in ProbeIngest/API/Monitor.ts and ProbeIngest/API/Probe.ts to block comments for clarity. - Standardized comments in various data migration scripts to block comments for consistency. - Modified eslint.config.js to enforce multiline comment style as an error.
748 lines
23 KiB
TypeScript
748 lines
23 KiB
TypeScript
import Express, {
|
|
ExpressRequest,
|
|
ExpressResponse,
|
|
ExpressRouter,
|
|
} from "../Utils/Express";
|
|
import Response from "../Utils/Response";
|
|
import SlackAuthorization from "../Middleware/SlackAuthorization";
|
|
import BadRequestException from "../../Types/Exception/BadRequestException";
|
|
import logger from "../Utils/Logger";
|
|
import { JSONObject } from "../../Types/JSON";
|
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
import {
|
|
AppApiClientUrl,
|
|
DashboardClientUrl,
|
|
Host,
|
|
HttpProtocol,
|
|
SlackAppClientId,
|
|
SlackAppClientSecret,
|
|
} from "../EnvironmentConfig";
|
|
import SlackAppManifest from "../Utils/Workspace/Slack/app-manifest.json";
|
|
import URL from "../../Types/API/URL";
|
|
import HTTPErrorResponse from "../../Types/API/HTTPErrorResponse";
|
|
import HTTPResponse from "../../Types/API/HTTPResponse";
|
|
import API from "../../Utils/API";
|
|
import WorkspaceProjectAuthTokenService from "../Services/WorkspaceProjectAuthTokenService";
|
|
import ObjectID from "../../Types/ObjectID";
|
|
import WorkspaceUserAuthTokenService from "../Services/WorkspaceUserAuthTokenService";
|
|
import WorkspaceType from "../../Types/Workspace/WorkspaceType";
|
|
import SlackAuthAction, {
|
|
SlackRequest,
|
|
} from "../Utils/Workspace/Slack/Actions/Auth";
|
|
import SlackIncidentActions from "../Utils/Workspace/Slack/Actions/Incident";
|
|
import SlackAlertActions from "../Utils/Workspace/Slack/Actions/Alert";
|
|
import SlackScheduledMaintenanceActions from "../Utils/Workspace/Slack/Actions/ScheduledMaintenance";
|
|
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
import SlackMonitorActions from "../Utils/Workspace/Slack/Actions/Monitor";
|
|
import SlackOnCallDutyActions from "../Utils/Workspace/Slack/Actions/OnCallDutyPolicy";
|
|
import WorkspaceProjectAuthToken, {
|
|
SlackMiscData,
|
|
} from "../../Models/DatabaseModels/WorkspaceProjectAuthToken";
|
|
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
import CommonAPI from "./CommonAPI";
|
|
import SlackUtil from "../Utils/Workspace/Slack/Slack";
|
|
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
|
|
export default class SlackAPI {
|
|
public getRouter(): ExpressRouter {
|
|
const router: ExpressRouter = Express.getRouter();
|
|
|
|
router.get(
|
|
"/slack/app-manifest",
|
|
(req: ExpressRequest, res: ExpressResponse) => {
|
|
// return app manifest for slack app
|
|
|
|
let ServerURL: string = new URL(HttpProtocol, Host).toString();
|
|
|
|
//remove trailing slash if present.
|
|
if (ServerURL.endsWith("/")) {
|
|
ServerURL = ServerURL.slice(0, -1);
|
|
}
|
|
|
|
// replace SERVER_URL in the manifest with the actual server url.
|
|
const manifestInString: string = JSON.stringify(
|
|
SlackAppManifest,
|
|
).replace(/{{SERVER_URL}}/g, ServerURL.toString());
|
|
|
|
// convert it back to json.
|
|
const manifest: JSONObject = JSON.parse(manifestInString);
|
|
|
|
return Response.sendJsonObjectResponse(req, res, manifest);
|
|
},
|
|
);
|
|
|
|
// this is project specific auth endpoint.
|
|
router.get(
|
|
"/slack/auth/:projectId/:userId",
|
|
async (req: ExpressRequest, res: ExpressResponse) => {
|
|
if (!SlackAppClientId) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadDataException("Slack App Client ID is not set"),
|
|
);
|
|
}
|
|
|
|
if (!SlackAppClientSecret) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadDataException("Slack App Client Secret is not set"),
|
|
);
|
|
}
|
|
|
|
const projectId: string | undefined =
|
|
req.params["projectId"]?.toString();
|
|
const userId: string | undefined = req.params["userId"]?.toString();
|
|
|
|
if (!projectId) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadDataException("Invalid ProjectID in request"),
|
|
);
|
|
}
|
|
|
|
if (!userId) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadDataException("Invalid UserID in request"),
|
|
);
|
|
}
|
|
|
|
// if there's an error query param.
|
|
const error: string | undefined = req.query["error"]?.toString();
|
|
|
|
const slackIntegrationPageUrl: URL = URL.fromString(
|
|
DashboardClientUrl.toString() +
|
|
`/${projectId.toString()}/settings/slack-integration`,
|
|
);
|
|
|
|
if (error) {
|
|
return Response.redirect(
|
|
req,
|
|
res,
|
|
slackIntegrationPageUrl.addQueryParam("error", error),
|
|
);
|
|
}
|
|
|
|
// slack returns the code on successful auth.
|
|
const code: string | undefined = req.query["code"]?.toString();
|
|
|
|
if (!code) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadRequestException("Invalid request"),
|
|
);
|
|
}
|
|
|
|
// get access token from slack api.
|
|
|
|
const redirectUri: URL = URL.fromString(
|
|
`${AppApiClientUrl.toString()}/slack/auth/${projectId}/${userId}`,
|
|
);
|
|
|
|
const requestBody: JSONObject = {
|
|
code: code,
|
|
client_id: SlackAppClientId,
|
|
client_secret: SlackAppClientSecret,
|
|
redirect_uri: redirectUri.toString(),
|
|
};
|
|
|
|
logger.debug("Slack Auth Request Body: ");
|
|
logger.debug(requestBody);
|
|
|
|
// send the request to slack api to get the access token https://slack.com/api/oauth.v2.access
|
|
|
|
const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
await API.post({
|
|
url: URL.fromString("https://slack.com/api/oauth.v2.access"),
|
|
data: requestBody,
|
|
headers: {
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
},
|
|
});
|
|
|
|
if (response instanceof HTTPErrorResponse) {
|
|
throw response;
|
|
}
|
|
|
|
const responseBody: JSONObject = response.data;
|
|
|
|
logger.debug("Slack Auth Request Body: ");
|
|
logger.debug(responseBody);
|
|
|
|
let slackTeamId: string | undefined = undefined;
|
|
let slackBotAccessToken: string | undefined = undefined;
|
|
let slackUserId: string | undefined = undefined;
|
|
let slackTeamName: string | undefined = undefined;
|
|
let botUserId: string | undefined = undefined;
|
|
let slackUserAccessToken: string | undefined = undefined;
|
|
|
|
/*
|
|
* ReponseBody is in this format.
|
|
* {
|
|
* "ok": true,
|
|
* "access_token": "sample-token",
|
|
* "token_type": "bot",
|
|
* "scope": "commands,incoming-webhook",
|
|
* "bot_user_id": "U0KRQLJ9H",
|
|
* "app_id": "A0KRD7HC3",
|
|
* "team": {
|
|
* "name": "Slack Pickleball Team",
|
|
* "id": "T9TK3CUKW"
|
|
* },
|
|
* "enterprise": {
|
|
* "name": "slack-pickleball",
|
|
* "id": "E12345678"
|
|
* },
|
|
* "authed_user": {
|
|
* "id": "U1234",
|
|
* "scope": "chat:write",
|
|
* "access_token": "sample-token",
|
|
* "token_type": "user"
|
|
* }
|
|
* }
|
|
*/
|
|
|
|
if (responseBody["ok"] !== true) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadRequestException("Invalid request"),
|
|
);
|
|
}
|
|
|
|
if (
|
|
responseBody["team"] &&
|
|
(responseBody["team"] as JSONObject)["id"]
|
|
) {
|
|
slackTeamId = (responseBody["team"] as JSONObject)["id"]?.toString();
|
|
}
|
|
|
|
if (responseBody["access_token"]) {
|
|
slackBotAccessToken = responseBody["access_token"]?.toString();
|
|
}
|
|
|
|
if (
|
|
responseBody["authed_user"] &&
|
|
(responseBody["authed_user"] as JSONObject)["id"]
|
|
) {
|
|
slackUserId = (responseBody["authed_user"] as JSONObject)[
|
|
"id"
|
|
]?.toString();
|
|
}
|
|
|
|
if (
|
|
responseBody["authed_user"] &&
|
|
(responseBody["authed_user"] as JSONObject)["access_token"]
|
|
) {
|
|
slackUserAccessToken = (responseBody["authed_user"] as JSONObject)[
|
|
"access_token"
|
|
]?.toString();
|
|
}
|
|
|
|
if (
|
|
responseBody["team"] &&
|
|
(responseBody["team"] as JSONObject)["name"]
|
|
) {
|
|
slackTeamName = (responseBody["team"] as JSONObject)[
|
|
"name"
|
|
]?.toString();
|
|
}
|
|
|
|
if (responseBody["bot_user_id"]) {
|
|
botUserId = responseBody["bot_user_id"]?.toString();
|
|
}
|
|
|
|
await WorkspaceProjectAuthTokenService.refreshAuthToken({
|
|
projectId: new ObjectID(projectId),
|
|
workspaceType: WorkspaceType.Slack,
|
|
authToken: slackBotAccessToken || "",
|
|
workspaceProjectId: slackTeamId || "",
|
|
miscData: {
|
|
teamId: slackTeamId || "",
|
|
teamName: slackTeamName || "",
|
|
botUserId: botUserId || "",
|
|
},
|
|
});
|
|
|
|
await WorkspaceUserAuthTokenService.refreshAuthToken({
|
|
projectId: new ObjectID(projectId),
|
|
userId: new ObjectID(userId),
|
|
workspaceType: WorkspaceType.Slack,
|
|
authToken: slackUserAccessToken || "",
|
|
workspaceUserId: slackUserId || "",
|
|
miscData: {
|
|
userId: slackUserId || "",
|
|
},
|
|
});
|
|
|
|
// return back to dashboard after successful auth.
|
|
Response.redirect(req, res, slackIntegrationPageUrl);
|
|
},
|
|
);
|
|
|
|
// this is user specific auth endpoint to sign in to slack.
|
|
router.get(
|
|
"/slack/auth/:projectId/:userId/user",
|
|
async (req: ExpressRequest, res: ExpressResponse) => {
|
|
if (!SlackAppClientId) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadDataException("Slack App Client ID is not set"),
|
|
);
|
|
}
|
|
|
|
if (!SlackAppClientSecret) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadDataException("Slack App Client Secret is not set"),
|
|
);
|
|
}
|
|
|
|
const projectId: string | undefined =
|
|
req.params["projectId"]?.toString();
|
|
const userId: string | undefined = req.params["userId"]?.toString();
|
|
|
|
if (!projectId) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadDataException("Invalid ProjectID in request"),
|
|
);
|
|
}
|
|
|
|
if (!userId) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadDataException("Invalid UserID in request"),
|
|
);
|
|
}
|
|
|
|
// if there's an error query param.
|
|
const error: string | undefined = req.query["error"]?.toString();
|
|
|
|
const slackIntegrationPageUrl: URL = URL.fromString(
|
|
DashboardClientUrl.toString() +
|
|
`/${projectId.toString()}/settings/slack-integration`,
|
|
);
|
|
|
|
if (error) {
|
|
return Response.redirect(
|
|
req,
|
|
res,
|
|
slackIntegrationPageUrl.addQueryParam("error", error),
|
|
);
|
|
}
|
|
|
|
// slack returns the code on successful auth.
|
|
const code: string | undefined = req.query["code"]?.toString();
|
|
|
|
if (!code) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadRequestException("Invalid request"),
|
|
);
|
|
}
|
|
|
|
// get access token from slack api.
|
|
|
|
const redirectUri: URL = URL.fromString(
|
|
`${AppApiClientUrl.toString()}/slack/auth/${projectId}/${userId}/user`,
|
|
);
|
|
|
|
const requestBody: JSONObject = {
|
|
code: code,
|
|
client_id: SlackAppClientId,
|
|
client_secret: SlackAppClientSecret,
|
|
redirect_uri: redirectUri.toString(),
|
|
};
|
|
|
|
logger.debug("Slack Auth Request Body: ");
|
|
logger.debug(requestBody);
|
|
|
|
// send the request to slack api to get the access token https://slack.com/api/oauth.v2.access
|
|
|
|
const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
await API.post({
|
|
url: URL.fromString("https://slack.com/api/openid.connect.token"),
|
|
data: requestBody,
|
|
headers: {
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
},
|
|
});
|
|
|
|
if (response instanceof HTTPErrorResponse) {
|
|
throw response;
|
|
}
|
|
|
|
const responseBody: JSONObject = response.data;
|
|
|
|
logger.debug("Slack User Auth Request Body: ");
|
|
logger.debug(responseBody);
|
|
|
|
if (
|
|
responseBody["id_token"] &&
|
|
typeof responseBody["id_token"] === "string" &&
|
|
responseBody["id_token"].split(".").length > 0
|
|
) {
|
|
const idToken: string = responseBody["id_token"];
|
|
const decodedIdToken: JSONObject = JSON.parse(
|
|
Buffer.from(
|
|
(idToken.split(".")?.[1] as string) || "",
|
|
"base64",
|
|
).toString("utf8"),
|
|
);
|
|
logger.debug("Decoded ID Token: ");
|
|
logger.debug(decodedIdToken);
|
|
responseBody["id_token"] = decodedIdToken;
|
|
}
|
|
|
|
const idToken: JSONObject | undefined = responseBody[
|
|
"id_token"
|
|
] as JSONObject;
|
|
|
|
/*
|
|
* Example of Response Body
|
|
* {
|
|
* "iss": "https://slack.com",
|
|
* "sub": "U123ABC456",
|
|
* "aud": "25259531569.1115258246291",
|
|
* "exp": 1626874955,
|
|
* "iat": 1626874655,
|
|
* "auth_time": 1626874655,
|
|
* "nonce": "abcd",
|
|
* "at_hash": "abc...123",
|
|
* "https://slack.com/team_id": "T0123ABC456",
|
|
* "https://slack.com/user_id": "U123ABC456",
|
|
* "email": "alice@example.com",
|
|
* "email_verified": true,
|
|
* "date_email_verified": 1622128723,
|
|
* "locale": "en-US",
|
|
* "name": "Alice",
|
|
* "given_name": "",
|
|
* "family_name": "",
|
|
* "https://slack.com/team_image_230": "https://secure.gravatar.com/avatar/bc.png",
|
|
* "https://slack.com/team_image_default": true
|
|
* }
|
|
*/
|
|
|
|
/*
|
|
* check if the team id matches the project id.
|
|
* get project auth.
|
|
*/
|
|
|
|
const projectAuth: WorkspaceProjectAuthToken | null =
|
|
await WorkspaceProjectAuthTokenService.findOneBy({
|
|
query: {
|
|
projectId: new ObjectID(projectId),
|
|
workspaceType: WorkspaceType.Slack,
|
|
},
|
|
select: {
|
|
workspaceProjectId: true,
|
|
miscData: true,
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
// cehck if the workspace project id is same as the team id.
|
|
if (projectAuth) {
|
|
logger.debug("Project Auth: ");
|
|
logger.debug(projectAuth.workspaceProjectId);
|
|
logger.debug("Response Team ID: ");
|
|
logger.debug(idToken["https://slack.com/team_id"]);
|
|
logger.debug("Response User ID: ");
|
|
logger.debug(idToken["https://slack.com/user_id"]);
|
|
|
|
if (
|
|
projectAuth.workspaceProjectId?.toString() !==
|
|
idToken["https://slack.com/team_id"]?.toString()
|
|
) {
|
|
const teamName: string | undefined = (
|
|
projectAuth.miscData as SlackMiscData
|
|
)?.teamName;
|
|
|
|
// send error response.
|
|
return Response.redirect(
|
|
req,
|
|
res,
|
|
slackIntegrationPageUrl.addQueryParam(
|
|
"error",
|
|
"Looks like you are trying to sign in to a different slack workspace. Please try again and sign in to the workspace " +
|
|
teamName,
|
|
),
|
|
);
|
|
}
|
|
} else {
|
|
// send error response.
|
|
return Response.redirect(
|
|
req,
|
|
res,
|
|
slackIntegrationPageUrl.addQueryParam(
|
|
"error",
|
|
"Looks like this OneUptime project is not connected to any slack workspace. Please try again and sign in to the workspace",
|
|
),
|
|
);
|
|
}
|
|
|
|
const authToken: string | undefined =
|
|
responseBody["access_token"]?.toString();
|
|
const slackUserId: string | undefined =
|
|
idToken["https://slack.com/user_id"]?.toString();
|
|
|
|
if (!slackUserId) {
|
|
return Response.redirect(
|
|
req,
|
|
res,
|
|
slackIntegrationPageUrl.addQueryParam(
|
|
"error",
|
|
"Unfortunately, we were unable to get your slack user id. Please try again.",
|
|
),
|
|
);
|
|
}
|
|
|
|
await WorkspaceUserAuthTokenService.refreshAuthToken({
|
|
projectId: new ObjectID(projectId),
|
|
userId: new ObjectID(userId),
|
|
workspaceType: WorkspaceType.Slack,
|
|
authToken: authToken || "",
|
|
workspaceUserId: slackUserId || "",
|
|
miscData: {
|
|
userId: slackUserId || "",
|
|
},
|
|
});
|
|
|
|
// return back to dashboard after successful auth.
|
|
Response.redirect(req, res, slackIntegrationPageUrl);
|
|
},
|
|
);
|
|
|
|
router.post(
|
|
"/slack/interactive",
|
|
SlackAuthorization.isAuthorizedSlackRequest,
|
|
async (req: ExpressRequest, res: ExpressResponse) => {
|
|
logger.debug("Slack Interactive Request: ");
|
|
|
|
const authResult: SlackRequest = await SlackAuthAction.isAuthorized({
|
|
req: req,
|
|
});
|
|
|
|
logger.debug("Slack Interactive Auth Result: ");
|
|
logger.debug(authResult);
|
|
|
|
// if slack uninstall app then,
|
|
if (authResult.payloadType === "app_uninstall") {
|
|
logger.debug("Slack App Uninstall Request: ");
|
|
|
|
// remove the project auth and user auth.
|
|
|
|
// delete all user auth tokens for this project.
|
|
await WorkspaceUserAuthTokenService.deleteBy({
|
|
query: {
|
|
projectId: authResult.projectId,
|
|
workspaceType: WorkspaceType.Slack,
|
|
},
|
|
limit: LIMIT_MAX,
|
|
skip: 0,
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
await WorkspaceProjectAuthTokenService.deleteBy({
|
|
query: {
|
|
projectId: authResult.projectId,
|
|
workspaceType: WorkspaceType.Slack,
|
|
},
|
|
limit: 1,
|
|
skip: 0,
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
logger.debug("Slack App Uninstall Request: Deleted all auth tokens.");
|
|
// return empty response.
|
|
|
|
return Response.sendTextResponse(req, res, "");
|
|
}
|
|
|
|
if (authResult.isAuthorized === false) {
|
|
// return empty response if not authorized. Do nothing in this case.
|
|
return Response.sendTextResponse(req, res, "");
|
|
}
|
|
|
|
for (const action of authResult.actions || []) {
|
|
if (!action.actionType) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadRequestException("Invalid request"),
|
|
);
|
|
}
|
|
|
|
if (
|
|
SlackIncidentActions.isIncidentAction({
|
|
actionType: action.actionType,
|
|
})
|
|
) {
|
|
return SlackIncidentActions.handleIncidentAction({
|
|
slackRequest: authResult,
|
|
action: action,
|
|
req: req,
|
|
res: res,
|
|
});
|
|
}
|
|
|
|
if (
|
|
SlackOnCallDutyActions.isOnCallDutyAction({
|
|
actionType: action.actionType,
|
|
})
|
|
) {
|
|
return SlackOnCallDutyActions.handleOnCallDutyAction({
|
|
slackRequest: authResult,
|
|
action: action,
|
|
req: req,
|
|
res: res,
|
|
});
|
|
}
|
|
|
|
if (
|
|
SlackAlertActions.isAlertAction({
|
|
actionType: action.actionType,
|
|
})
|
|
) {
|
|
return SlackAlertActions.handleAlertAction({
|
|
slackRequest: authResult,
|
|
action: action,
|
|
req: req,
|
|
res: res,
|
|
});
|
|
}
|
|
|
|
if (
|
|
SlackMonitorActions.isMonitorAction({
|
|
actionType: action.actionType,
|
|
})
|
|
) {
|
|
return SlackMonitorActions.handleMonitorAction({
|
|
slackRequest: authResult,
|
|
action: action,
|
|
req: req,
|
|
res: res,
|
|
});
|
|
}
|
|
|
|
if (
|
|
SlackScheduledMaintenanceActions.isScheduledMaintenanceAction({
|
|
actionType: action.actionType,
|
|
})
|
|
) {
|
|
return SlackScheduledMaintenanceActions.handleScheduledMaintenanceAction(
|
|
{
|
|
slackRequest: authResult,
|
|
action: action,
|
|
req: req,
|
|
res: res,
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadRequestException("Invalid request"),
|
|
);
|
|
},
|
|
);
|
|
|
|
// Fetch and cache all Slack channels for current tenant's project
|
|
router.get(
|
|
"/slack/get-all-channels",
|
|
UserMiddleware.getUserMiddleware,
|
|
async (req: ExpressRequest, res: ExpressResponse) => {
|
|
const props: DatabaseCommonInteractionProps =
|
|
await CommonAPI.getDatabaseCommonInteractionProps(req);
|
|
|
|
if (!props.tenantId) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadRequestException("ProjectId (tenant) not found in request"),
|
|
);
|
|
}
|
|
|
|
// Get Slack project auth
|
|
const projectAuth: WorkspaceProjectAuthToken | null =
|
|
await WorkspaceProjectAuthTokenService.getProjectAuth({
|
|
projectId: props.tenantId,
|
|
workspaceType: WorkspaceType.Slack,
|
|
});
|
|
|
|
if (!projectAuth || !projectAuth.authToken) {
|
|
return Response.sendErrorResponse(
|
|
req,
|
|
res,
|
|
new BadRequestException(
|
|
"Slack is not connected for this project. Please connect Slack first.",
|
|
),
|
|
);
|
|
}
|
|
|
|
// Fetch all channels (also updates cache under miscData.channelCache)
|
|
|
|
let updatedProjectAuth: WorkspaceProjectAuthToken | null = projectAuth;
|
|
|
|
if (!(projectAuth.miscData as SlackMiscData)?.channelCache) {
|
|
await SlackUtil.getAllWorkspaceChannels({
|
|
authToken: projectAuth.authToken,
|
|
projectId: props.tenantId,
|
|
});
|
|
|
|
// Re-fetch to return the latest cached object
|
|
updatedProjectAuth =
|
|
await WorkspaceProjectAuthTokenService.getProjectAuth({
|
|
projectId: props.tenantId,
|
|
workspaceType: WorkspaceType.Slack,
|
|
});
|
|
}
|
|
|
|
const channelCache: {
|
|
[channelName: string]: {
|
|
id: string;
|
|
name: string;
|
|
lastUpdated: string;
|
|
};
|
|
} =
|
|
((updatedProjectAuth?.miscData as SlackMiscData | undefined) || {})
|
|
?.channelCache || {};
|
|
|
|
return Response.sendJsonObjectResponse(req, res, channelCache as any);
|
|
},
|
|
);
|
|
|
|
// options load endpoint.
|
|
|
|
router.post(
|
|
"/slack/options-load",
|
|
SlackAuthorization.isAuthorizedSlackRequest,
|
|
(req: ExpressRequest, res: ExpressResponse) => {
|
|
return Response.sendJsonObjectResponse(req, res, {
|
|
response_action: "clear",
|
|
});
|
|
},
|
|
);
|
|
|
|
return router;
|
|
}
|
|
}
|