UNPKG

@cn-shell/jira

Version:
740 lines (739 loc) 26.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CNJira = void 0; const cn_shell_1 = __importDefault(require("cn-shell")); const jira_resource_url_1 = require("./jira-resource-url"); // Jira config consts here const CFG_JIRA_SERVER = "JIRA_SERVER"; const CFG_JIRA_USER = "JIRA_USER"; const CFG_JIRA_PASSWORD = "JIRA_PASSWORD"; const CFG_SESSION_REFRESH_PERIOD = "SESSION_REFRESH_PERIOD"; const DEFAULT_SESSION_REFRESH_PERIOD = "60"; // In mins // Misc consts here const SCRIPTRUNNER_DASHBOARDS_N_FILTERS_URL = "rest/scriptrunner/latest/canned/com.onresolve.scriptrunner.canned.jira.admin.ChangeSharedEntityOwnership"; // CNJira class here class CNJira extends cn_shell_1.default { // Constructor here constructor(name, master) { super(name, master); let server = this.getRequiredCfg(CFG_JIRA_SERVER); this._server = server.replace(/(\/+$)/, ""); this._user = this.getCfg(CFG_JIRA_USER); this._password = this.getCfg(CFG_JIRA_PASSWORD, undefined, false, true); let period = this.getCfg(CFG_SESSION_REFRESH_PERIOD, DEFAULT_SESSION_REFRESH_PERIOD); this._refreshPeriod = parseInt(period, 10) * 60 * 1000; // Convert to ms // Prepend the server to the resources to make our life easier this._resourceUrls = {}; for (let r in jira_resource_url_1.JiraResources) { this._resourceUrls[r] = `${this._server}${jira_resource_url_1.JiraResources[r]}`; } } // Abstract method implementations here async start() { return true; } async stop() { return; } async healthCheck() { return true; } // Private methods here // Public methods here async login(auth) { let url = this._resourceUrls.session; let res = await this.httpReq({ method: "post", url, data: { username: auth !== undefined ? auth.username : this._user, password: auth !== undefined ? auth.password : this._password, }, }); this._jiraSessionId = res.data.session.value; // Start a timer to sutomatically renew the session ID this._timeout = setTimeout(() => { this.info("Refreshing session ID!"); this.login(); }, this._refreshPeriod); } async logout() { if (this._jiraSessionId === undefined) { return; } // Stop the timer first! clearInterval(this._timeout); let url = this._resourceUrls.session; await this.httpReq({ method: "delete", url, headers: { cookie: `JSESSIONID=${this._jiraSessionId}`, }, }); this._jiraSessionId = undefined; } async getFieldDict(update = false) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } // Check to see if the field dict is populated AND the user hasn't requested it to be updated if (this._fieldDict !== undefined && update === false) { return this._fieldDict; } let url = this._resourceUrls.field; let res = await this.httpReq({ method: "get", url, headers, }); this._fieldDict = { byId: {}, byName: {} }; if (Array.isArray(res.data)) { for (let field of res.data) { this._fieldDict.byName[field.name] = { id: field.id, type: field.schema !== undefined ? field.schema.type : "Unknown", itemType: field.schema !== undefined ? field.schema.items : "Unknown", }; this._fieldDict.byId[field.id] = { name: field.name, type: field.schema !== undefined ? field.schema.type : "Unknown", itemType: field.schema !== undefined ? field.schema.items : "Unknown", }; } } return this._fieldDict; } async getAllowedFieldValues(projectKey, issueType, fieldName) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = this._resourceUrls.createmeta; let params = new URLSearchParams(); params.append("expand", "projects.issuetypes.fields"); params.append("projectKeys", projectKey); params.append("issuetypeNames", issueType); let res = await this.httpReq({ method: "get", url, params, headers, }); // Convert field name to field ID let dict = await this.getFieldDict(); let fieldInfo = dict.byName[fieldName]; if (fieldInfo === undefined) { throw Error(`Unknown field ${fieldName}`); } let field = res.data.projects[0].issuetypes[0].fields[fieldInfo.id]; if (field === undefined || field.allowedValues === undefined) { return []; } let allowed = []; for (let info of field.allowedValues) { allowed.push(info.value); } return allowed; } async getComponents(projectKey) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._resourceUrls.components}/${projectKey}/components`; let res = await this.httpReq({ method: "get", url, headers, }); let components = {}; for (let component of res.data) { components[component.name] = component.id; } return components; } async getProjects(component) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = this._resourceUrls.project; let params = new URLSearchParams(); params.append("expand", "lead"); let res = await this.httpReq({ method: "get", url, headers, params, }); let projects = res.data; if (component !== undefined) { return projects.filter(el => el.projectCategory.name === component); } return projects; } // TODO: add getProject async updateProject(project, data) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._resourceUrls.project}/${project}`; await this.httpReq({ method: "put", url, headers, data, }); } async updateProjectLead(project, lead) { await this.updateProject(project, { lead }); } async createIssue(projectKey, issueType, component, fields) { var _a; let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let components = await this.getComponents(projectKey); let issue = { fields: { project: { key: projectKey }, issuetype: { name: issueType }, components: [{ id: components[component] }], }, }; // Convert any field names to field IDs await this.getFieldDict(); for (let fname in fields) { let fid = (_a = this._fieldDict.byName[fname]) === null || _a === void 0 ? void 0 : _a.id; if (fid !== undefined) { issue.fields[fid] = fields[fname]; } else { issue.fields[fname] = fields[fname]; } } let url = this._resourceUrls.issue; this.debug("createIssue: issue (%j)", issue); let res = await this.httpReq({ method: "post", url, data: issue, headers, }); return res.data.key; } async updateIssue(key, fields, notifyUsers = true) { var _a; let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let issue = { fields: {}, }; // Convert any field names to field IDs await this.getFieldDict(); for (let fname in fields) { let fid = (_a = this._fieldDict.byName[fname]) === null || _a === void 0 ? void 0 : _a.id; if (fid !== undefined) { issue.fields[fid] = fields[fname]; } else { issue.fields[fname] = fields[fname]; } } let url = `${this._resourceUrls.issue}/${key}`; if (notifyUsers === false) { url = `${url}?notifyUsers=false`; } let res = await this.httpReq({ method: "put", url, data: issue, headers, }); return res.data.key; } async getIssue(idOrKey) { var _a; let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._resourceUrls.issue}/${idOrKey}`; let res = await this.httpReq({ method: "get", url, headers, }); let issue = {}; // Convert any field IDs to field name await this.getFieldDict(); for (let fid in res.data.fields) { let fname = (_a = this._fieldDict.byId[fid]) === null || _a === void 0 ? void 0 : _a.name; if (fname !== undefined) { issue[fname] = res.data.fields[fid]; } else { issue[fid] = res.data.fields[fid]; } } // Add id to list of fields issue["id"] = res.data.id; return issue; } async issueReporter(key, reporter, notifyUsers = true) { await this.updateIssue(key, { reporter: { name: reporter } }, notifyUsers); } async assignIssue(key, assignee, notifyUsers = true) { await this.updateIssue(key, { assignee: { name: assignee, }, }, notifyUsers); } async updateLabels(key, action, labels, notifyUsers = true) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let issue = { update: { labels: [], }, }; issue.update.labels = []; // Convert any field names to field IDs await this.getFieldDict(); for (let label of labels) { issue.update.labels.push({ [action]: label }); } let url = `${this._resourceUrls.issue}/${key}`; if (notifyUsers === false) { url = `${url}?notifyUsers=false`; } let res = await this.httpReq({ method: "put", url, data: issue, headers, }); return res.data.key; } async addComment(idOrKey, comment) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._resourceUrls.issue}/${idOrKey}/comment`; await this.httpReq({ method: "post", url, data: { body: comment, }, headers, }); } async addWatcher(idOrKey, watcher) { let headers = { "Content-Type": "application/json;charset=UTF-8", }; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._resourceUrls.issue}/${idOrKey}/watchers`; await this.httpReq({ method: "post", url, data: JSON.stringify(watcher), headers, }); } async removeWatcher(idOrKey, watcher) { let headers = { "Content-Type": "application/json;charset=UTF-8", }; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._resourceUrls.issue}/${idOrKey}/watchers`; let params = new URLSearchParams(); params.append("username", watcher); await this.httpReq({ method: "delete", url, data: JSON.stringify(watcher), headers, params, }); } async getTransitions(idOrKey) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._resourceUrls.issue}/${idOrKey}/transitions`; let res = await this.httpReq({ method: "get", url, headers, }); let transitions = {}; for (let transition of res.data.transitions) { transitions[transition.name] = transition.id; } return transitions; } async doTransition(idOrKey, transitionIdOrName, fields, comment) { var _a; let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } // transition may be the Transition ID or name so check let availableTransitions = await this.getTransitions(idOrKey); let transitionId = availableTransitions[transitionIdOrName]; if (transitionId === undefined) { transitionId = transitionIdOrName; } let dfields = {}; if (fields !== undefined) { // Convert any field names to field IDs await this.getFieldDict(); for (let fname in fields) { let fid = (_a = this._fieldDict.byName[fname]) === null || _a === void 0 ? void 0 : _a.id; if (fid !== undefined) { dfields[fid] = { name: fields[fname] }; } else { dfields[fname] = { name: fields[fname] }; } } } let dcomment = { comment: [{ add: { body: comment } }] }; let data = { update: comment === undefined ? undefined : dcomment, fields: fields === undefined || fields.length === 0 ? undefined : dfields, transition: { id: transitionId }, }; let url = `${this._resourceUrls.issue}/${idOrKey}/transitions`; await this.httpReq({ method: "post", url, data, headers, }); } async runJql(jql) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._resourceUrls.search}?jql=${encodeURI(jql)}`; let res = await this.httpReq({ method: "get", url, headers, }); if (res === undefined) { return []; } return res.data.issues; } async jqlGetAll(jql) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let issues = []; let startAt = 0; let maxResults = 1000; // 1000 is the max you can get while (true) { let url = `${this._resourceUrls.search}?jql=${encodeURI(jql)}&startAt=${startAt}&maxResults=${maxResults}&fields=key`; let res = await this.httpReq({ method: "get", url, headers, }).catch(e => { this.error(e); }); if (res === undefined) { break; } // Append the results to what we already have let results = res.data; for (let issue of results.issues) { issues.push(issue.key); } // Increment by maxResults startAt += maxResults; // If we are beyond the total then we have everything so break, // otherwise go again if (startAt > results.total) { break; } } return issues; } async getUserDashboardIds(userId) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._server}/${SCRIPTRUNNER_DASHBOARDS_N_FILTERS_URL}/params`; let res = await this.httpReq({ method: "post", url, data: { FIELD_FROM_USER_ID: userId, }, headers, }); let dashboardIds = []; let data = res.data; for (let obj of data) { if (obj.name === "FIELD_DASHBOARD_IDS") { for (let value of obj.values) { dashboardIds.push(value[0]); } } } return dashboardIds; } async getUserFilterIds(userId) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._server}/${SCRIPTRUNNER_DASHBOARDS_N_FILTERS_URL}/params`; let res = await this.httpReq({ method: "post", url, data: { FIELD_FROM_USER_ID: userId, }, headers, }); let filterIds = []; let data = res.data; for (let obj of data) { if (obj.name === "FIELD_FILTER_IDS") { for (let value of obj.values) { filterIds.push(value[0].toString()); } } } return filterIds; } async migrateDashboards(fromUserId, toUserId, dashboardIds) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._server}/${SCRIPTRUNNER_DASHBOARDS_N_FILTERS_URL}`; let res = await this.httpReq({ method: "post", url, data: { FIELD_FROM_USER_ID: fromUserId, FIELD_TO_USER_ID: toUserId, FIELD_DASHBOARD_IDS: dashboardIds, FIELD_FILTER_IDS: [], }, headers, }); this.info("%s", res.data); } async migrateFilters(fromUserId, toUserId, filterIds) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._server}/${SCRIPTRUNNER_DASHBOARDS_N_FILTERS_URL}`; let res = await this.httpReq({ method: "post", url, data: { FIELD_FROM_USER_ID: fromUserId, FIELD_TO_USER_ID: toUserId, FIELD_DASHBOARD_IDS: [], FIELD_FILTER_IDS: filterIds, }, headers, }); this.info("%s", res.data); } async getUser(user, byKey, includeGroups = false) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = this._resourceUrls.user; let params = new URLSearchParams(); if (byKey) { params.append("key", user); } else { params.append("username", user); } if (includeGroups) { params.append("expand", "groups"); } let res = await this.httpReq({ method: "get", url, params, headers, }); return res.data; } async addUserToGroup(user, group) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._resourceUrls.group}/user`; let params = new URLSearchParams(); params.append("groupname", group); let res = await this.httpReq({ method: "post", url, params, headers, data: { name: user }, }); return res.data; } async getUserGroups(user) { var _a; let details = await this.getUser(user, false, true); let groups = []; let groupItems = (_a = details === null || details === void 0 ? void 0 : details.groups) === null || _a === void 0 ? void 0 : _a.items; if (groups !== undefined) { for (let group of groupItems) { groups.push(group.name); } } return groups; } async addUserToApplication(user, applicationKey) { let headers = {}; if (this._jiraSessionId !== undefined) { headers.cookie = `JSESSIONID=${this._jiraSessionId}`; } else { let token = Buffer.from(`${this._user}:${this._password}`).toString("base64"); headers.Authorization = `Basic ${token}`; } let url = `${this._resourceUrls.user}/application`; let params = new URLSearchParams(); params.append("username", user); params.append("applicationKey", applicationKey); await this.httpReq({ method: "post", url, params, headers, data: {}, }).catch(e => { this.error(e); }); } } exports.CNJira = CNJira;