mirror of
https://github.com/matrix-org/matrix-hookshot.git
synced 2025-03-10 13:17:08 +00:00
Fix GitHub and GitLab ghost user intent creation (#303)
* Fix GitHub and GitLab ghost user intent creation, and add config * changelog
This commit is contained in:
parent
e1b5f989b9
commit
27fc699e0e
1
changelog.d/303.bugfix
Normal file
1
changelog.d/303.bugfix
Normal file
@ -0,0 +1 @@
|
||||
Fix GitHub / GitLab issue rooms breaking due to being unable to generate ghost users.
|
@ -32,6 +32,10 @@ github:
|
||||
showIssueRoomLink: false
|
||||
hotlinkIssues:
|
||||
prefix: "#"
|
||||
userIdPrefix:
|
||||
# (Optional) Prefix used when creating ghost users for GitHub accounts.
|
||||
#
|
||||
_github_
|
||||
gitlab:
|
||||
# (Optional) Configure this to enable GitLab support
|
||||
#
|
||||
@ -40,6 +44,10 @@ gitlab:
|
||||
url: https://gitlab.com
|
||||
webhook:
|
||||
secret: secrettoken
|
||||
userIdPrefix:
|
||||
# (Optional) Prefix used when creating ghost users for GitLab accounts.
|
||||
#
|
||||
_gitlab_
|
||||
figma:
|
||||
# (Optional) Configure this to enable Figma support
|
||||
#
|
||||
|
@ -417,7 +417,7 @@ export class Bridge {
|
||||
);
|
||||
|
||||
this.queue.on<GitHubWebhookTypes.DiscussionCreatedEvent>("github.discussion.created", async ({data}) => {
|
||||
if (!this.github) {
|
||||
if (!this.github || !this.config.github) {
|
||||
return;
|
||||
}
|
||||
const spaces = connManager.getConnectionsForGithubRepoDiscussion(data.repository.owner.login, data.repository.name);
|
||||
@ -439,6 +439,7 @@ export class Bridge {
|
||||
this.tokenStore,
|
||||
this.commentProcessor,
|
||||
this.messageClient,
|
||||
this.config.github,
|
||||
);
|
||||
connManager.push(discussionConnection);
|
||||
} catch (ex) {
|
||||
@ -1093,6 +1094,9 @@ export class Bridge {
|
||||
}
|
||||
});
|
||||
adminRoom.on("open.gitlab-issue", async (issueInfo: GetIssueOpts, res: GetIssueResponse, instanceName: string, instance: GitLabInstance) => {
|
||||
if (!this.config.gitlab) {
|
||||
return;
|
||||
}
|
||||
const [ connection ] = this.connectionManager?.getConnectionsForGitLabIssue(instance, issueInfo.projects, issueInfo.issue) || [];
|
||||
if (connection) {
|
||||
return this.as.botClient.inviteUser(adminRoom.userId, connection.roomId);
|
||||
@ -1105,7 +1109,8 @@ export class Bridge {
|
||||
this.as,
|
||||
this.tokenStore,
|
||||
this.commentProcessor,
|
||||
this.messageClient
|
||||
this.messageClient,
|
||||
this.config.gitlab,
|
||||
);
|
||||
this.connectionManager?.push(newConnection);
|
||||
return this.as.botClient.inviteUser(adminRoom.userId, newConnection.roomId);
|
||||
|
@ -45,20 +45,21 @@ interface BridgeConfigGitHubYAML {
|
||||
redirect_uri: string;
|
||||
};
|
||||
defaultOptions?: GitHubRepoConnectionOptions;
|
||||
userIdPrefix?: string;
|
||||
}
|
||||
|
||||
export class BridgeConfigGitHub {
|
||||
@configKey("Authentication for the GitHub App.", false)
|
||||
auth: {
|
||||
readonly auth: {
|
||||
id: number|string;
|
||||
privateKeyFile: string;
|
||||
};
|
||||
@configKey("Webhook settings for the GitHub app.", false)
|
||||
webhook: {
|
||||
readonly webhook: {
|
||||
secret: string;
|
||||
};
|
||||
@configKey("Settings for allowing users to sign in via OAuth.", true)
|
||||
oauth?: {
|
||||
readonly oauth?: {
|
||||
// eslint-disable-next-line camelcase
|
||||
client_id: string;
|
||||
// eslint-disable-next-line camelcase
|
||||
@ -67,13 +68,17 @@ export class BridgeConfigGitHub {
|
||||
redirect_uri: string;
|
||||
};
|
||||
@configKey("Default options for GitHub connections.", true)
|
||||
defaultOptions?: GitHubRepoConnectionOptions;
|
||||
readonly defaultOptions?: GitHubRepoConnectionOptions;
|
||||
|
||||
@configKey("Prefix used when creating ghost users for GitHub accounts.", true)
|
||||
readonly userIdPrefix: string;
|
||||
|
||||
constructor(yaml: BridgeConfigGitHubYAML) {
|
||||
this.auth = yaml.auth;
|
||||
this.webhook = yaml.webhook;
|
||||
this.oauth = yaml.oauth;
|
||||
this.defaultOptions = yaml.defaultOptions;
|
||||
this.userIdPrefix = yaml.userIdPrefix || "_github_";
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,11 +160,28 @@ export interface GitLabInstance {
|
||||
// };
|
||||
}
|
||||
|
||||
interface BridgeConfigGitLab {
|
||||
export interface BridgeConfigGitLabYAML {
|
||||
webhook: {
|
||||
secret: string;
|
||||
},
|
||||
instances: {[name: string]: GitLabInstance};
|
||||
userIdPrefix: string;
|
||||
}
|
||||
|
||||
export class BridgeConfigGitLab {
|
||||
readonly instances: {[name: string]: GitLabInstance};
|
||||
readonly webhook: {
|
||||
secret: string;
|
||||
};
|
||||
|
||||
@configKey("Prefix used when creating ghost users for GitLab accounts.", true)
|
||||
readonly userIdPrefix: string;
|
||||
|
||||
constructor(yaml: BridgeConfigGitLabYAML) {
|
||||
this.instances = yaml.instances;
|
||||
this.webhook = yaml.webhook;
|
||||
this.userIdPrefix = yaml.userIdPrefix || "_gitlab_";
|
||||
}
|
||||
}
|
||||
|
||||
export interface BridgeConfigFigma {
|
||||
@ -303,7 +325,7 @@ export interface BridgeConfigRoot {
|
||||
figma?: BridgeConfigFigma;
|
||||
generic?: BridgeGenericWebhooksConfigYAML;
|
||||
github?: BridgeConfigGitHub;
|
||||
gitlab?: BridgeConfigGitLab;
|
||||
gitlab?: BridgeConfigGitLabYAML;
|
||||
permissions?: BridgeConfigActorPermission[];
|
||||
provisioning?: BridgeConfigProvisioning;
|
||||
jira?: BridgeConfigJira;
|
||||
@ -369,7 +391,7 @@ export class BridgeConfig {
|
||||
if (this.github?.oauth && env["GITHUB_OAUTH_REDIRECT_URI"]) {
|
||||
this.github.oauth.redirect_uri = env["GITHUB_OAUTH_REDIRECT_URI"];
|
||||
}
|
||||
this.gitlab = configData.gitlab;
|
||||
this.gitlab = configData.gitlab && new BridgeConfigGitLab(configData.gitlab);
|
||||
this.figma = configData.figma;
|
||||
this.jira = configData.jira && new BridgeConfigJira(configData.jira);
|
||||
this.generic = configData.generic && new BridgeConfigGenericWebhooks(configData.generic);
|
||||
|
@ -65,7 +65,8 @@ export const DefaultConfig = new BridgeConfig({
|
||||
hotlinkIssues: {
|
||||
prefix: "#"
|
||||
}
|
||||
}
|
||||
},
|
||||
userIdPrefix: "_github_",
|
||||
},
|
||||
gitlab: {
|
||||
instances: {
|
||||
@ -75,7 +76,8 @@ export const DefaultConfig = new BridgeConfig({
|
||||
},
|
||||
webhook: {
|
||||
secret: "secrettoken",
|
||||
}
|
||||
},
|
||||
userIdPrefix: "_gitlab_",
|
||||
},
|
||||
jira: {
|
||||
webhook: {
|
||||
|
@ -149,13 +149,13 @@ export class ConnectionManager {
|
||||
}
|
||||
|
||||
if (GitHubDiscussionConnection.EventTypes.includes(state.type)) {
|
||||
if (!this.github) {
|
||||
if (!this.github || !this.config.github) {
|
||||
throw Error('GitHub is not configured');
|
||||
}
|
||||
this.assertStateAllowed(state, "github");
|
||||
return new GitHubDiscussionConnection(
|
||||
roomId, this.as, state.content, state.stateKey, this.tokenStore, this.commentProcessor,
|
||||
this.messageClient,
|
||||
this.messageClient, this.config.github,
|
||||
);
|
||||
}
|
||||
|
||||
@ -171,12 +171,15 @@ export class ConnectionManager {
|
||||
}
|
||||
|
||||
if (GitHubIssueConnection.EventTypes.includes(state.type)) {
|
||||
if (!this.github) {
|
||||
if (!this.github || !this.config.github) {
|
||||
throw Error('GitHub is not configured');
|
||||
}
|
||||
|
||||
this.assertStateAllowed(state, "github");
|
||||
const issue = new GitHubIssueConnection(roomId, this.as, state.content, state.stateKey || "", this.tokenStore, this.commentProcessor, this.messageClient, this.github);
|
||||
const issue = new GitHubIssueConnection(
|
||||
roomId, this.as, state.content, state.stateKey || "", this.tokenStore,
|
||||
this.commentProcessor, this.messageClient, this.github, this.config.github,
|
||||
);
|
||||
await issue.syncIssueState();
|
||||
return issue;
|
||||
}
|
||||
@ -206,7 +209,7 @@ export class ConnectionManager {
|
||||
}
|
||||
|
||||
if (GitLabIssueConnection.EventTypes.includes(state.type)) {
|
||||
if (!this.config.gitlab) {
|
||||
if (!this.github || !this.config.gitlab) {
|
||||
throw Error('GitLab is not configured');
|
||||
}
|
||||
this.assertStateAllowed(state, "gitlab");
|
||||
@ -219,7 +222,9 @@ export class ConnectionManager {
|
||||
this.tokenStore,
|
||||
this.commentProcessor,
|
||||
this.messageClient,
|
||||
instance);
|
||||
instance,
|
||||
this.config.gitlab,
|
||||
);
|
||||
}
|
||||
|
||||
if (JiraProjectConnection.EventTypes.includes(state.type)) {
|
||||
|
@ -12,6 +12,7 @@ import { DiscussionCommentCreatedEvent } from "@octokit/webhooks-types";
|
||||
import { GithubGraphQLClient } from "../Github/GithubInstance";
|
||||
import LogWrapper from "../LogWrapper";
|
||||
import { BaseConnection } from "./BaseConnection";
|
||||
import { BridgeConfigGitHub } from "../Config/Config";
|
||||
export interface GitHubDiscussionConnectionState {
|
||||
owner: string;
|
||||
repo: string;
|
||||
@ -43,11 +44,12 @@ export class GitHubDiscussionConnection extends BaseConnection implements IConne
|
||||
public static async createDiscussionRoom(
|
||||
as: Appservice, userId: string|null, owner: string, repo: string, discussion: Discussion,
|
||||
tokenStore: UserTokenStore, commentProcessor: CommentProcessor, messageClient: MessageSenderClient,
|
||||
config: BridgeConfigGitHub,
|
||||
) {
|
||||
const commentIntent = await getIntentForUser({
|
||||
login: discussion.user.login,
|
||||
avatarUrl: discussion.user.avatar_url,
|
||||
}, as);
|
||||
}, as, config.userIdPrefix);
|
||||
const state: GitHubDiscussionConnectionState = {
|
||||
owner,
|
||||
repo,
|
||||
@ -79,16 +81,17 @@ export class GitHubDiscussionConnection extends BaseConnection implements IConne
|
||||
format: 'org.matrix.custom.html',
|
||||
});
|
||||
await as.botIntent.ensureJoined(roomId);
|
||||
return new GitHubDiscussionConnection(roomId, as, state, '', tokenStore, commentProcessor, messageClient);
|
||||
return new GitHubDiscussionConnection(roomId, as, state, '', tokenStore, commentProcessor, messageClient, config);
|
||||
}
|
||||
|
||||
constructor(roomId: string,
|
||||
private readonly as: Appservice,
|
||||
private state: GitHubDiscussionConnectionState,
|
||||
private readonly state: GitHubDiscussionConnectionState,
|
||||
stateKey: string,
|
||||
private tokenStore: UserTokenStore,
|
||||
private commentProcessor: CommentProcessor,
|
||||
private messageClient: MessageSenderClient) {
|
||||
private readonly tokenStore: UserTokenStore,
|
||||
private readonly commentProcessor: CommentProcessor,
|
||||
private readonly messageClient: MessageSenderClient,
|
||||
private readonly config: BridgeConfigGitHub) {
|
||||
super(roomId, stateKey, GitHubDiscussionConnection.CanonicalEventType);
|
||||
}
|
||||
|
||||
@ -130,7 +133,7 @@ export class GitHubDiscussionConnection extends BaseConnection implements IConne
|
||||
if (this.sentEvents.has(data.comment.node_id)) {
|
||||
return;
|
||||
}
|
||||
const intent = await getIntentForUser(data.comment.user, this.as);
|
||||
const intent = await getIntentForUser(data.comment.user, this.as, this.config.userIdPrefix);
|
||||
await this.messageClient.sendMatrixMessage(this.roomId, {
|
||||
body: data.comment.body,
|
||||
formatted_body: md.render(data.comment.body),
|
||||
|
@ -13,6 +13,7 @@ import { GithubInstance } from "../Github/GithubInstance";
|
||||
import { IssuesGetCommentResponseData, IssuesGetResponseData, ReposGetResponseData} from "../Github/Types";
|
||||
import { IssuesEditedEvent, IssueCommentCreatedEvent } from "@octokit/webhooks-types";
|
||||
import { BaseConnection } from "./BaseConnection";
|
||||
import { BridgeConfigGitHub } from "../Config/Config";
|
||||
|
||||
export interface GitHubIssueConnectionState {
|
||||
org: string;
|
||||
@ -139,7 +140,8 @@ export class GitHubIssueConnection extends BaseConnection implements IConnection
|
||||
private tokenStore: UserTokenStore,
|
||||
private commentProcessor: CommentProcessor,
|
||||
private messageClient: MessageSenderClient,
|
||||
private github: GithubInstance) {
|
||||
private github: GithubInstance,
|
||||
private config: BridgeConfigGitHub,) {
|
||||
super(roomId, stateKey, GitHubIssueConnection.CanonicalEventType);
|
||||
}
|
||||
|
||||
@ -187,7 +189,7 @@ export class GitHubIssueConnection extends BaseConnection implements IConnection
|
||||
const commentIntent = await getIntentForUser({
|
||||
login: comment.user.login,
|
||||
avatarUrl: comment.user.avatar_url,
|
||||
}, this.as);
|
||||
}, this.as, this.config.userIdPrefix);
|
||||
const matrixEvent = await this.commentProcessor.getEventBodyForGitHubComment(comment, event.repository, event.issue);
|
||||
// Comment body may be blank
|
||||
if (matrixEvent) {
|
||||
@ -219,7 +221,7 @@ export class GitHubIssueConnection extends BaseConnection implements IConnection
|
||||
// TODO: Fix
|
||||
login: issue.data.user?.login as string,
|
||||
avatarUrl: issue.data.user?.avatar_url || undefined
|
||||
}, this.as);
|
||||
}, this.as, this.config.userIdPrefix);
|
||||
// We've not sent any messages into the room yet, let's do it!
|
||||
if (issue.data.body) {
|
||||
await this.messageClient.sendMatrixMessage(this.roomId, {
|
||||
|
@ -5,7 +5,7 @@ import { UserTokenStore } from "../UserTokenStore";
|
||||
import LogWrapper from "../LogWrapper";
|
||||
import { CommentProcessor } from "../CommentProcessor";
|
||||
import { MessageSenderClient } from "../MatrixSender";
|
||||
import { GitLabInstance } from "../Config/Config";
|
||||
import { BridgeConfigGitLab, GitLabInstance } from "../Config/Config";
|
||||
import { GetIssueResponse } from "../Gitlab/Types";
|
||||
import { IGitLabWebhookNoteEvent } from "../Gitlab/WebhookTypes";
|
||||
import { getIntentForUser } from "../IntentUtils";
|
||||
@ -51,7 +51,7 @@ export class GitLabIssueConnection extends BaseConnection implements IConnection
|
||||
public static async createRoomForIssue(instanceName: string, instance: GitLabInstance,
|
||||
issue: GetIssueResponse, projects: string[], as: Appservice,
|
||||
tokenStore: UserTokenStore, commentProcessor: CommentProcessor,
|
||||
messageSender: MessageSenderClient) {
|
||||
messageSender: MessageSenderClient, config: BridgeConfigGitLab) {
|
||||
const state: GitLabIssueConnectionState = {
|
||||
projects,
|
||||
state: issue.state,
|
||||
@ -76,7 +76,7 @@ export class GitLabIssueConnection extends BaseConnection implements IConnection
|
||||
],
|
||||
});
|
||||
|
||||
return new GitLabIssueConnection(roomId, as, state, issue.web_url, tokenStore, commentProcessor, messageSender, instance);
|
||||
return new GitLabIssueConnection(roomId, as, state, issue.web_url, tokenStore, commentProcessor, messageSender, instance, config);
|
||||
}
|
||||
|
||||
public get projectPath() {
|
||||
@ -94,7 +94,8 @@ export class GitLabIssueConnection extends BaseConnection implements IConnection
|
||||
private tokenStore: UserTokenStore,
|
||||
private commentProcessor: CommentProcessor,
|
||||
private messageClient: MessageSenderClient,
|
||||
private instance: GitLabInstance,) {
|
||||
private instance: GitLabInstance,
|
||||
private config: BridgeConfigGitLab) {
|
||||
super(roomId, stateKey, GitLabIssueConnection.CanonicalEventType);
|
||||
}
|
||||
|
||||
@ -122,7 +123,7 @@ export class GitLabIssueConnection extends BaseConnection implements IConnection
|
||||
const commentIntent = await getIntentForUser({
|
||||
login: event.user.name,
|
||||
avatarUrl: event.user.avatar_url,
|
||||
}, this.as);
|
||||
}, this.as, this.config.userIdPrefix);
|
||||
const matrixEvent = await this.commentProcessor.getEventBodyForGitLabNote(event);
|
||||
|
||||
await this.messageClient.sendMatrixMessage(this.roomId, matrixEvent, "m.room.message", commentIntent.userId);
|
||||
|
@ -4,8 +4,9 @@ import axios from "axios";
|
||||
|
||||
const log = new LogWrapper("IntentUtils");
|
||||
|
||||
export async function getIntentForUser(user: {avatarUrl?: string, login: string}, as: Appservice) {
|
||||
const intent = as.getIntentForSuffix(user.login);
|
||||
export async function getIntentForUser(user: {avatarUrl?: string, login: string}, as: Appservice, prefix: string) {
|
||||
const domain = as.botUserId.split(":")[1];
|
||||
const intent = as.getIntentForUserId(`@${prefix}${user.login}:${domain}`);
|
||||
const displayName = `${user.login}`;
|
||||
// Verify up-to-date profile
|
||||
let profile;
|
||||
|
Loading…
x
Reference in New Issue
Block a user