diff --git a/.github/workflows/docker-hub-latest.yml b/.github/workflows/docker-hub-latest.yml index 4ae92d84..9f384750 100644 --- a/.github/workflows/docker-hub-latest.yml +++ b/.github/workflows/docker-hub-latest.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2 - - name: Login to Docker Hub + - name: Log in to Docker Hub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} diff --git a/.github/workflows/docker-hub-release.yml b/.github/workflows/docker-hub-release.yml index c0db9413..d015840b 100644 --- a/.github/workflows/docker-hub-release.yml +++ b/.github/workflows/docker-hub-release.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v2 - name: Get release tag run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - name: Login to Docker Hub + - name: Log in to Docker Hub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 83819efa..ff1ac1ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,7 +65,7 @@ Bugfixes - Fix a bug which caused GitHub "ready for review" events to be unhandled. ([\#149](https://github.com/matrix-org/matrix-hookshot/issues/149)) - Fix a bug preventing `!hookshot jira project` from working ([\#166](https://github.com/matrix-org/matrix-hookshot/issues/166)) - Fix a few issues preventing GitHub notifications from working ([\#173](https://github.com/matrix-org/matrix-hookshot/issues/173)) -- Fixed an issue where the bridge bot would change it's displayname if a webhook event is handled while `generic.userIdPrefix` is not set in the config. ([\#215](https://github.com/matrix-org/matrix-hookshot/issues/215)) +- Fixed an issue where the bridge bot would change its displayname if a webhook event is handled while `generic.userIdPrefix` is not set in the config. ([\#215](https://github.com/matrix-org/matrix-hookshot/issues/215)) - Remove nonfunctional `gitlab notifications toggle` command. ([\#226](https://github.com/matrix-org/matrix-hookshot/issues/226)) diff --git a/changelog.d/267.misc b/changelog.d/267.misc new file mode 100644 index 00000000..ca579cd7 --- /dev/null +++ b/changelog.d/267.misc @@ -0,0 +1 @@ +Make some grammar corrections in code, chat notices and documentation. diff --git a/docs/setup.md b/docs/setup.md index 4219bba2..84dc7e6f 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -108,11 +108,11 @@ Each permission set can have a services. The `service` field can be: - `*`, for any service. The `level` can be: - - `commands` Can run commands within connected rooms, but NOT log into the bridge. - - `login` All the above, and can also log into the bridge. + - `commands` Can run commands within connected rooms, but NOT log in to the bridge. + - `login` All the above, and can also log in to the bridge. - `notifications` All the above, and can also bridge their notifications. - `manageConnections` All the above, and can create and delete connections (either via the provisioner, setup commands, or state events). - - `admin` All permissions. Currently there are no admin features so this exists as a placeholder. + - `admin` All permissions. Currently, there are no admin features so this exists as a placeholder. When permissions are checked, if a user matches any of the permission set and one of those grants the right level for a service, they are allowed access. If none of the @@ -134,7 +134,7 @@ permissions: services: - service: github level: manageConnections - # Allow users on this domain to login to jira and github. + # Allow users on this domain to log in to jira and github. - actor: support.example.com services: - service: jira diff --git a/docs/setup/figma.md b/docs/setup/figma.md index 4673f3d5..b2e73f91 100644 --- a/docs/setup/figma.md +++ b/docs/setup/figma.md @@ -29,7 +29,7 @@ The `accessToken` should be the personal access token for your account. The `passcode` should be a randomly generated code which is used to authenticate requests from Figma. -The bridge will automatically setup a webhook on Figma for you upon startup, and will automatically reconfigure that webhook if the `publicUrl` or `passcode` changes. +The bridge will automatically set up a webhook on Figma for you upon startup, and will automatically reconfigure that webhook if the `publicUrl` or `passcode` changes. ## Next steps diff --git a/docs/setup/jira.md b/docs/setup/jira.md index cdfc76d2..06c76836 100644 --- a/docs/setup/jira.md +++ b/docs/setup/jira.md @@ -25,7 +25,7 @@ jira: ... # See below ``` -You can omit the `oauth` section if you are not planning to allow users to login and use interactive features (i.e. webhook only mode). +You can omit the `oauth` section if you are not planning to allow users to log in and use interactive features (i.e. webhook only mode). ## Connecting Matrix users to JIRA @@ -85,7 +85,7 @@ jira: # The path to your webhooks listener on the "/jira/oauth" path. redirect_uri: http://localhost:5065/jira/oauth ``` -To start with, setup your JIRA instance to support OAuth. +To start with, set up your JIRA instance to support OAuth. 1. Open the **Administration** page for your JIRA instance. @@ -104,7 +104,7 @@ To start with, setup your JIRA instance to support OAuth. 1. Enter your `consumerKey` from the config file above. 2. The `consumerName` can be anything, but will be visible to users of your app. You could use something like `Matrix`, `Hookshot` or anything else. 3. The `publicKey` can be generated by running `openssl rsa -in jira_privatekey.pem -pubout` on the key you created earlier. -7. Congratulations, you now have OAuth setup. +7. Congratulations, you now have OAuth set up. ## Next steps diff --git a/docs/usage/auth.md b/docs/usage/auth.md index ffd5a6a0..6965f209 100644 --- a/docs/usage/auth.md +++ b/docs/usage/auth.md @@ -38,7 +38,7 @@ To authenticate with a personal access token: You can authenticate with GitLab by supplying a Personal Access Token. OAuth-style authentication isn't supported yet. -- You will need to have configured a GitLab instance in your config.yml for the instance you want to login to. +- You will need to have configured a GitLab instance in your config.yml for the instance you want to log in to. - Open https://%instance%/-/profile/personal_access_tokens (GitLab > User Settings > Access Tokens), where instance is your GitLab instance address. - For the public GitLab server, this would be "gitlab.com" - Give it a good name, and a sensible expiration date. For scopes you will need to tick `api`. @@ -49,7 +49,7 @@ yet. ## JIRA -You can login to JIRA via OAuth. This means you will need to have configured OAuth support in your `config.yml`, and +You can log in to JIRA via OAuth. This means you will need to have configured OAuth support in your `config.yml`, and have the endpoints required accessible from the internet. Authentication is required when trying to bridge JIRA resources into rooms. - Say `jira login` to get the URL to authenticate via. diff --git a/src/AdminRoom.ts b/src/AdminRoom.ts index 561d7578..dc622edd 100644 --- a/src/AdminRoom.ts +++ b/src/AdminRoom.ts @@ -160,7 +160,7 @@ export class AdminRoom extends AdminRoomCommandHandler { private async setGitHubNotificationsStateParticipating() { const newData = await this.saveAccountData((data) => { if (!data.github?.notifications?.enabled) { - throw Error('Notifications are not enabled') + throw Error('Notifications are not enabled.') } const oldState = data.github?.notifications?.participating ?? false; return { @@ -174,17 +174,17 @@ export class AdminRoom extends AdminRoomCommandHandler { }; }); if (newData.github?.notifications?.participating) { - return this.sendNotice(`Filtering for events you are participating in`); + return this.sendNotice(`Filtering for events you are participating in.`); } - return this.sendNotice(`Showing all events`); + return this.sendNotice(`Showing all events.`); } @botCommand("github notifications", {help: "Show the current notification settings", category: "github"}) public async getGitHubNotificationsState() { if (!this.notificationsEnabled("github")) { - return this.sendNotice(`Notifications are disabled`); + return this.sendNotice(`Notifications are disabled.`); } - return this.sendNotice(`Notifications are enabled, ${this.notificationsParticipating("github") ? "Showing only events you are particiapting in" : "Showing all events"}`); + return this.sendNotice(`Notifications are enabled, ${this.notificationsParticipating("github") ? "Showing only events you are particiapting in." : "Showing all events."}`); } @@ -192,7 +192,7 @@ export class AdminRoom extends AdminRoomCommandHandler { // @ts-ignore - property is used private async listProjects(username?: string, repo?: string) { if (!this.config.github) { - return this.sendNotice("The bridge is not configured with GitHub support"); + return this.sendNotice("The bridge is not configured with GitHub support."); } const octokit = await this.tokenStore.getOctokitForUser(this.userId); if (!octokit) { @@ -218,7 +218,7 @@ export class AdminRoom extends AdminRoomCommandHandler { })).data; } catch (ex) { log.warn(`Failed to fetch projects:`, ex); - return this.sendNotice(`Failed to fetch projects due to an error. See logs for details`); + return this.sendNotice(`Failed to fetch projects due to an error. See logs for details.`); } const content = `Projects for ${username}:\n${FormatUtil.projectListing(res)}\n`; @@ -234,7 +234,7 @@ export class AdminRoom extends AdminRoomCommandHandler { // @ts-ignore - property is used private async listProjects(org: string, repo?: string) { if (!this.config.github) { - return this.sendNotice("The bridge is not configured with GitHub support"); + return this.sendNotice("The bridge is not configured with GitHub support."); } const octokit = await this.tokenStore.getOctokitForUser(this.userId); if (!octokit) { @@ -254,10 +254,10 @@ export class AdminRoom extends AdminRoomCommandHandler { })); } catch (ex) { if (ex.status === 404) { - return this.sendNotice('Not found'); + return this.sendNotice(`${repo ? "Repository" : "Org"} does not exist.`); } log.warn(`Failed to fetch projects:`, ex); - return this.sendNotice(`Failed to fetch projects due to an error. See logs for details`); + return this.sendNotice(`Failed to fetch projects due to an error. See logs for details.`); } const content = `Projects for ${org}:\n` + res.data.map(r => ` - ${FormatUtil.projectListing([r])}\n`).join("\n"); @@ -273,7 +273,7 @@ export class AdminRoom extends AdminRoomCommandHandler { // @ts-ignore - property is used private async openProject(projectId: string) { if (!this.config.github) { - return this.sendNotice("The bridge is not configured with GitHub support"); + return this.sendNotice("The bridge is not configured with GitHub support."); } const octokit = await this.tokenStore.getOctokitForUser(this.userId); if (!octokit) { @@ -287,10 +287,10 @@ export class AdminRoom extends AdminRoomCommandHandler { this.emit('open.project', project.data); } catch (ex) { if (ex.status === 404) { - return this.sendNotice('Not found'); + return this.sendNotice('Project does not exist.'); } log.warn(`Failed to fetch project:`, ex); - return this.sendNotice(`Failed to fetch project due to an error. See logs for details`); + return this.sendNotice(`Failed to fetch project due to an error. See logs for details.`); } } @@ -299,7 +299,7 @@ export class AdminRoom extends AdminRoomCommandHandler { private async listDiscussions(owner: string, repo: string, numberStr: string) { const number = parseInt(numberStr); if (!this.config.github) { - return this.sendNotice("The bridge is not configured with GitHub support"); + return this.sendNotice("The bridge is not configured with GitHub support."); } const octokit = await this.tokenStore.getOctokitForUser(this.userId); if (!octokit) { @@ -311,10 +311,10 @@ export class AdminRoom extends AdminRoomCommandHandler { this.emit('open.discussion', owner, repo, discussions); } catch (ex) { if (ex.status === 404) { - return this.sendNotice('Not found'); + return this.sendNotice('Discussion does not exist.'); } log.warn(`Failed to fetch discussions:`, ex); - return this.sendNotice(`Failed to fetch discussions due to an error. See logs for details`); + return this.sendNotice(`Failed to fetch discussions due to an error. See logs for details.`); } } @@ -325,7 +325,7 @@ export class AdminRoom extends AdminRoomCommandHandler { // @ts-ignore - property is used private async gitLabOpenIssue(url: string) { if (!this.config.gitlab) { - return this.sendNotice("The bridge is not configured with GitLab support"); + return this.sendNotice("The bridge is not configured with GitLab support."); } const urlResult = GitLabClient.splitUrlIntoParts(this.config.gitlab.instances, url); @@ -336,7 +336,7 @@ export class AdminRoom extends AdminRoomCommandHandler { const instance = this.config.gitlab.instances[instanceName]; const client = await this.tokenStore.getGitLabForUser(this.userId, instance.url); if (!client) { - return this.sendNotice("You have not added a personal access token for GitLab"); + return this.sendNotice("You have not added a personal access token for GitLab."); } const getIssueOpts = { issue: parseInt(parts[parts.length-1]), @@ -351,11 +351,11 @@ export class AdminRoom extends AdminRoomCommandHandler { public async setGitLabPersonalAccessToken(instanceName: string, accessToken: string) { let me: GetUserResponse; if (!this.config.gitlab) { - return this.sendNotice("The bridge is not configured with GitLab support"); + return this.sendNotice("The bridge is not configured with GitLab support."); } const instance = this.config.gitlab.instances[instanceName]; if (!instance) { - return this.sendNotice("The bridge is not configured for this GitLab instance"); + return this.sendNotice("The bridge is not configured for this GitLab instance."); } try { const client = new GitLabClient(instance.url, accessToken); @@ -365,22 +365,22 @@ export class AdminRoom extends AdminRoomCommandHandler { log.error("Gitlab auth error:", ex); return this.sendNotice("Could not authenticate with GitLab. Is your token correct?"); } - await this.sendNotice(`Connected as ${me.username}. Token stored`); + await this.sendNotice(`Connected as ${me.username}. Token stored.`); return this.tokenStore.storeUserToken("gitlab", this.userId, accessToken, instance.url); } @botCommand("gitlab hastoken", {help: "Check if you have a token stored for GitLab", requiredArgs: ["instanceName"], category: "gitlab"}) public async gitlabHasPersonalToken(instanceName: string) { if (!this.config.gitlab) { - return this.sendNotice("The bridge is not configured with GitLab support"); + return this.sendNotice("The bridge is not configured with GitLab support."); } const instance = this.config.gitlab.instances[instanceName]; if (!instance) { - return this.sendNotice("The bridge is not configured for this GitLab instance"); + return this.sendNotice("The bridge is not configured for this GitLab instance."); } const result = await this.tokenStore.getUserToken("gitlab", this.userId, instance.url); if (result === null) { - return this.sendNotice("You do not currently have a token stored"); + return this.sendNotice("You do not currently have a token stored."); } return this.sendNotice("A token is stored for your GitLab account."); } @@ -388,7 +388,7 @@ export class AdminRoom extends AdminRoomCommandHandler { @botCommand("filters list", "List your saved filters") public async getFilters() { if (this.notifFilter.empty) { - return this.sendNotice("You do not currently have any filters"); + return this.sendNotice("You do not currently have any filters."); } const filterText = Object.entries(this.notifFilter.filters).map(([name, value]) => { const userText = value.users.length ? `users: ${value.users.join("|")}` : ''; @@ -407,7 +407,7 @@ export class AdminRoom extends AdminRoomCommandHandler { const users = parameters.filter(param => param.toLowerCase().startsWith("users:")).map(param => param.toLowerCase().substring("users:".length).split(",")).flat(); const repos = parameters.filter(param => param.toLowerCase().startsWith("repos:")).map(param => param.toLowerCase().substring("repos:".length).split(",")).flat(); if (orgs.length + users.length + repos.length === 0) { - return this.sendNotice("You must specify some filter options like 'orgs:matrix-org,half-shot', 'users:Half-Shot' or 'repos:matrix-hookshot'"); + return this.sendNotice("You must specify some filter options like 'orgs:matrix-org,half-shot', 'users:Half-Shot' or 'repos:matrix-hookshot'."); } this.notifFilter.setFilter(name, { orgs, @@ -415,20 +415,20 @@ export class AdminRoom extends AdminRoomCommandHandler { repos, }); await this.botIntent.underlyingClient.sendStateEvent(this.roomId, NotifFilter.StateType, "", this.notifFilter.getStateContent()); - return this.sendNotice(`Stored new filter "${name}". You can now apply the filter by saying 'filters notifications toggle $name'`); + return this.sendNotice(`Stored new filter "${name}". You can now apply the filter by saying 'filters notifications toggle $name'.`); } @botCommand("filters notifications toggle", "Apply a filter as a whitelist to your notifications", ["name"]) public async setFiltersNotificationsToggle(name: string) { if (!this.notifFilter.filters[name]) { - return this.sendNotice(`Filter "${name}" doesn't exist'`); + return this.sendNotice(`Filter "${name}" doesn't exist.`); } if (this.notifFilter.forNotifications.has(name)) { this.notifFilter.forNotifications.delete(name); - await this.sendNotice(`Filter "${name}" disabled for notifications`); + await this.sendNotice(`Filter "${name}" disabled for notifications.`); } else { this.notifFilter.forNotifications.add(name); - await this.sendNotice(`Filter "${name}" enabled for notifications`); + await this.sendNotice(`Filter "${name}" enabled for notifications.`); } return this.botIntent.underlyingClient.sendStateEvent(this.roomId, NotifFilter.StateType, "", this.notifFilter.getStateContent()); } @@ -449,7 +449,7 @@ export class AdminRoom extends AdminRoomCommandHandler { const checkPermission = (service: string, level: BridgePermissionLevel) => this.config.checkPermission(this.userId, service, level); const result = await handleCommand(this.userId, command, AdminRoom.botCommands, this, checkPermission); if (!result.handled) { - return this.sendNotice("Command not understood"); + return this.sendNotice("Command not understood."); } if ("error" in result) { @@ -488,7 +488,7 @@ export class AdminRoom extends AdminRoomCommandHandler { } } - public async setupWidget() { + public async setUpWidget() { try { const res = await this.botIntent.underlyingClient.getRoomStateEvent(this.roomId, "im.vector.modular.widgets", "bridge_control"); if (res) { diff --git a/src/BotCommands.ts b/src/BotCommands.ts index e546293a..5c83727b 100644 --- a/src/BotCommands.ts +++ b/src/BotCommands.ts @@ -106,10 +106,10 @@ export async function handleCommand( if (command) { const permissionService = command.permissionService || defaultPermissionService; if (permissionService && !permissionCheckFn(permissionService, command.permissionLevel || BridgePermissionLevel.commands)) { - return {handled: true, error: "You do not have permission to use this command"}; + return {handled: true, error: "You do not have permission to use this command."}; } if (command.requiredArgs && command.requiredArgs.length > parts.length - i) { - return {handled: true, error: "Missing args"}; + return {handled: true, error: "Missing at least one required parameter."}; } const args = parts.slice(i); if (command.includeUserId) { diff --git a/src/Bridge.ts b/src/Bridge.ts index 3ccc4622..92a80ddf 100644 --- a/src/Bridge.ts +++ b/src/Bridge.ts @@ -109,7 +109,7 @@ export class Bridge { } if (this.config.figma) { - // Ensure webhooks are setup + // Ensure webhooks are set up await ensureFigmaWebhooks(this.config.figma, this.as.botClient); } @@ -621,12 +621,12 @@ export class Bridge { // No state yet } } - const adminRoom = await this.setupAdminRoom(roomId, accountData, notifContent || NotifFilter.getDefaultContent()); + const adminRoom = await this.setUpAdminRoom(roomId, accountData, notifContent || NotifFilter.getDefaultContent()); // Call this on startup to set the state await this.onAdminRoomSettingsChanged(adminRoom, accountData, { admin_user: accountData.admin_user }); log.debug(`Room ${roomId} is connected to: ${adminRoom.toString()}`); } catch (ex) { - log.error(`Failed to setup admin room ${roomId}:`, ex); + log.error(`Failed to set up admin room ${roomId}:`, ex); } })); @@ -678,7 +678,7 @@ export class Bridge { } await retry(() => this.as.botIntent.joinRoom(roomId), 5); if (event.content.is_direct) { - const room = await this.setupAdminRoom(roomId, {admin_user: event.sender}, NotifFilter.getDefaultContent()); + const room = await this.setUpAdminRoom(roomId, {admin_user: event.sender}, NotifFilter.getDefaultContent()); await this.as.botIntent.underlyingClient.setRoomAccountData( BRIDGE_ROOM_TYPE, roomId, room.accountData, ); @@ -1016,10 +1016,10 @@ export class Bridge { is_direct: true, preset: "trusted_private_chat", }); - return this.setupAdminRoom(roomId, {admin_user: userId}, NotifFilter.getDefaultContent()); + return this.setUpAdminRoom(roomId, {admin_user: userId}, NotifFilter.getDefaultContent()); } - private async setupAdminRoom(roomId: string, accountData: AdminAccountData, notifContent: NotificationFilterStateContent) { + private async setUpAdminRoom(roomId: string, accountData: AdminAccountData, notifContent: NotificationFilterStateContent) { const adminRoom = new AdminRoom( roomId, accountData, notifContent, this.as.botIntent, this.tokenStore, this.config, ); @@ -1053,9 +1053,9 @@ export class Bridge { }); this.adminRooms.set(roomId, adminRoom); if (this.config.widgets?.addToAdminRooms && this.config.widgets.publicUrl) { - await adminRoom.setupWidget(); + await adminRoom.setUpWidget(); } - log.debug(`Setup ${roomId} as an admin room for ${adminRoom.userId}`); + log.debug(`Set up ${roomId} as an admin room for ${adminRoom.userId}`); return adminRoom; } } \ No newline at end of file diff --git a/src/Connections/CommandConnection.ts b/src/Connections/CommandConnection.ts index 8c45c9ce..4359b10d 100644 --- a/src/Connections/CommandConnection.ts +++ b/src/Connections/CommandConnection.ts @@ -48,7 +48,7 @@ export abstract class CommandConnection extends BaseConnection { }); await this.botClient.sendEvent(this.roomId, 'm.room.message', { msgtype: "m.notice", - body: humanError ? `Failed to handle command: ${humanError}` : "Failed to handle command", + body: humanError ? `Failed to handle command: ${humanError}` : "Failed to handle command.", }); log.warn(`Failed to handle command:`, error); return true; diff --git a/src/Connections/GithubRepo.ts b/src/Connections/GithubRepo.ts index 8f79b8e0..dfb0376c 100644 --- a/src/Connections/GithubRepo.ts +++ b/src/Connections/GithubRepo.ts @@ -514,7 +514,7 @@ export class GitHubRepoConnection extends CommandConnection implements IConnecti const workflow = workflows.data.workflows.find(w => w.name.toLowerCase().trim() === name.toLowerCase().trim()); if (!workflow) { const workflowNames = workflows.data.workflows.map(w => w.name).join(', '); - await this.as.botIntent.sendText(this.roomId, `Could not find a workflow by the name of "${name}". The workflows on this repository are ${workflowNames}`, "m.notice"); + await this.as.botIntent.sendText(this.roomId, `Could not find a workflow by the name of "${name}". The workflows on this repository are ${workflowNames}.`, "m.notice"); return; } try { @@ -544,7 +544,7 @@ export class GitHubRepoConnection extends CommandConnection implements IConnecti throw ex; } - await this.as.botIntent.sendText(this.roomId, `Workflow started`, "m.notice"); + await this.as.botIntent.sendText(this.roomId, `Workflow started.`, "m.notice"); } public async onIssueCreated(event: IssuesOpenedEvent) { diff --git a/src/Connections/GitlabRepo.ts b/src/Connections/GitlabRepo.ts index 1c30e1c4..34bc4f3a 100644 --- a/src/Connections/GitlabRepo.ts +++ b/src/Connections/GitlabRepo.ts @@ -76,7 +76,7 @@ export class GitLabRepoConnection extends CommandConnection { public async onCreateIssue(userId: string, title: string, description?: string, labels?: string) { const client = await this.tokenStore.getGitLabForUser(userId, this.instance.url); if (!client) { - await this.as.botIntent.sendText(this.roomId, "You must login to create an issue", "m.notice"); + await this.as.botIntent.sendText(this.roomId, "You must be logged in to create an issue.", "m.notice"); throw Error('Not logged in'); } const res = await client.issues.create({ @@ -99,7 +99,7 @@ export class GitLabRepoConnection extends CommandConnection { public async onClose(userId: string, number: string) { const client = await this.tokenStore.getGitLabForUser(userId, this.instance.url); if (!client) { - await this.as.botIntent.sendText(this.roomId, "You must login to create an issue", "m.notice"); + await this.as.botIntent.sendText(this.roomId, "You must be logged in to create an issue.", "m.notice"); throw Error('Not logged in'); } diff --git a/src/Connections/IConnection.ts b/src/Connections/IConnection.ts index 24924365..91b74427 100644 --- a/src/Connections/IConnection.ts +++ b/src/Connections/IConnection.ts @@ -16,7 +16,7 @@ export interface IConnection { */ get connectionId(): string; /** - * When a room gets an update to it's state. + * When a room gets an update to its state. */ onStateUpdate?: (ev: MatrixEvent) => Promise; /** diff --git a/src/Connections/SetupConnection.ts b/src/Connections/SetupConnection.ts index 9e585a3b..48ca16c9 100644 --- a/src/Connections/SetupConnection.ts +++ b/src/Connections/SetupConnection.ts @@ -41,19 +41,19 @@ export class SetupConnection extends CommandConnection { ) } - @botCommand("github repo", "Create a connection for a GitHub repository. (You must be logged in with GitHub to do this)", ["url"], [], true) + @botCommand("github repo", "Create a connection for a GitHub repository. (You must be logged in with GitHub to do this.)", ["url"], [], true) public async onGitHubRepo(userId: string, url: string) { if (!this.githubInstance || !this.config.github) { - throw new CommandError("not-configured", "The bridge is not configured to support GitHub"); + throw new CommandError("not-configured", "The bridge is not configured to support GitHub."); } if (!this.config.checkPermission(userId, "github", BridgePermissionLevel.manageConnections)) { - throw new CommandError('You are not permitted to provision connections for GitHub'); + throw new CommandError('You are not permitted to provision connections for GitHub.'); } if (!await this.as.botClient.userHasPowerLevelFor(userId, this.roomId, "", true)) { - throw new CommandError("not-configured", "You must be able to set state in a room ('Change settings') in order to setup new integrations."); + throw new CommandError("not-configured", "You must be able to set state in a room ('Change settings') in order to set up new integrations."); } if (!await this.as.botClient.userHasPowerLevelFor(this.as.botUserId, this.roomId, GitHubRepoConnection.CanonicalEventType, true)) { - throw new CommandError("Bot lacks power level to set room state", "I do not have permission to setup a bridge in this room. Please promote me to an Admin/Moderator"); + throw new CommandError("Bot lacks power level to set room state", "I do not have permission to set up a bridge in this room. Please promote me to an Admin/Moderator."); } const octokit = await this.tokenStore.getOctokitForUser(userId); if (!octokit) { @@ -61,7 +61,7 @@ export class SetupConnection extends CommandConnection { } const urlParts = /^https:\/\/github\.com\/([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/.exec(url.trim().toLowerCase()); if (!urlParts) { - throw new CommandError("Invalid GitHub url", "The GitHub url you entered was not valid"); + throw new CommandError("Invalid GitHub url", "The GitHub url you entered was not valid."); } const [, org, repo] = urlParts; const res = await GitHubRepoConnection.provisionConnection(this.roomId, userId, {org, repo}, this.as, this.tokenStore, this.githubInstance, this.config.github); @@ -69,20 +69,20 @@ export class SetupConnection extends CommandConnection { await this.as.botClient.sendNotice(this.roomId, `Room configured to bridge ${org}/${repo}`); } - @botCommand("jira project", "Create a connection for a JIRA project. (You must be logged in with JIRA to do this)", ["url"], [], true) + @botCommand("jira project", "Create a connection for a JIRA project. (You must be logged in with JIRA to do this.)", ["url"], [], true) public async onJiraProject(userId: string, urlStr: string) { const url = new URL(urlStr); if (!this.config.jira) { - throw new CommandError("not-configured", "The bridge is not configured to support Jira"); + throw new CommandError("not-configured", "The bridge is not configured to support Jira."); } if (!this.config.checkPermission(userId, "jira", BridgePermissionLevel.manageConnections)) { - throw new CommandError('You are not permitted to provision connections for Jira'); + throw new CommandError('You are not permitted to provision connections for Jira.'); } if (!await this.as.botClient.userHasPowerLevelFor(userId, this.roomId, "", true)) { - throw new CommandError("not-configured", "You must be able to set state in a room ('Change settings') in order to setup new integrations."); + throw new CommandError("not-configured", "You must be able to set state in a room ('Change settings') in order to set up new integrations."); } if (!await this.as.botClient.userHasPowerLevelFor(this.as.botUserId, this.roomId, GitHubRepoConnection.CanonicalEventType, true)) { - throw new CommandError("Bot lacks power level to set room state", "I do not have permission to setup a bridge in this room. Please promote me to an Admin/Moderator"); + throw new CommandError("Bot lacks power level to set room state", "I do not have permission to set up a bridge in this room. Please promote me to an Admin/Moderator."); } const jiraClient = await this.tokenStore.getJiraForUser(userId, urlStr); if (!jiraClient) { @@ -91,57 +91,57 @@ export class SetupConnection extends CommandConnection { const urlParts = /.+\/projects\/(\w+)\/?(\w+\/?)*$/.exec(url.pathname.toLowerCase()); const projectKey = urlParts?.[1] || url.searchParams.get('projectKey'); if (!projectKey) { - throw new CommandError("Invalid Jira url", "The JIRA project url you entered was not valid. It should be in the format of `https://jira-instance/.../projects/PROJECTKEY/...` or `.../RapidBoard.jspa?projectKey=TEST`"); + throw new CommandError("Invalid Jira url", "The JIRA project url you entered was not valid. It should be in the format of `https://jira-instance/.../projects/PROJECTKEY/...` or `.../RapidBoard.jspa?projectKey=TEST`."); } const safeUrl = `https://${url.host}/projects/${projectKey}`; const res = await JiraProjectConnection.provisionConnection(this.roomId, userId, { url: safeUrl }, this.as, this.tokenStore); await this.as.botClient.sendStateEvent(this.roomId, JiraProjectConnection.CanonicalEventType, safeUrl, res.stateEventContent); - await this.as.botClient.sendNotice(this.roomId, `Room configured to bridge Jira project ${res.connection.projectKey}`); + await this.as.botClient.sendNotice(this.roomId, `Room configured to bridge Jira project ${res.connection.projectKey}.`); } - @botCommand("webhook", "Create an inbound webhook", ["name"], [], true) + @botCommand("webhook", "Create an inbound webhook.", ["name"], [], true) public async onWebhook(userId: string, name: string) { if (!this.config.generic?.enabled) { - throw new CommandError("not-configured", "The bridge is not configured to support webhooks"); + throw new CommandError("not-configured", "The bridge is not configured to support webhooks."); } if (!this.config.checkPermission(userId, "webhooks", BridgePermissionLevel.manageConnections)) { - throw new CommandError('You are not permitted to provision connections for generic webhooks'); + throw new CommandError('You are not permitted to provision connections for generic webhooks.'); } if (!await this.as.botClient.userHasPowerLevelFor(userId, this.roomId, "", true)) { - throw new CommandError("not-configured", "You must be able to set state in a room ('Change settings') in order to setup new integrations."); + throw new CommandError("not-configured", "You must be able to set state in a room ('Change settings') in order to set up new integrations."); } if (!await this.as.botClient.userHasPowerLevelFor(this.as.botUserId, this.roomId, GitHubRepoConnection.CanonicalEventType, true)) { - throw new CommandError("Bot lacks power level to set room state", "I do not have permission to setup a bridge in this room. Please promote me to an Admin/Moderator"); + throw new CommandError("Bot lacks power level to set room state", "I do not have permission to set up a bridge in this room. Please promote me to an Admin/Moderator."); } if (!name || name.length < 3 || name.length > 64) { - throw new CommandError("Bad webhook name", "A webhook name must be between 3-64 characters"); + throw new CommandError("Bad webhook name", "A webhook name must be between 3-64 characters."); } const hookId = uuid(); const url = `${this.config.generic.urlPrefix}${this.config.generic.urlPrefix.endsWith('/') ? '' : '/'}${hookId}`; await GenericHookConnection.ensureRoomAccountData(this.roomId, this.as, hookId, name); await this.as.botClient.sendStateEvent(this.roomId, GenericHookConnection.CanonicalEventType, name, {hookId, name}); const adminRoom = await this.getOrCreateAdminRoom(userId); - await adminRoom.sendNotice(`You have bridged a webhook. Please configure your webhook source to use \`${url}\``); + await adminRoom.sendNotice(`You have bridged a webhook. Please configure your webhook source to use \`${url}\`.`); return this.as.botClient.sendHtmlNotice(this.roomId, md.renderInline(`Room configured to bridge webhooks. See admin room for secret url.`)); } - @botCommand("figma file", "Bridge a Figma file to the room", ["url"], [], true) + @botCommand("figma file", "Bridge a Figma file to the room.", ["url"], [], true) public async onFigma(userId: string, url: string) { if (!this.config.figma) { - throw new CommandError("not-configured", "The bridge is not configured to support Figma"); + throw new CommandError("not-configured", "The bridge is not configured to support Figma."); } if (!this.config.checkPermission(userId, "figma", BridgePermissionLevel.manageConnections)) { - throw new CommandError('You are not permitted to provision connections for Figma'); + throw new CommandError('You are not permitted to provision connections for Figma.'); } if (!await this.as.botClient.userHasPowerLevelFor(userId, this.roomId, "", true)) { - throw new CommandError("not-configured", "You must be able to set state in a room ('Change settings') in order to setup new integrations."); + throw new CommandError("not-configured", "You must be able to set state in a room ('Change settings') in order to set up new integrations."); } if (!await this.as.botClient.userHasPowerLevelFor(this.as.botUserId, this.roomId, GitHubRepoConnection.CanonicalEventType, true)) { - throw new CommandError("Bot lacks power level to set room state", "I do not have permission to setup a bridge in this room. Please promote me to an Admin/Moderator"); + throw new CommandError("Bot lacks power level to set room state", "I do not have permission to set up a bridge in this room. Please promote me to an Admin/Moderator."); } const res = /https:\/\/www\.figma\.com\/file\/(\w+).+/.exec(url); if (!res) { - throw new CommandError("Invalid Figma url", "The Figma file url you entered was not valid. It should be in the format of `https://figma.com/file/FILEID/...`"); + throw new CommandError("Invalid Figma url", "The Figma file url you entered was not valid. It should be in the format of `https://figma.com/file/FILEID/...`."); } const [, fileId] = res; await this.as.botClient.sendStateEvent(this.roomId, FigmaFileConnection.CanonicalEventType, fileId, {fileId}); diff --git a/src/Github/AdminCommands.ts b/src/Github/AdminCommands.ts index 68ffe0cd..c4f881fa 100644 --- a/src/Github/AdminCommands.ts +++ b/src/Github/AdminCommands.ts @@ -20,22 +20,22 @@ export function generateGitHubOAuthUrl(clientId: string, redirectUri: string, st } export class GitHubBotCommands extends AdminRoomCommandHandler { - @botCommand("github login", {help: "Login to GitHub", category: "github"}) + @botCommand("github login", {help: "Log in to GitHub", category: "github"}) public async loginCommand() { if (!this.config.github) { - throw new CommandError("no-github-support", "The bridge is not configured with GitHub support"); + throw new CommandError("no-github-support", "The bridge is not configured with GitHub support."); } if (!this.config.github.oauth) { - throw new CommandError("no-github-support", "The bridge is not configured with GitHub OAuth support"); + throw new CommandError("no-github-support", "The bridge is not configured with GitHub OAuth support."); } const state = this.tokenStore.createStateForOAuth(this.userId); - return this.sendNotice(`To login, open ${generateGitHubOAuthUrl(this.config.github.oauth.client_id, this.config.github.oauth.redirect_uri, state)} to link your account to the bridge`); + return this.sendNotice(`Open ${generateGitHubOAuthUrl(this.config.github.oauth.client_id, this.config.github.oauth.redirect_uri, state)} to link your account to the bridge.`); } @botCommand("github setpersonaltoken", {help: "Set your personal access token for GitHub", requiredArgs: ['accessToken'], category: "github"}) public async setGHPersonalAccessToken(accessToken: string) { if (!this.config.github) { - throw new CommandError("no-github-support", "The bridge is not configured with GitHub support"); + throw new CommandError("no-github-support", "The bridge is not configured with GitHub support."); } let me; try { @@ -46,18 +46,18 @@ export class GitHubBotCommands extends AdminRoomCommandHandler { await this.sendNotice("Could not authenticate with GitHub. Is your token correct?"); return; } - await this.sendNotice(`Connected as ${me.data.login}. Token stored`); + await this.sendNotice(`Connected as ${me.data.login}. Token stored.`); await this.tokenStore.storeUserToken("github", this.userId, JSON.stringify({access_token: accessToken, token_type: 'pat'} as GitHubOAuthToken)); } @botCommand("github hastoken", {help: "Check if you have a token stored for GitHub", category: "github"}) public async hasPersonalToken() { if (!this.config.github) { - throw new CommandError("no-github-support", "The bridge is not configured with GitHub support"); + throw new CommandError("no-github-support", "The bridge is not configured with GitHub support."); } const result = await this.tokenStore.getUserToken("github", this.userId); if (result === null) { - await this.sendNotice("You do not currently have a token stored"); + await this.sendNotice("You do not currently have a token stored."); return; } await this.sendNotice("A token is stored for your GitHub account."); diff --git a/src/Jira/AdminCommands.ts b/src/Jira/AdminCommands.ts index a4318709..28ac0dbc 100644 --- a/src/Jira/AdminCommands.ts +++ b/src/Jira/AdminCommands.ts @@ -7,22 +7,22 @@ import { CLOUD_INSTANCE } from "./Client"; const log = new LogWrapper('JiraBotCommands'); export class JiraBotCommands extends AdminRoomCommandHandler { - @botCommand("jira login", {help: "Login to JIRA", category: "jira"}) + @botCommand("jira login", {help: "Log in to JIRA", category: "jira"}) public async loginCommand() { if (!this.config.jira?.oauth || !this.tokenStore.jiraOAuth) { - this.sendNotice(`Bot is not configured with JIRA OAuth support`); + this.sendNotice(`Bot is not configured with JIRA OAuth support.`); return; } const state = this.tokenStore.createStateForOAuth(this.userId); const url = await this.tokenStore.jiraOAuth?.getAuthUrl(state); - await this.sendNotice(`To login, open ${url} to link your account to the bridge`); + await this.sendNotice(`Open ${url} to link your account to the bridge.`); } @botCommand("jira logout", {help: "Clear any login information", category: "jira"}) public async logout() { if (!this.config.jira?.oauth || !this.tokenStore.jiraOAuth) { - this.sendNotice(`Bot is not configured with JIRA OAuth support`); + this.sendNotice(`Bot is not configured with JIRA OAuth support.`); return; } if (await this.tokenStore.clearUserToken("jira", this.userId, this.config.jira.url || CLOUD_INSTANCE)) { @@ -34,13 +34,13 @@ export class JiraBotCommands extends AdminRoomCommandHandler { @botCommand("jira whoami", {help: "Determine JIRA identity", category: "jira"}) public async whoami() { if (!this.config.jira) { - await this.sendNotice(`Bot is not configured with JIRA OAuth support`); + await this.sendNotice(`Bot is not configured with JIRA OAuth support.`); return; } const client = await this.tokenStore.getJiraForUser(this.userId, this.config.jira.url); if (!client) { - await this.sendNotice(`You are not logged into JIRA`); + await this.sendNotice(`You are not logged into JIRA.`); return; } // Get all resources for user @@ -49,10 +49,10 @@ export class JiraBotCommands extends AdminRoomCommandHandler { resources = await client.getAccessibleResources(); } catch (ex) { log.warn(`Could not request resources from JIRA API: `, ex); - await this.sendNotice(`Could not request JIRA resources due to an error`); + await this.sendNotice(`Could not request JIRA resources due to an error.`); return; } - let response = resources.length === 0 ? `You do not have any instances authorised with this bot` : 'You have access to the following instances:'; + let response = resources.length === 0 ? `You do not have any instances authorised with this bot.` : 'You have access to the following instances:'; for (const resource of resources) { const clientForResource = await client.getClientForResource(resource); if (!clientForResource) { diff --git a/src/Jira/Router.ts b/src/Jira/Router.ts index afbed434..b0eeee9c 100644 --- a/src/Jira/Router.ts +++ b/src/Jira/Router.ts @@ -134,7 +134,7 @@ export class JiraProvisionerRouter { private async onOAuth(req: Request, res: Response<{url: string}>) { if (!this.tokenStore.jiraOAuth) { - throw new ApiError('JIRA OAuth is disabled', ErrCode.DisabledFeature); + throw new ApiError('JIRA OAuth is disabled.', ErrCode.DisabledFeature); } const url = await this.tokenStore.jiraOAuth.getAuthUrl(this.tokenStore.createStateForOAuth(req.query.userId)); res.send({ url }); @@ -157,7 +157,7 @@ export class JiraProvisionerRouter { } } catch (ex) { log.warn(`Failed to fetch accessible resources for ${req.query.userId}`, ex); - return next( new ApiError("Could not fetch accessible resources for JIRA user", ErrCode.Unknown)); + return next( new ApiError("Could not fetch accessible resources for JIRA user.", ErrCode.Unknown)); } return res.send({ loggedIn: true, @@ -177,10 +177,10 @@ export class JiraProvisionerRouter { resClient = await jiraUser.getClientForName(req.params.instanceName); } catch (ex) { log.warn(`Failed to fetch client for ${req.params.instanceName} for ${req.query.userId}`, ex); - return next( new ApiError("Could not fetch accessible resources for JIRA user", ErrCode.Unknown)); + return next( new ApiError("Could not fetch accessible resources for JIRA user.", ErrCode.Unknown)); } if (!resClient) { - return next( new ApiError("Instance not known or not accessible to this user", ErrCode.ForbiddenUser)); + return next( new ApiError("Instance not known or not accessible to this user.", ErrCode.ForbiddenUser)); } const projects = []; @@ -195,7 +195,7 @@ export class JiraProvisionerRouter { } } catch (ex) { log.warn(`Failed to fetch accessible projects for ${req.params.instanceName} / ${req.query.userId}`, ex); - return next( new ApiError("Could not fetch accessible projects for JIRA user", ErrCode.Unknown)); + return next( new ApiError("Could not fetch accessible projects for JIRA user.", ErrCode.Unknown)); } return res.send(projects); diff --git a/src/UserTokenStore.ts b/src/UserTokenStore.ts index f0f0c81b..aeadbff5 100644 --- a/src/UserTokenStore.ts +++ b/src/UserTokenStore.ts @@ -76,7 +76,7 @@ export class UserTokenStore { public async storeUserToken(type: TokenType, userId: string, token: string, instanceUrl?: string): Promise { if (!this.config.checkPermission(userId, type, BridgePermissionLevel.login)) { - throw new ApiError('User does not have permission to login to service', ErrCode.ForbiddenUser); + throw new ApiError('User does not have permission to log in to service', ErrCode.ForbiddenUser); } const key = tokenKey(type, userId, false, instanceUrl); const tokenParts: string[] = []; diff --git a/src/figma/index.ts b/src/figma/index.ts index 8cd7198d..bf1ad32a 100644 --- a/src/figma/index.ts +++ b/src/figma/index.ts @@ -55,7 +55,7 @@ export async function ensureFigmaWebhooks(figmaConfig: BridgeConfigFigma, matrix webhookDefinition = res.data as FigmaWebhookDefinition; await matrixClient.setAccountData(accountDataKey, {webhookId: webhookDefinition.id}); } - // Webhook is ready and setup + // Webhook is ready and set up } } \ No newline at end of file diff --git a/src/provisioning/api.md b/src/provisioning/api.md index cc4aebd4..c1a2cd31 100644 --- a/src/provisioning/api.md +++ b/src/provisioning/api.md @@ -45,7 +45,7 @@ Request the connection types enabled for this bridge. "type": "JiraProject", // The name of the connection "eventType": "uk.half-shot.matrix-hookshot.jira.project", // Corresponds to the state type for the connection "service": "jira", // or github, webhook. A human-readable service name to make things look pretty - "botUserId": "@hookshot:yourdomain.com", // The bot mxid for the service. Currently this is the sender_localpart, but may change in the future. + "botUserId": "@hookshot:yourdomain.com", // The bot mxid for the service. Currently, this is the sender_localpart, but may change in the future. } } ``` @@ -62,7 +62,7 @@ Request the connections for a given room. The `{roomId}` parameter is the target "eventType": "uk.half-shot.matrix-hookshot.jira.project", // Corresponds to the state type in the connection "id": "opaque-unique-id", // An opaque ID used to refer to this connection. Should **NOT** be assumed to be stable. "service": "jira", // or github, webhook. A human-readable service name to make things look pretty - "botUserId": "@hookshot:yourdomain.com", // The bot mxid for the service. Currently this is the sender_localpart, but may change in the future. + "botUserId": "@hookshot:yourdomain.com", // The bot mxid for the service. Currently, this is the sender_localpart, but may change in the future. "config": { // ... connection specific details, can be configured. } @@ -82,7 +82,7 @@ Request details of a single connection. The `{roomId}` parameter is the target M "eventType": "uk.half-shot.matrix-hookshot.jira.project", // Corresponds to the state type in the connection "id": "opaque-unique-id", // An opaque ID used to refer to this connection. Should **NOT** be assumed to be stable. "service": "jira", // or github, webhook. A human-readable service name to make things look pretty - "botUserId": "@hookshot:yourdomain.com", // The bot mxid for the service. Currently this is the sender_localpart, but may change in the future. + "botUserId": "@hookshot:yourdomain.com", // The bot mxid for the service. Currently, this is the sender_localpart, but may change in the future. "config": { // ... connection specific details, can be configured. } @@ -110,7 +110,7 @@ The body of the request is the configuration for the connection, which will be t "eventType": "uk.half-shot.matrix-hookshot.jira.project", // Corresponds to the state type in the connection "id": "opaque-unique-id", // An opaque ID used to refer to this connection. Should **NOT** be assumed to be stable. "service": "jira", // or github, webhook. A human-readable service name to make things look pretty - "botUserId": "@hookshot:yourdomain.com", // The bot mxid for the service. Currently this is the sender_localpart, but may change in the future. + "botUserId": "@hookshot:yourdomain.com", // The bot mxid for the service. Currently, this is the sender_localpart, but may change in the future. "config": { // ... connection specific details, can be configured. } @@ -138,7 +138,7 @@ The body of the request is the configuration for the connection, which will be t "eventType": "uk.half-shot.matrix-hookshot.jira.project", // Corresponds to the state type in the connection "id": "opaque-unique-id", // An opaque ID used to refer to this connection. Should **NOT** be assumed to be stable. "service": "jira", // or github, webhook. A human-readable service name to make things look pretty - "botUserId": "@hookshot:yourdomain.com", // The bot mxid for the service. Currently this is the sender_localpart, but may change in the future. + "botUserId": "@hookshot:yourdomain.com", // The bot mxid for the service. Currently, this is the sender_localpart, but may change in the future. "config": { // ... connection specific details, can be configured. } diff --git a/src/provisioning/provisioner.ts b/src/provisioning/provisioner.ts index 02239665..16832db4 100644 --- a/src/provisioning/provisioner.ts +++ b/src/provisioning/provisioner.ts @@ -185,10 +185,10 @@ export class Provisioner { private getConnection(req: Request<{roomId: string, connectionId: string}>, res: Response) { const connection = this.connMan.getConnectionById(req.params.roomId, req.params.connectionId); if (!connection) { - throw new ApiError("Connection does not exist", ErrCode.NotFound); + throw new ApiError("Connection does not exist.", ErrCode.NotFound); } if (!connection.getProvisionerDetails) { - throw new ApiError("Connection type does not support updates", ErrCode.UnsupportedOperation); + throw new ApiError("Connection type does not support updates.", ErrCode.UnsupportedOperation); } return res.send(connection.getProvisionerDetails()); } @@ -197,15 +197,15 @@ export class Provisioner { // Need to figure out which connections are available try { if (!req.body || typeof req.body !== "object") { - throw new ApiError("A JSON body must be provided", ErrCode.BadValue); + throw new ApiError("A JSON body must be provided.", ErrCode.BadValue); } const connection = await this.connMan.provisionConnection(req.params.roomId, req.query.userId, req.params.type, req.body); if (!connection.getProvisionerDetails) { - throw new Error('Connection supported provisioning but not getProvisionerDetails'); + throw new Error('Connection supported provisioning but not getProvisionerDetails.'); } res.send(connection.getProvisionerDetails()); } catch (ex) { - log.warn(`Failed to create connection for ${req.params.roomId}`, ex); + log.warn(`Failed to create connection for ${req.params.roomId}.`, ex); return next(ex); } } @@ -214,10 +214,10 @@ export class Provisioner { try { const connection = this.connMan.getConnectionById(req.params.roomId, req.params.connectionId); if (!connection) { - return next(new ApiError("Connection does not exist", ErrCode.NotFound)); + return next(new ApiError("Connection does not exist.", ErrCode.NotFound)); } if (!connection.provisionerUpdateConfig || !connection.getProvisionerDetails) { - return next(new ApiError("Connection type does not support updates", ErrCode.UnsupportedOperation)); + return next(new ApiError("Connection type does not support updates.", ErrCode.UnsupportedOperation)); } await connection.provisionerUpdateConfig(req.query.userId, req.body); res.send(connection.getProvisionerDetails()); @@ -230,10 +230,10 @@ export class Provisioner { try { const connection = this.connMan.getConnectionById(req.params.roomId, req.params.connectionId); if (!connection) { - return next(new ApiError("Connection does not exist", ErrCode.NotFound)); + return next(new ApiError("Connection does not exist.", ErrCode.NotFound)); } if (!connection.onRemove) { - return next(new ApiError("Connection does not support removal", ErrCode.UnsupportedOperation)); + return next(new ApiError("Connection does not support removal.", ErrCode.UnsupportedOperation)); } await this.connMan.purgeConnection(req.params.roomId, req.params.connectionId); res.send({ok: true});