mirror of
https://github.com/matrix-org/matrix-hookshot.git
synced 2025-03-10 21:19:13 +00:00
More work in progress GitLab support
This commit is contained in:
parent
24cfd9e542
commit
4b3eca1913
@ -11,6 +11,7 @@ import "reflect-metadata";
|
||||
import markdown from "markdown-it";
|
||||
import { FormatUtil } from "./FormatUtil";
|
||||
import { botCommand, compileBotCommands, handleCommand, BotCommands } from "./BotCommands";
|
||||
import { GitLabClient } from "./Gitlab/Client";
|
||||
|
||||
const md = new markdown();
|
||||
const log = new LogWrapper('AdminRoom');
|
||||
@ -84,10 +85,9 @@ export class AdminRoom extends EventEmitter {
|
||||
return this.botIntent.underlyingClient.sendMessage(this.roomId, AdminRoom.helpMessage);
|
||||
}
|
||||
|
||||
|
||||
@botCommand("setpersonaltoken", "Set your personal access token for GitHub", ['accessToken'])
|
||||
// @ts-ignore - property is used
|
||||
private async setPersonalAccessToken(accessToken: string) {
|
||||
private async setGHPersonalAccessToken(accessToken: string) {
|
||||
let me;
|
||||
try {
|
||||
const octokit = new Octokit({
|
||||
@ -104,6 +104,22 @@ export class AdminRoom extends EventEmitter {
|
||||
await this.tokenStore.storeUserToken("github", this.userId, accessToken);
|
||||
}
|
||||
|
||||
@botCommand("gitlab personaltoken", "Set your personal access token for GitLab", ['instanceUrl', 'accessToken'])
|
||||
// @ts-ignore - property is used
|
||||
private async setGitLabPersonalAccessToken(instanceUrl: string, accessToken: string) {
|
||||
let me: GetUserResponse;
|
||||
try {
|
||||
const client = new GitLabClient(instanceUrl, accessToken);
|
||||
me = await client.user();
|
||||
} catch (ex) {
|
||||
log.error("Gitlab auth error:", ex);
|
||||
await this.sendNotice("Could not authenticate with GitLab. Is your token correct?");
|
||||
return;
|
||||
}
|
||||
await this.sendNotice(`Connected as ${me.username}. Token stored`);
|
||||
await this.tokenStore.storeUserToken("gitlab", this.userId, accessToken, instanceUrl);
|
||||
}
|
||||
|
||||
@botCommand("hastoken", "Check if you have a token stored for GitHub")
|
||||
// @ts-ignore - property is used
|
||||
private async hasPersonalToken() {
|
||||
@ -259,13 +275,14 @@ export class AdminRoom extends EventEmitter {
|
||||
if (error) {
|
||||
return this.sendNotice("Failed to handle command:" + error);
|
||||
}
|
||||
return this.botIntent.underlyingClient.sendEvent(this.roomId, "m.reaction", {
|
||||
"m.relates_to": {
|
||||
rel_type: "m.annotation",
|
||||
event_id: event_id,
|
||||
key: "✅",
|
||||
}
|
||||
});
|
||||
return null;
|
||||
// return this.botIntent.underlyingClient.sendEvent(this.roomId, "m.reaction", {
|
||||
// "m.relates_to": {
|
||||
// rel_type: "m.annotation",
|
||||
// event_id: event_id,
|
||||
// key: "✅",
|
||||
// }
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import markdown from "markdown-it";
|
||||
// @ts-ignore
|
||||
import argvSplit from "argv-split";
|
||||
import e from "express";
|
||||
|
||||
const md = new markdown();
|
||||
|
||||
@ -53,10 +52,9 @@ export function compileBotCommands(prototype: any): {helpMessage: any, botComman
|
||||
}
|
||||
|
||||
export async function handleCommand(userId: string, command: string, botCommands: BotCommands, obj: any): Promise<{error?: string, handled?: boolean}> {
|
||||
const cmdLower = command.toLowerCase();
|
||||
const parts = argvSplit(cmdLower);
|
||||
const parts = argvSplit(command);
|
||||
for (let i = parts.length; i > 0; i--) {
|
||||
const prefix = parts.slice(0, i).join(" ");
|
||||
const prefix = parts.slice(0, i).join(" ").toLowerCase();
|
||||
// We have a match!
|
||||
const command = botCommands[prefix];
|
||||
if (command) {
|
||||
|
135
src/Connections/GitlabRepo.ts
Normal file
135
src/Connections/GitlabRepo.ts
Normal file
@ -0,0 +1,135 @@
|
||||
import { IConnection } from "./IConnection";
|
||||
import { UserTokenStore } from "../UserTokenStore";
|
||||
import { Appservice } from "matrix-bot-sdk";
|
||||
import { BotCommands, handleCommand, botCommand, compileBotCommands } from "../BotCommands";
|
||||
import { MatrixEvent, MatrixMessageContent } from "../MatrixEvent";
|
||||
import markdown from "markdown-it";
|
||||
import LogWrapper from "../LogWrapper";
|
||||
|
||||
export interface GitLabRepoConnectionState {
|
||||
instance_url: string;
|
||||
org: string;
|
||||
repo: string;
|
||||
state: string;
|
||||
}
|
||||
|
||||
const log = new LogWrapper("GitHubRepoConnection");
|
||||
const md = new markdown();
|
||||
|
||||
/**
|
||||
* Handles rooms connected to a github repo.
|
||||
*/
|
||||
export class GitLabRepoConnection implements IConnection {
|
||||
static readonly CanonicalEventType = "uk.half-shot.matrix-github.gitlab.repository";
|
||||
|
||||
static readonly EventTypes = [
|
||||
GitLabRepoConnection.CanonicalEventType, // Legacy event, with an awful name.
|
||||
];
|
||||
|
||||
static helpMessage: any;
|
||||
static botCommands: BotCommands;
|
||||
|
||||
constructor(public readonly roomId: string,
|
||||
private readonly as: Appservice,
|
||||
private readonly state: GitLabRepoConnectionState,
|
||||
private readonly tokenStore: UserTokenStore) {
|
||||
|
||||
}
|
||||
|
||||
public get org() {
|
||||
return this.state.org;
|
||||
}
|
||||
|
||||
public get repo() {
|
||||
return this.state.repo;
|
||||
}
|
||||
|
||||
public isInterestedInStateEvent(eventType: string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public async onMessageEvent(ev: MatrixEvent<MatrixMessageContent>) {
|
||||
const { error, handled } = await handleCommand(ev.sender, ev.content.body, GitLabRepoConnection.botCommands, this);
|
||||
if (!handled) {
|
||||
// Not for us.
|
||||
return;
|
||||
}
|
||||
if (error) {
|
||||
log.error(error);
|
||||
await this.as.botIntent.sendEvent(this.roomId,{
|
||||
msgtype: "m.notice",
|
||||
body: "Failed to handle command",
|
||||
});
|
||||
return;
|
||||
}
|
||||
await this.as.botClient.sendEvent(this.roomId, "m.reaction", {
|
||||
"m.relates_to": {
|
||||
rel_type: "m.annotation",
|
||||
event_id: ev.event_id,
|
||||
key: "✅",
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@botCommand("gl create", "Create an issue for this repo", ["title"], ["description", "labels"], true)
|
||||
// @ts-ignore
|
||||
private async onCreateIssue(userId: string, title: string, description?: string, labels?: string) {
|
||||
const client = await this.tokenStore.getGitLabForUser(userId, this.state.instance_url);
|
||||
if (!client) {
|
||||
await this.as.botIntent.sendText(this.roomId, "You must login to create an issue", "m.notice");
|
||||
throw Error('Not logged in');
|
||||
}
|
||||
const res = await client.issues.create({
|
||||
id: encodeURIComponent(`${this.state.org}/${this.state.repo}`),
|
||||
title,
|
||||
description,
|
||||
labels: labels ? labels.split(",") : undefined,
|
||||
});
|
||||
|
||||
const content = `Created issue #${res.iid}: [${res.web_url}](${res.web_url})`;
|
||||
return this.as.botIntent.sendEvent(this.roomId,{
|
||||
msgtype: "m.notice",
|
||||
body: content,
|
||||
formatted_body: md.render(content),
|
||||
format: "org.matrix.custom.html"
|
||||
});
|
||||
}
|
||||
|
||||
@botCommand("gl close", "Close an issue", ["number"], ["comment"], true)
|
||||
// @ts-ignore
|
||||
private async onClose(userId: string, number: string, comment?: string) {
|
||||
const client = await this.tokenStore.getGitLabForUser(userId, this.state.instance_url);
|
||||
if (!client) {
|
||||
await this.as.botIntent.sendText(this.roomId, "You must login to create an issue", "m.notice");
|
||||
throw Error('Not logged in');
|
||||
}
|
||||
|
||||
await client.issues.edit({
|
||||
id: encodeURIComponent(`${this.state.org}/${this.state.repo}`),
|
||||
issue_iid: number,
|
||||
state_event: "close",
|
||||
});
|
||||
}
|
||||
|
||||
// public async onIssueCreated(event: IGitHubWebhookEvent) {
|
||||
|
||||
// }
|
||||
|
||||
// public async onIssueStateChange(event: IGitHubWebhookEvent) {
|
||||
|
||||
// }
|
||||
|
||||
public async onEvent(evt: MatrixEvent<unknown>) {
|
||||
|
||||
}
|
||||
|
||||
public async onStateUpdate() { }
|
||||
|
||||
public toString() {
|
||||
return `GitHubRepo`;
|
||||
}
|
||||
}
|
||||
|
||||
const res = compileBotCommands(GitLabRepoConnection.prototype);
|
||||
GitLabRepoConnection.helpMessage = res.helpMessage;
|
||||
GitLabRepoConnection.botCommands = res.botCommands;
|
@ -22,6 +22,8 @@ import { IConnection } from "./Connections/IConnection";
|
||||
import { GitHubRepoConnection } from "./Connections/GithubRepo";
|
||||
import { GitHubIssueConnection } from "./Connections/GithubIssue";
|
||||
import { GitHubProjectConnection } from "./Connections/GithubProject";
|
||||
import { GitLabRepoConnection } from "./Connections/GitlabRepo";
|
||||
import { IGitLabWebhookMREvent } from "./Gitlab/WebhookTypes";
|
||||
|
||||
const log = new LogWrapper("GithubBridge");
|
||||
|
||||
@ -52,6 +54,9 @@ export class GithubBridge {
|
||||
if (GitHubIssueConnection.EventTypes.includes(state.type)) {
|
||||
return new GitHubIssueConnection(roomId, this.as, state.content, state.state_key || "", this.tokenStore, this.commentProcessor, this.messageClient, this.octokit);
|
||||
}
|
||||
if (GitLabRepoConnection.EventTypes.includes(state.type)) {
|
||||
return new GitLabRepoConnection(roomId, this.as, state.content, this.tokenStore);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -65,6 +70,10 @@ export class GithubBridge {
|
||||
(c instanceof GitHubRepoConnection && c.org === org && c.repo === repo));
|
||||
}
|
||||
|
||||
private getConnectionsForGitLabIssue(org: string, repo: string, issueNumber: number) {
|
||||
return this.connections.filter((c) => (c instanceof GitLabRepoConnection && c.org === org && c.repo === repo));
|
||||
}
|
||||
|
||||
public stop() {
|
||||
this.as.stop();
|
||||
this.queue.stop();
|
||||
@ -151,6 +160,7 @@ export class GithubBridge {
|
||||
this.queue.subscribe("issue.*");
|
||||
this.queue.subscribe("response.matrix.message");
|
||||
this.queue.subscribe("notifications.user.events");
|
||||
this.queue.subscribe("merge_request.*")
|
||||
|
||||
this.queue.on<IGitHubWebhookEvent>("comment.created", async (msg) => {
|
||||
const connections = this.getConnectionsForGithubIssue(msg.data.repository!.owner.login, msg.data.repository!.name, msg.data.issue!.number);
|
||||
@ -212,6 +222,18 @@ export class GithubBridge {
|
||||
})
|
||||
});
|
||||
|
||||
// this.queue.on<IGitLabWebhookMREvent>("merge_request.open", async (msg) => {
|
||||
// const connections = this.getConnectionsForGitLabIssue(msg.data.project.namespace, msg.data.repository!.name, msg.data.issue!.number);
|
||||
// connections.map(async (c) => {
|
||||
// try {
|
||||
// if (c.onIssueCreated)
|
||||
// await c.onIssueStateChange(msg.data);
|
||||
// } catch (ex) {
|
||||
// log.warn(`Connection ${c.toString()} failed to handle comment.created:`, ex);
|
||||
// }
|
||||
// })
|
||||
// });
|
||||
|
||||
this.queue.on<UserNotificationsEvent>("notifications.user.events", async (msg) => {
|
||||
const adminRoom = this.adminRooms.get(msg.data.roomId);
|
||||
if (!adminRoom) {
|
||||
@ -281,11 +303,9 @@ export class GithubBridge {
|
||||
const accountData = await this.as.botIntent.underlyingClient.getRoomAccountData(
|
||||
BRIDGE_ROOM_TYPE, roomId,
|
||||
);
|
||||
if (accountData.type === "admin") {
|
||||
const adminRoom = this.setupAdminRoom(roomId, accountData);
|
||||
// Call this on startup to set the state
|
||||
await this.onAdminRoomSettingsChanged(adminRoom, accountData);
|
||||
}
|
||||
const adminRoom = this.setupAdminRoom(roomId, accountData);
|
||||
// Call this on startup to set the state
|
||||
await this.onAdminRoomSettingsChanged(adminRoom, accountData);
|
||||
} catch (ex) {
|
||||
log.warn(`Room ${roomId} has no connections and is not an admin room`);
|
||||
}
|
||||
@ -310,7 +330,10 @@ export class GithubBridge {
|
||||
}
|
||||
await retry(() => this.as.botIntent.joinRoom(roomId), 5);
|
||||
if (event.content.is_direct) {
|
||||
this.setupAdminRoom(roomId, {admin_user: event.sender, notifications: { enabled: false, participating: false}});
|
||||
const room = this.setupAdminRoom(roomId, {admin_user: event.sender, notifications: { enabled: false, participating: false}});
|
||||
await this.as.botIntent.underlyingClient.setRoomAccountData(
|
||||
BRIDGE_ROOM_TYPE, roomId, room.data,
|
||||
);
|
||||
}
|
||||
// This is a group room, don't add the admin settings and just sit in the room.
|
||||
}
|
||||
@ -360,7 +383,7 @@ export class GithubBridge {
|
||||
|
||||
const command = event.content.body;
|
||||
if (command) {
|
||||
await this.adminRooms.get(roomId)!.handleCommand(command);
|
||||
await this.adminRooms.get(roomId)!.handleCommand(event.event_id, command);
|
||||
}
|
||||
}
|
||||
|
||||
@ -445,6 +468,7 @@ export class GithubBridge {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
throw Error('No regex matching query pattern');
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import qs from "querystring";
|
||||
import { Server } from "http";
|
||||
import axios from "axios";
|
||||
import { UserNotificationWatcher } from "./UserNotificationWatcher";
|
||||
import { IGitLabWebhookEvent } from "./Gitlab/WebhookTypes";
|
||||
|
||||
const log = new LogWrapper("GithubWebhooks");
|
||||
|
||||
@ -91,27 +92,41 @@ export class GithubWebhooks extends EventEmitter {
|
||||
}
|
||||
|
||||
private onGitHubPayload(body: IGitHubWebhookEvent) {
|
||||
let eventName;
|
||||
let from;
|
||||
if (body.sender) {
|
||||
from = body.sender.login;
|
||||
if (body.action === "created" && body.comment) {
|
||||
return "comment.created";
|
||||
} else if (body.action === "edited" && body.comment) {
|
||||
return "comment.edited";
|
||||
} else if (body.action === "opened" && body.issue) {
|
||||
return "issue.opened";
|
||||
} else if (body.action === "edited" && body.issue) {
|
||||
return "issue.edited";
|
||||
} else if (body.action === "closed" && body.issue) {
|
||||
return "issue.closed";
|
||||
} else if (body.action === "reopened" && body.issue) {
|
||||
return "issue.reopened";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private onGitLabPayload(body: IGitLabWebhookEvent) {
|
||||
if (body.event_type === "merge_request") {
|
||||
return `merge_request.${body.object_attributes.action}`;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private onPayload(req: Request, res: Response) {
|
||||
log.debug(`New webhook: ${req.url}`);
|
||||
try {
|
||||
if (body.action === "created" && body.comment) {
|
||||
eventName = "comment.created";
|
||||
} else if (body.action === "edited" && body.comment) {
|
||||
eventName = "comment.edited";
|
||||
} else if (body.action === "opened" && body.issue) {
|
||||
eventName = "issue.opened";
|
||||
} else if (body.action === "edited" && body.issue) {
|
||||
eventName = "issue.edited";
|
||||
} else if (body.action === "closed" && body.issue) {
|
||||
eventName = "issue.closed";
|
||||
} else if (body.action === "reopened" && body.issue) {
|
||||
eventName = "issue.reopened";
|
||||
let eventName: string|null = null;
|
||||
let body = req.body;
|
||||
res.sendStatus(200);
|
||||
if (req.headers['x-hub-signature']) {
|
||||
eventName = this.onGitHubPayload(body);
|
||||
} else if (req.headers['x-gitlab-token']) {
|
||||
eventName = this.onGitLabPayload(body);
|
||||
}
|
||||
if (eventName) {
|
||||
log.info(`Got event ${eventName} ${from ? "from " + from : ""}`);
|
||||
this.queue.push({
|
||||
eventName,
|
||||
sender: "GithubWebhooks",
|
||||
@ -119,21 +134,12 @@ export class GithubWebhooks extends EventEmitter {
|
||||
}).catch((err) => {
|
||||
log.info(`Failed to emit payload: ${err}`);
|
||||
});
|
||||
} else {
|
||||
log.debug("Unknown event:", req.body);
|
||||
}
|
||||
} catch (ex) {
|
||||
log.error("Failed to emit");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private onPayload(req: Request, res: Response) {
|
||||
log.debug(`New webhook: ${req.url}`);
|
||||
const body = req.body as IGitHubWebhookEvent;
|
||||
log.debug("Got", body);
|
||||
res.sendStatus(200);
|
||||
if (req.headers['x-hub-signature']) {
|
||||
return this.onGitHubPayload(body);
|
||||
}
|
||||
}
|
||||
|
||||
public async onGetOauth(req: Request, res: Response) {
|
||||
|
40
src/Gitlab/Client.ts
Normal file
40
src/Gitlab/Client.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import axios from "axios";
|
||||
|
||||
export class GitLabClient {
|
||||
constructor(private instanceUrl: string, private token: string) {
|
||||
|
||||
}
|
||||
|
||||
get defaultConfig() {
|
||||
return {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
UserAgent: "matrix-github v0.0.1",
|
||||
},
|
||||
baseURL: this.instanceUrl
|
||||
};
|
||||
}
|
||||
|
||||
async version() {
|
||||
return (await axios.get(`${this.instanceUrl}/api/v4/versions`, this.defaultConfig)).data;
|
||||
}
|
||||
|
||||
async user(): Promise<GetUserResponse> {
|
||||
return (await axios.get(`${this.instanceUrl}/api/v4/user`, this.defaultConfig)).data;
|
||||
}
|
||||
|
||||
private async createIssue(opts: CreateIssueOpts): Promise<CreateIssueResponse> {
|
||||
return (await axios.post(`${this.instanceUrl}/api/v4/projects/${opts.id}/issues`, opts, this.defaultConfig)).data;
|
||||
}
|
||||
|
||||
private async editIssue(opts: EditIssueOpts): Promise<CreateIssueResponse> {
|
||||
return (await axios.put(`${this.instanceUrl}/api/v4/projects/${opts.id}/issues/${opts.issue_iid}`, opts, this.defaultConfig)).data;
|
||||
}
|
||||
|
||||
get issues() {
|
||||
return {
|
||||
create: this.createIssue.bind(this),
|
||||
edit: this.editIssue.bind(this),
|
||||
}
|
||||
}
|
||||
}
|
67
src/Gitlab/Types.ts
Normal file
67
src/Gitlab/Types.ts
Normal file
@ -0,0 +1,67 @@
|
||||
interface GetUserResponse {
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
name: string;
|
||||
state: string;
|
||||
avatar_url: string;
|
||||
web_url: string;
|
||||
created_at: string;
|
||||
bio: string;
|
||||
bio_html: string;
|
||||
location: null|string;
|
||||
public_email: string;
|
||||
skype: string;
|
||||
linkedin: string;
|
||||
twitter: string;
|
||||
website_url: string;
|
||||
organization: string;
|
||||
last_sign_in_at: string;
|
||||
confirmed_at: string;
|
||||
theme_id: number;
|
||||
last_activity_on: string;
|
||||
color_scheme_id: number;
|
||||
projects_limit: number;
|
||||
current_sign_in_at: string;
|
||||
identities: [
|
||||
{provider: string, extern_uid: string},
|
||||
];
|
||||
can_create_group: boolean;
|
||||
can_create_project: boolean;
|
||||
two_factor_enabled: boolean;
|
||||
external: boolean;
|
||||
private_profile: boolean;
|
||||
}
|
||||
|
||||
// https://docs.gitlab.com/ee/api/issues.html#new-issue
|
||||
interface CreateIssueOpts {
|
||||
id: string|number;
|
||||
title: string;
|
||||
description?: string;
|
||||
confidential?: boolean;
|
||||
labels?: string[];
|
||||
}
|
||||
|
||||
interface CreateIssueResponse {
|
||||
state: string;
|
||||
id: string;
|
||||
iid: string;
|
||||
web_url: string;
|
||||
}
|
||||
|
||||
// https://docs.gitlab.com/ee/api/issues.html#new-issue
|
||||
interface EditIssueOpts {
|
||||
id: string|number;
|
||||
issue_iid: string|number;
|
||||
title?: string;
|
||||
description?: string;
|
||||
confidential?: boolean;
|
||||
labels?: string[];
|
||||
state_event?: string;
|
||||
}
|
||||
|
||||
interface CreateIssueResponse {
|
||||
state: string;
|
||||
id: string;
|
||||
web_url: string;
|
||||
}
|
20
src/Gitlab/WebhookTypes.ts
Normal file
20
src/Gitlab/WebhookTypes.ts
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
export interface IGitLabWebhookEvent {
|
||||
object_kind: string;
|
||||
event_type: string;
|
||||
object_attributes: {
|
||||
action: string;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IGitLabWebhookMREvent {
|
||||
object_kind: "merge_request";
|
||||
user: {
|
||||
name: string;
|
||||
username: string;
|
||||
avatar_url: string;
|
||||
};
|
||||
project: {
|
||||
namespace: string;
|
||||
};
|
||||
}
|
@ -4,6 +4,7 @@ import { publicEncrypt, privateDecrypt } from "crypto";
|
||||
import LogWrapper from "./LogWrapper";
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import { createTokenAuth } from "@octokit/auth-token";
|
||||
import { GitLabClient } from "./Gitlab/Client";
|
||||
|
||||
const ACCOUNT_DATA_TYPE = "uk.half-shot.matrix-github.password-store:";
|
||||
const ACCOUNT_DATA_GITLAB_TYPE = "uk.half-shot.matrix-github.gitlab.password-store:";
|
||||
@ -21,16 +22,20 @@ export class UserTokenStore {
|
||||
this.key = await fs.readFile(this.keyPath);
|
||||
}
|
||||
|
||||
public async storeUserToken(type: "github"|"gitlab", userId: string, token: string): Promise<void> {
|
||||
const prefix = type === "github" ? ACCOUNT_DATA_TYPE : ACCOUNT_DATA_GITLAB_TYPE;
|
||||
public async storeUserToken(type: "github"|"gitlab", userId: string, token: string, instanceUrl?: string): Promise<void> {
|
||||
let prefix = type === "github" ? ACCOUNT_DATA_TYPE : ACCOUNT_DATA_GITLAB_TYPE;
|
||||
if (instanceUrl) {
|
||||
prefix += instanceUrl;
|
||||
}
|
||||
await this.intent.underlyingClient.setAccountData(`${prefix}${userId}`, {
|
||||
encrypted: publicEncrypt(this.key, Buffer.from(token)).toString("base64"),
|
||||
instance_url: instanceUrl,
|
||||
});
|
||||
this.userTokens.set(userId, token);
|
||||
log.info(`Stored new ${type} token for ${userId}`);
|
||||
}
|
||||
|
||||
public async getUserToken(type: "github"|"gitlab", userId: string): Promise<string|null> {
|
||||
public async getUserToken(type: "github"|"gitlab", userId: string, instanceUrl?: string): Promise<string|null> {
|
||||
if (this.userTokens.has(userId)) {
|
||||
return this.userTokens.get(userId)!;
|
||||
}
|
||||
@ -39,7 +44,7 @@ export class UserTokenStore {
|
||||
if (type === "github") {
|
||||
obj = await this.intent.underlyingClient.getAccountData(`${ACCOUNT_DATA_TYPE}${userId}`);
|
||||
} else if (type === "gitlab") {
|
||||
obj = await this.intent.underlyingClient.getAccountData(`${ACCOUNT_DATA_GITLAB_TYPE}${userId}`);
|
||||
obj = await this.intent.underlyingClient.getAccountData(`${ACCOUNT_DATA_GITLAB_TYPE}${instanceUrl}${userId}`);
|
||||
}
|
||||
const encryptedTextB64 = obj.encrypted;
|
||||
const encryptedText = Buffer.from(encryptedTextB64, "base64");
|
||||
@ -65,4 +70,13 @@ export class UserTokenStore {
|
||||
userAgent: "matrix-github v0.0.1",
|
||||
});
|
||||
}
|
||||
|
||||
public async getGitLabForUser(userId: string, instanceUrl: string) {
|
||||
// TODO: Move this somewhere else.
|
||||
const senderToken = await this.getUserToken("gitlab", userId, instanceUrl);
|
||||
if (!senderToken) {
|
||||
return null;
|
||||
}
|
||||
return new GitLabClient(instanceUrl, senderToken);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user