mirror of
https://github.com/matrix-org/matrix-hookshot.git
synced 2025-03-10 21:19:13 +00:00
Add ability to request all supported types
This commit is contained in:
parent
3b732145e5
commit
87e5020469
@ -13,7 +13,7 @@ import { GitLabClient } from "./Gitlab/Client";
|
||||
import { JiraProject } from "./Jira/Types";
|
||||
import LogWrapper from "./LogWrapper";
|
||||
import { MessageSenderClient } from "./MatrixSender";
|
||||
import { ApiError } from "./provisioning/api";
|
||||
import { ApiError, GetConnectionTypeResponseItem } from "./provisioning/api";
|
||||
import { UserTokenStore } from "./UserTokenStore";
|
||||
|
||||
const log = new LogWrapper("ConnectionManager");
|
||||
@ -289,4 +289,12 @@ export class ConnectionManager {
|
||||
const connectionIndex = this.connections.indexOf(connection);
|
||||
this.connections.splice(connectionIndex, 1);
|
||||
}
|
||||
|
||||
public getConnectionTypesProvisioningDetails(): {[eventType: string]: GetConnectionTypeResponseItem} {
|
||||
const results: {[eventType: string]: GetConnectionTypeResponseItem} = {};
|
||||
// TODO: Do this dynamically.
|
||||
const jiraProject = JiraProjectConnection.getProvisionerDetails(this.as.botUserId);
|
||||
results[jiraProject.eventType] = jiraProject;
|
||||
return results;
|
||||
}
|
||||
}
|
@ -13,8 +13,7 @@ import { MatrixMessageContent } from "../MatrixEvent";
|
||||
import { CommandConnection } from "./CommandConnection";
|
||||
import { UserTokenStore } from "../UserTokenStore";
|
||||
import { CommandError, NotLoggedInError } from "../errors";
|
||||
import { ApiError } from "../provisioning/api";
|
||||
import { stat } from "fs";
|
||||
import { ApiError, ErrCode } from "../provisioning/api";
|
||||
|
||||
type JiraAllowedEventsNames = "issue.created";
|
||||
const JiraAllowedEvents: JiraAllowedEventsNames[] = ["issue.created"];
|
||||
@ -29,18 +28,18 @@ export interface JiraProjectConnectionState {
|
||||
function validateJiraConnectionState(state: JiraProjectConnectionState) {
|
||||
const {url, commandPrefix, events} = state as JiraProjectConnectionState;
|
||||
if (url === undefined) {
|
||||
throw new ApiError("Expected a 'url' property", 400);
|
||||
throw new ApiError("Expected a 'url' property", ErrCode.BadValue);
|
||||
}
|
||||
if (commandPrefix) {
|
||||
if (typeof commandPrefix !== "string") {
|
||||
throw new ApiError("Expected 'commandPrefix' to be a string", 400);
|
||||
throw new ApiError("Expected 'commandPrefix' to be a string", ErrCode.BadValue);
|
||||
}
|
||||
if (commandPrefix.length < 2 || commandPrefix.length > 24) {
|
||||
throw new ApiError("Expected 'commandPrefix' to be between 2-24 characters", 400);
|
||||
throw new ApiError("Expected 'commandPrefix' to be between 2-24 characters", ErrCode.BadValue);
|
||||
}
|
||||
}
|
||||
if (events?.find((ev) => !JiraAllowedEvents.includes(ev))?.length) {
|
||||
throw new ApiError(`'events' can only contain ${JiraAllowedEvents.join(", ")}`, 400);
|
||||
throw new ApiError(`'events' can only contain ${JiraAllowedEvents.join(", ")}`, ErrCode.BadValue);
|
||||
}
|
||||
return {url, commandPrefix, events};
|
||||
}
|
||||
@ -160,6 +159,16 @@ export class JiraProjectConnection extends CommandConnection implements IConnect
|
||||
return `${this.roomId}/${JiraProjectConnection.CanonicalEventType}/${this.stateKey}`;
|
||||
}
|
||||
|
||||
public static getProvisionerDetails(botUserId: string) {
|
||||
return {
|
||||
service: "jira",
|
||||
eventType: JiraProjectConnection.CanonicalEventType,
|
||||
type: "JiraProject",
|
||||
// TODO: Add ability to configure the bot per connnection type.
|
||||
botUserId: botUserId,
|
||||
}
|
||||
}
|
||||
|
||||
public getProvisionerDetails() {
|
||||
return {
|
||||
service: "jira",
|
||||
|
@ -33,6 +33,22 @@ HTTP 200
|
||||
|
||||
Any other response should be considered a failed request (e.g. 404, 502 etc).
|
||||
|
||||
## GET /v1/connectiontypes
|
||||
|
||||
Request the connection types enabled for this bridge.
|
||||
|
||||
### Response
|
||||
|
||||
```json5
|
||||
{
|
||||
"uk.half-shot.matrix-hookshot.jira.project": {
|
||||
"type": "uk.half-shot.matrix-hookshot.jira.project", // Corresponds to the state type in 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.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## GET /v1/{roomId}/connections
|
||||
|
||||
Request the connections for a given room. The `{roomId}` parameter is the target Matrix room.
|
||||
@ -44,12 +60,14 @@ Request the connections for a given room. The `{roomId}` parameter is the target
|
||||
"type": "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
|
||||
"details": {
|
||||
"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.
|
||||
}
|
||||
}]
|
||||
```
|
||||
|
||||
|
||||
## GET /v1/{roomId}/connections/{id}
|
||||
|
||||
Request details of a single connection. The `{roomId}` parameter is the target Matrix room.
|
||||
@ -61,7 +79,8 @@ Request details of a single connection. The `{roomId}` parameter is the target M
|
||||
"type": "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
|
||||
"details": {
|
||||
"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.
|
||||
}
|
||||
}
|
||||
@ -86,7 +105,8 @@ The body of the request is the configuration for the connection, which will be t
|
||||
"type": "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
|
||||
"details": {
|
||||
"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.
|
||||
}
|
||||
}
|
||||
@ -111,7 +131,8 @@ The body of the request is the configuration for the connection, which will be t
|
||||
"type": "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
|
||||
"details": {
|
||||
"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.
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,17 @@
|
||||
|
||||
import { Response } from "express";
|
||||
export interface GetConnectionsResponseItem {
|
||||
|
||||
export interface GetConnectionTypeResponseItem {
|
||||
type: string;
|
||||
service: string;
|
||||
botUserId: string;
|
||||
}
|
||||
export interface GetConnectionsResponseItem extends GetConnectionTypeResponseItem {
|
||||
id: string;
|
||||
config: Record<string, unknown>;
|
||||
}
|
||||
|
||||
|
||||
export enum ErrCode {
|
||||
// Errors are prefixed with HS_
|
||||
/**
|
||||
|
@ -3,7 +3,7 @@ import { Application, default as express, NextFunction, Request, Response, Route
|
||||
import { ConnectionManager } from "../ConnectionManager";
|
||||
import LogWrapper from "../LogWrapper";
|
||||
import { Server } from "http";
|
||||
import { ApiError, ErrCode, GetConnectionsResponseItem } from "./api";
|
||||
import { ApiError, ErrCode, GetConnectionsResponseItem, GetConnectionTypeResponseItem } from "./api";
|
||||
import { Intent, MembershipEventContent, PowerLevelsEventContent } from "matrix-bot-sdk";
|
||||
|
||||
const log = new LogWrapper("Provisioner");
|
||||
@ -30,11 +30,15 @@ export class Provisioner {
|
||||
this.expressApp = express();
|
||||
this.expressApp.get("/v1/health", this.getHealth);
|
||||
this.expressApp.use(this.checkAuth.bind(this));
|
||||
// Room Routes
|
||||
this.expressApp.get(
|
||||
"/v1/connectiontypes",
|
||||
this.getConnectionTypes.bind(this),
|
||||
);
|
||||
this.expressApp.use(this.checkUserId.bind(this));
|
||||
additionalRoutes.forEach(route => {
|
||||
this.expressApp.use(route.route, route.router);
|
||||
});
|
||||
// Room Routes
|
||||
this.expressApp.get<{roomId: string}, unknown, unknown, {userId: string}>(
|
||||
"/v1/:roomId/connections",
|
||||
this.checkRoomId.bind(this),
|
||||
@ -153,31 +157,25 @@ export class Provisioner {
|
||||
return res.send({})
|
||||
}
|
||||
|
||||
private async getConnections(req: Request<{roomId: string}>, res: Response<GetConnectionsResponseItem[]>, next: NextFunction) {
|
||||
try {
|
||||
const connections = await this.connMan.getAllConnectionsForRoom(req.params.roomId);
|
||||
const details = connections.map(c => c.getProvisionerDetails?.()).filter(c => !!c) as GetConnectionsResponseItem[];
|
||||
return res.send(details);
|
||||
} catch (ex) {
|
||||
log.warn(`Failed to fetch connections for ${req.params.roomId}`, ex);
|
||||
return next(new ApiError(`An internal issue occured while trying to fetch connections`));
|
||||
}
|
||||
private getConnectionTypes(_req: Request, res: Response<Record<string, GetConnectionTypeResponseItem>>) {
|
||||
return res.send(this.connMan.getConnectionTypesProvisioningDetails());
|
||||
}
|
||||
|
||||
private async getConnection(req: Request<{roomId: string, connectionId: string}>, res: Response<GetConnectionsResponseItem>, next: NextFunction) {
|
||||
try {
|
||||
const connection = await this.connMan.getConnectionById(req.params.roomId, req.params.connectionId);
|
||||
if (!connection) {
|
||||
return next(new ApiError("Connection does not exist", ErrCode.NotFound));
|
||||
}
|
||||
if (!connection.getProvisionerDetails) {
|
||||
return next(new ApiError("Connection type does not support updates", ErrCode.UnsupportedOperation));
|
||||
}
|
||||
return res.send(connection.getProvisionerDetails());
|
||||
} catch (ex) {
|
||||
log.warn(`Failed to fetch connections for ${req.params.roomId}`, ex);
|
||||
return next(new ApiError(`An internal issue occured while trying to fetch connections`));
|
||||
private getConnections(req: Request<{roomId: string}>, res: Response<GetConnectionsResponseItem[]>) {
|
||||
const connections = this.connMan.getAllConnectionsForRoom(req.params.roomId);
|
||||
const details = connections.map(c => c.getProvisionerDetails?.()).filter(c => !!c) as GetConnectionsResponseItem[];
|
||||
return res.send(details);
|
||||
}
|
||||
|
||||
private getConnection(req: Request<{roomId: string, connectionId: string}>, res: Response<GetConnectionsResponseItem>) {
|
||||
const connection = this.connMan.getConnectionById(req.params.roomId, req.params.connectionId);
|
||||
if (!connection) {
|
||||
throw new ApiError("Connection does not exist", ErrCode.NotFound);
|
||||
}
|
||||
if (!connection.getProvisionerDetails) {
|
||||
throw new ApiError("Connection type does not support updates", ErrCode.UnsupportedOperation);
|
||||
}
|
||||
return res.send(connection.getProvisionerDetails());
|
||||
}
|
||||
|
||||
private async putConnection(req: Request<{roomId: string, type: string}, unknown, Record<string, unknown>, {userId: string}>, res: Response, next: NextFunction) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user