mirror of
https://github.com/matrix-org/matrix-hookshot.git
synced 2025-03-10 21:19:13 +00:00
Sneaky jira tweaks
This commit is contained in:
parent
8ab5505a0f
commit
945514bcbc
@ -179,8 +179,10 @@ export class GitLabIssueConnection implements IConnection {
|
||||
if (ev.content.body === '!sync') {
|
||||
// Sync data.
|
||||
// return this.syncIssueState();
|
||||
return true;
|
||||
}
|
||||
await this.onMatrixIssueComment(ev);
|
||||
return true;
|
||||
}
|
||||
|
||||
public toString() {
|
||||
|
@ -13,9 +13,10 @@ export interface IConnection {
|
||||
onEvent?: (ev: MatrixEvent<unknown>) => Promise<void>;
|
||||
|
||||
/**
|
||||
* When a room gets a message event
|
||||
* When a room gets a message event.
|
||||
* @returns Was the message handled
|
||||
*/
|
||||
onMessageEvent?: (ev: MatrixEvent<MatrixMessageContent>) => Promise<void>;
|
||||
onMessageEvent?: (ev: MatrixEvent<MatrixMessageContent>) => Promise<boolean>;
|
||||
|
||||
onIssueCreated?: (ev: IssuesOpenedEvent) => Promise<void>;
|
||||
|
||||
|
@ -7,13 +7,13 @@ import { JiraIssueEvent, JiraIssueUpdatedEvent } from "../Jira/WebhookTypes";
|
||||
import { FormatUtil } from "../FormatUtil";
|
||||
import markdownit from "markdown-it";
|
||||
import { generateJiraWebLinkFromIssue } from "../Jira";
|
||||
import { JiraIssue, JiraProject } from "../Jira/Types";
|
||||
import { JiraProject } from "../Jira/Types";
|
||||
import { botCommand, BotCommands, compileBotCommands } from "../BotCommands";
|
||||
import { MatrixMessageContent } from "../MatrixEvent";
|
||||
import { CommandConnection } from "./CommandConnection";
|
||||
import { start } from "repl";
|
||||
import { UserTokenStore } from "../UserTokenStore";
|
||||
import { CommandError, NotLoggedInError } from "../errors";
|
||||
import JiraApi from "jira-client";
|
||||
|
||||
type JiraAllowedEventsNames = "issue.created";
|
||||
const JiraAllowedEvents: JiraAllowedEventsNames[] = ["issue.created"];
|
||||
@ -159,11 +159,14 @@ export class JiraProjectConnection extends CommandConnection implements IConnect
|
||||
if (!jiraClient) {
|
||||
throw new NotLoggedInError();
|
||||
}
|
||||
const resource = (await jiraClient.getAccessibleResources()).find((r) => new URL(r.url).origin === this.instanceOrigin);
|
||||
if (!resource) {
|
||||
throw new CommandError("No-resource", "You do not have permission to create issues for this JIRA org");
|
||||
if (!this.projectUrl) {
|
||||
throw new CommandError("No-resource-origin", "Room is configured with an ID and not a URL, cannot determine correct JIRA client");
|
||||
}
|
||||
return jiraClient.getClientForResource(resource);
|
||||
const jiraProjectClient = await jiraClient.getClientForUrl(this.projectUrl);
|
||||
if (!jiraProjectClient) {
|
||||
throw new CommandError("No-resource", "You do not have permission to manage issues for this JIRA org");
|
||||
}
|
||||
return jiraProjectClient;
|
||||
}
|
||||
|
||||
@botCommand("create", "Create an issue for this project", ["type", "title"], ["description", "labels"], true)
|
||||
@ -183,7 +186,7 @@ export class JiraProjectConnection extends CommandConnection implements IConnect
|
||||
throw new CommandError("invalid-issuetype", `You must specify a valid issue type (one of ${content}). E.g. ${this.commandPrefix} create ${project.issueTypes[0].name}`);
|
||||
}
|
||||
log.info(`Creating new issue on behalf of ${userId}`);
|
||||
let result: any;
|
||||
let result: JiraApi.JsonResponse;
|
||||
try {
|
||||
result = await api.addNewIssue({
|
||||
//update: {},
|
||||
|
@ -4,7 +4,9 @@ import JiraApi, { SearchUserOptions } from 'jira-client';
|
||||
import QuickLRU from "@alloc/quick-lru";
|
||||
import { JiraAccount, JiraAPIAccessibleResource, JiraIssue, JiraOAuthResult, JiraProject } from './Types';
|
||||
import { BridgeConfigJira } from '../Config/Config';
|
||||
import LogWrapper from '../LogWrapper';
|
||||
|
||||
const log = new LogWrapper("JiraClient");
|
||||
const ACCESSIBLE_RESOURCE_CACHE_LIMIT = 100;
|
||||
const ACCESSIBLE_RESOURCE_CACHE_TTL_MS = 60000;
|
||||
|
||||
@ -13,11 +15,11 @@ export class HookshotJiraApi extends JiraApi {
|
||||
super(options);
|
||||
}
|
||||
|
||||
async getProject(projectIdOrKey: string) {
|
||||
async getProject(projectIdOrKey: string): Promise<JiraProject> {
|
||||
return await super.getProject(projectIdOrKey) as JiraProject;
|
||||
}
|
||||
|
||||
async getIssue(issueIdOrKey: string) {
|
||||
async getIssue(issueIdOrKey: string): Promise<JiraIssue> {
|
||||
const res = await axios.get<JiraIssue>(`https://api.atlassian.com/${this.options.base}/rest/api/3/issue/${issueIdOrKey}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.options.bearer}`
|
||||
@ -60,6 +62,7 @@ export class JiraClient {
|
||||
// Existing failed promise, break out and try again.
|
||||
JiraClient.resourceCache.delete(this.bearer);
|
||||
}
|
||||
await this.checkTokenAge();
|
||||
const promise = (async () => {
|
||||
const res = await axios.get(`https://api.atlassian.com/oauth/token/accessible-resources`, {
|
||||
headers: {
|
||||
@ -74,26 +77,28 @@ export class JiraClient {
|
||||
}
|
||||
|
||||
async checkTokenAge() {
|
||||
console.log("checkTokenAge:", this.oauth2State);
|
||||
if (this.oauth2State.expires_in + 60000 > Date.now()) {
|
||||
return;
|
||||
}
|
||||
log.info(`Refreshing oauth token`);
|
||||
// Refresh the token
|
||||
const res = await axios.post<unknown, JiraOAuthResult>(`https://api.atlassian.com/oauth/token`, {
|
||||
const res = await axios.post(`https://api.atlassian.com/oauth/token`, {
|
||||
grant_type: "refresh_token",
|
||||
client_id: this.config.oauth.client_id,
|
||||
client_secret: this.config.oauth.client_secret,
|
||||
refresh_token: this.oauth2State.refresh_token,
|
||||
});
|
||||
res.expires_in += Date.now() + (res.expires_in * 1000);
|
||||
this.oauth2State = res;
|
||||
const data = res.data as JiraOAuthResult;
|
||||
data.expires_in += Date.now() + (data.expires_in * 1000);
|
||||
this.oauth2State = data;
|
||||
this.onTokenRefreshed(this.oauth2State);
|
||||
}
|
||||
|
||||
async getClientForName(name: string) {
|
||||
const resources = await this.getAccessibleResources();
|
||||
const resource = resources.find((res) => res.name === name);
|
||||
await this.checkTokenAge();
|
||||
async getClientForUrl(url: URL) {
|
||||
const resource = (await this.getAccessibleResources()).find((r) => new URL(r.url).origin === url.origin);
|
||||
if (!resource) {
|
||||
throw Error('User does not have access to this resource');
|
||||
return null;
|
||||
}
|
||||
return this.getClientForResource(resource);
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ export interface JiraIssue {
|
||||
}
|
||||
|
||||
export interface JiraOAuthResult {
|
||||
state: string;
|
||||
state?: string;
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
expires_in: number;
|
||||
|
@ -3,7 +3,6 @@ import { GitLabClient } from "./Gitlab/Client";
|
||||
import { Intent } from "matrix-bot-sdk";
|
||||
import { promises as fs } from "fs";
|
||||
import { publicEncrypt, privateDecrypt } from "crypto";
|
||||
import JiraApi from 'jira-client';
|
||||
import LogWrapper from "./LogWrapper";
|
||||
import { JiraClient } from "./Jira/Client";
|
||||
import { JiraOAuthResult } from "./Jira/Types";
|
||||
|
Loading…
x
Reference in New Issue
Block a user