Skip to content

Commit 6c58bd5

Browse files
authored
Merge pull request #744 from matrix-org/justinbot/provisioning-checks
Add error messages in setup widget
2 parents 3b575ea + b15b9a9 commit 6c58bd5

File tree

4 files changed

+86
-64
lines changed

4 files changed

+86
-64
lines changed

changelog.d/744.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add improved error messages in setup widget.

src/provisioning/Provisioner.ts

Lines changed: 60 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,24 @@ export class Provisioner extends ProvisioningApi {
170170
return (currentCount >= this.main.config.provisioning?.limits?.room_count);
171171
}
172172

173+
/**
174+
* Checks if a Matrix room is public.
175+
* @param roomId Matrix room ID to check.
176+
* @returns Promise resolving to true if the room is public, otherwise false.
177+
* @private
178+
*/
179+
private async getIsRoomPublic(roomId: string): Promise<boolean> {
180+
try {
181+
const joinRulesEvent = await this.main.botIntent.getStateEvent(roomId, 'm.room.join_rules', '');
182+
return joinRulesEvent.join_rule === 'public';
183+
} catch (e) {
184+
throw new ApiError(
185+
"Could not check if room is public",
186+
ErrCode.Unknown,
187+
);
188+
}
189+
}
190+
173191
private async getBotId(req: ProvisioningRequest, res: Response) {
174192
const hasRoomLimit = this.main.config.provisioning?.limits?.room_count;
175193
const hasTeamLimit = this.main.config.provisioning?.limits?.team_count;
@@ -363,43 +381,54 @@ export class Provisioner extends ProvisioningApi {
363381
const matrixRoomId = body.matrix_room_id;
364382

365383
const room = this.main.rooms.getByMatrixRoomId(matrixRoomId);
366-
if (!room) {
367-
throw new SlackProvisioningError(
368-
"Link not found",
369-
SlackErrCode.UnknownLink,
370-
);
384+
if (room) {
385+
// Convert the room 'status' into an integration manager 'status'
386+
let status = room.getStatus();
387+
if (status.match(/^ready/)) {
388+
// OK
389+
} else if (status === "pending-params") {
390+
status = "partial";
391+
} else if (status === "pending-name") {
392+
status = "pending";
393+
} else {
394+
status = "unknown";
395+
}
396+
397+
return res.json({
398+
inbound_uri: this.main.getInboundUrlForRoom(room),
399+
isWebhook: room.SlackWebhookUri !== undefined,
400+
matrix_room_id: matrixRoomId,
401+
slack_channel_id: room.SlackChannelId,
402+
slack_channel_name: room.SlackChannelName,
403+
slack_webhook_uri: room.SlackWebhookUri,
404+
status,
405+
team_id: room.SlackTeamId,
406+
});
371407
}
372408

373-
const allowed = await this.main.checkLinkPermission(matrixRoomId, userId);
374-
if (!allowed) {
409+
if (this.config.require_public_room) {
410+
// Check if the room is public
411+
const isRoomPublic = await this.getIsRoomPublic(matrixRoomId);
412+
if (!isRoomPublic) {
413+
throw new SlackProvisioningError(
414+
"Only allowed to link public rooms",
415+
SlackErrCode.NotPublic,
416+
);
417+
}
418+
}
419+
420+
const hasPermissions = await this.main.checkLinkPermission(matrixRoomId, userId);
421+
if (!hasPermissions) {
375422
throw new SlackProvisioningError(
376423
"Not allowed to provision links in this room",
377424
SlackErrCode.NotEnoughPower,
378425
);
379426
}
380427

381-
// Convert the room 'status' into an integration manager 'status'
382-
let status = room.getStatus();
383-
if (status.match(/^ready/)) {
384-
// OK
385-
} else if (status === "pending-params") {
386-
status = "partial";
387-
} else if (status === "pending-name") {
388-
status = "pending";
389-
} else {
390-
status = "unknown";
391-
}
392-
393-
return res.json({
394-
inbound_uri: this.main.getInboundUrlForRoom(room),
395-
isWebhook: room.SlackWebhookUri !== undefined,
396-
matrix_room_id: matrixRoomId,
397-
slack_channel_id: room.SlackChannelId,
398-
slack_channel_name: room.SlackChannelName,
399-
slack_webhook_uri: room.SlackWebhookUri,
400-
status,
401-
team_id: room.SlackTeamId,
402-
});
428+
throw new SlackProvisioningError(
429+
"Link not found",
430+
SlackErrCode.UnknownLink,
431+
);
403432
}
404433

405434
private async getChannelInfo(req: ProvisioningRequest, res: Response) {
@@ -475,19 +504,8 @@ export class Provisioner extends ProvisioningApi {
475504
}
476505

477506
if (this.config.require_public_room) {
478-
// Check if the room is public
479-
let joinRulesEvent;
480-
try {
481-
joinRulesEvent = await this.main.botIntent.getStateEvent(matrixRoomId, 'm.room.join_rules', '');
482-
} catch (e) {
483-
req.log.error(e);
484-
throw new ApiError(
485-
"Could not check if room is public",
486-
ErrCode.Unknown,
487-
);
488-
}
489-
490-
if (joinRulesEvent.join_rule !== 'public') {
507+
const isRoomPublic = await this.getIsRoomPublic(matrixRoomId);
508+
if (!isRoomPublic) {
491509
throw new SlackProvisioningError(
492510
"Only allowed to link public rooms",
493511
SlackErrCode.NotPublic,

widget/src/SlackApp.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -372,13 +372,23 @@ export const SlackApp = () => {
372372
const getLink = useCallback(async() => {
373373
try {
374374
const link = await client.getLink(provisioningContext.roomId);
375-
setLink(link ?? null);
375+
setLink(link);
376376
} catch (e) {
377-
console.error('Failed to get link:', e);
378-
setError(
379-
'Could not get link status.'
380-
+ ` ${e instanceof ProvisioningError ? e.message : ''}`
381-
);
377+
if (e instanceof ProvisioningError) {
378+
if (e.errcode === 'SLACK_UNKNOWN_LINK') {
379+
setLink(null);
380+
} else if (e.errcode === 'SLACK_ROOM_NOT_PUBLIC') {
381+
setError('This bridge only allows public Matrix rooms to be linked.');
382+
} else if (e.errcode === 'SLACK_NOT_ENOUGH_POWER') {
383+
setError("You don't have permissions to link this room.");
384+
} else {
385+
console.error('Failed to get link:', e);
386+
setError(`Could not get link status. ${e.message}`);
387+
}
388+
} else {
389+
console.error('Failed to get link:', e);
390+
setError('Could not get link status.');
391+
}
382392
}
383393
}, [client, provisioningContext]);
384394

widget/src/SlackProvisioningClient.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,15 @@ export class SlackProvisioningClient {
4141
readonly client: ProvisioningClient,
4242
) {}
4343

44-
getLink = async(roomId: string): Promise<GetLinkResponse | undefined> => {
45-
try {
46-
const res = await this.client.request(
47-
'POST',
48-
'/getlink',
49-
{
50-
matrix_room_id: roomId,
51-
},
52-
);
53-
return res as GetLinkResponse;
54-
} catch (e) {
55-
if (e instanceof ProvisioningError && e.errcode === 'SLACK_UNKNOWN_LINK') {
56-
return undefined;
57-
}
58-
throw e;
59-
}
44+
getLink = async(roomId: string): Promise<GetLinkResponse> => {
45+
const res = await this.client.request(
46+
'POST',
47+
'/getlink',
48+
{
49+
matrix_room_id: roomId,
50+
},
51+
);
52+
return res as GetLinkResponse;
6053
};
6154

6255
listWorkspaces = async(): Promise<SlackWorkspace[]> => {

0 commit comments

Comments
 (0)