start moving integrations state to mobx
This commit is contained in:
parent
de35ef8822
commit
452fe62ebe
4 changed files with 606 additions and 0 deletions
126
frontend/app/mstore/integrationsStore.ts
Normal file
126
frontend/app/mstore/integrationsStore.ts
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
import { makeAutoObservable } from 'mobx';
|
||||
|
||||
import { integrationsService } from 'App/services';
|
||||
|
||||
import {
|
||||
Bugsnag,
|
||||
Cloudwatch,
|
||||
DatadogInt,
|
||||
ElasticSearchInt,
|
||||
GithubInt,
|
||||
Integration,
|
||||
IssueTracker,
|
||||
JiraInt,
|
||||
NewRelicInt,
|
||||
RollbarInt,
|
||||
SentryInt,
|
||||
StackDriverInt,
|
||||
SumoLogic,
|
||||
} from './types/integrations';
|
||||
|
||||
class GenericIntegrationsStore {
|
||||
list: any[] = [];
|
||||
siteId: string | null = null;
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
setSiteId(siteId: string) {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
setList(list: any[]) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
fetchIntegrations = async () => {
|
||||
//client.get(`/${siteID}/integrations`)
|
||||
// this.setList()
|
||||
};
|
||||
}
|
||||
|
||||
class NamedIntegrationStore<T extends Integration> {
|
||||
instance: T | null = null;
|
||||
list: T[] = [];
|
||||
fetched: boolean = false;
|
||||
issuesFetched: boolean = false;
|
||||
|
||||
constructor(
|
||||
private readonly name: string,
|
||||
private readonly NamedType: new (config: Record<string, any>) => T
|
||||
) {
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
setInstance(instance: T) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
setList(list: T[]) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
setFetched(fetched: boolean) {
|
||||
this.fetched = fetched;
|
||||
}
|
||||
|
||||
setIssuesFetched(issuesFetched: boolean) {
|
||||
this.issuesFetched = issuesFetched;
|
||||
}
|
||||
|
||||
fetchIntegrations = async () => {
|
||||
const { data } = await integrationsService.fetchList(this.name);
|
||||
this.setList(
|
||||
data.map((config: Record<string, any>) => new this.NamedType(config))
|
||||
);
|
||||
};
|
||||
|
||||
fetchIntegration = async (siteId: string) => {
|
||||
const { data } = await integrationsService.fetchIntegration(
|
||||
this.name,
|
||||
siteId
|
||||
);
|
||||
this.setInstance(new this.NamedType(data));
|
||||
};
|
||||
|
||||
saveIntegration(name: string, siteId: string) {
|
||||
if (!this.instance) return;
|
||||
const response = integrationsService.saveIntegration(
|
||||
name,
|
||||
siteId,
|
||||
this.instance.toData()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
edit(data: T) {
|
||||
this.setInstance(data);
|
||||
}
|
||||
|
||||
deleteIntegration(siteId: string) {
|
||||
if (!this.instance) return;
|
||||
integrationsService.removeIntegration(this.name, siteId);
|
||||
}
|
||||
|
||||
init(config: Record<string, any>) {
|
||||
this.instance = new this.NamedType(config);
|
||||
}
|
||||
}
|
||||
|
||||
export class IntegrationsStore {
|
||||
sentry = new NamedIntegrationStore('sentry', SentryInt);
|
||||
datadog = new NamedIntegrationStore('datadog', DatadogInt);
|
||||
stackdriver = new NamedIntegrationStore('stackdriver', StackDriverInt);
|
||||
rollbar = new NamedIntegrationStore('rollbar', RollbarInt);
|
||||
newrelic = new NamedIntegrationStore('newrelic', NewRelicInt);
|
||||
bugsnag = new NamedIntegrationStore('bugsnag', Bugsnag);
|
||||
cloudwatch = new NamedIntegrationStore('cloudwatch', Cloudwatch);
|
||||
elasticsearch = new NamedIntegrationStore('elasticsearch', ElasticSearchInt);
|
||||
sumologic = new NamedIntegrationStore('sumologic', SumoLogic);
|
||||
jira = new NamedIntegrationStore('jira', JiraInt);
|
||||
github = new NamedIntegrationStore('github', GithubInt);
|
||||
issues = new NamedIntegrationStore('issues', IssueTracker);
|
||||
integrations = new GenericIntegrationsStore();
|
||||
// + slack
|
||||
// + teams
|
||||
}
|
||||
444
frontend/app/mstore/types/integrations.ts
Normal file
444
frontend/app/mstore/types/integrations.ts
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
import { makeAutoObservable } from 'mobx';
|
||||
|
||||
import { validateURL } from 'App/validate';
|
||||
|
||||
export interface Integration {
|
||||
validate(): boolean;
|
||||
exists(): boolean;
|
||||
toData(): Record<string, any>;
|
||||
}
|
||||
|
||||
export class SentryInt implements Integration {
|
||||
projectId: number;
|
||||
organizationSlug: string = '';
|
||||
projectSlug: string = '';
|
||||
token: string = '';
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
validate() {
|
||||
return Boolean(this.organizationSlug && this.projectSlug && this.token);
|
||||
}
|
||||
|
||||
exists() {
|
||||
return this.projectId >= 0;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
organizationSlug: this.organizationSlug,
|
||||
projectSlug: this.projectSlug,
|
||||
token: this.token,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class DatadogInt implements Integration {
|
||||
apiKey: string = '';
|
||||
applicationKey: string = '';
|
||||
projectId: number;
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
validate() {
|
||||
return Boolean(this.apiKey && this.applicationKey);
|
||||
}
|
||||
|
||||
exists() {
|
||||
return this.projectId >= 0;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
apiKey: this.apiKey,
|
||||
applicationKey: this.applicationKey,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class StackDriverInt implements Integration {
|
||||
projectId: number;
|
||||
logName: string = '';
|
||||
serviceAccountCredentials: string = '';
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
validate() {
|
||||
return Boolean(
|
||||
this.serviceAccountCredentials !== '' && this.logName !== ''
|
||||
);
|
||||
}
|
||||
|
||||
exists() {
|
||||
return this.projectId >= 0;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
logName: this.logName,
|
||||
serviceAccountCredentials: this.serviceAccountCredentials,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class RollbarInt implements Integration {
|
||||
projectId: number;
|
||||
accessToken: string = '';
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
validate() {
|
||||
return Boolean(this.accessToken);
|
||||
}
|
||||
|
||||
exists() {
|
||||
return this.projectId >= 0;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
accessToken: this.accessToken,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class NewRelicInt implements Integration {
|
||||
projectId: number;
|
||||
applicationId: string = '';
|
||||
xQueryKey: string = '';
|
||||
region: boolean = true;
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
validate() {
|
||||
return Boolean(this.applicationId && this.xQueryKey);
|
||||
}
|
||||
|
||||
exists() {
|
||||
return this.projectId >= 0;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
applicationId: this.applicationId,
|
||||
xQueryKey: this.xQueryKey,
|
||||
region: this.region,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class Bugsnag implements Integration {
|
||||
projectId: number;
|
||||
authorizationToken: string = '';
|
||||
bugsnagProjectId: string = '';
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
validate() {
|
||||
return Boolean(
|
||||
this.bugsnagProjectId !== '' && tokenRE.test(this.authorizationToken)
|
||||
);
|
||||
}
|
||||
|
||||
exists() {
|
||||
return this.projectId >= 0;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
authorizationToken: this.authorizationToken,
|
||||
bugsnagProjectId: this.bugsnagProjectId,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class Cloudwatch implements Integration {
|
||||
projectId: number;
|
||||
awsAccessKeyId: string = '';
|
||||
awsSecretAccessKey: string = '';
|
||||
region: string = 'us-east-1';
|
||||
logGroupName: string = '';
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
validate() {
|
||||
return Boolean(
|
||||
this.awsAccessKeyId !== '' &&
|
||||
this.awsSecretAccessKey !== '' &&
|
||||
this.logGroupName !== '' &&
|
||||
this.region !== ''
|
||||
);
|
||||
}
|
||||
|
||||
exists() {
|
||||
return this.projectId >= 0;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
awsAccessKeyId: this.awsAccessKeyId,
|
||||
awsSecretAccessKey: this.awsSecretAccessKey,
|
||||
region: this.region,
|
||||
logGroupName: this.logGroupName,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class ElasticSearchInt implements Integration {
|
||||
projectId: number;
|
||||
host: string = '';
|
||||
apiKeyId: string = '';
|
||||
apiKey: string = '';
|
||||
indexes: string = '*log*';
|
||||
port: number = 9200;
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
private validateKeys() {
|
||||
return Boolean(
|
||||
this.apiKeyId.length > API_KEY_ID_LENGTH &&
|
||||
this.apiKey.length > API_KEY_LENGTH &&
|
||||
validateURL(this.host)
|
||||
);
|
||||
}
|
||||
|
||||
validate() {
|
||||
return (
|
||||
this.host !== '' &&
|
||||
this.apiKeyId !== '' &&
|
||||
this.apiKey !== '' &&
|
||||
this.indexes !== '' &&
|
||||
!!this.port &&
|
||||
this.validateKeys()
|
||||
);
|
||||
}
|
||||
|
||||
exists() {
|
||||
return this.projectId >= 0;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
host: this.host,
|
||||
apiKeyId: this.apiKeyId,
|
||||
apiKey: this.apiKey,
|
||||
indexes: this.indexes,
|
||||
port: this.port,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class SumoLogic implements Integration {
|
||||
projectId: number;
|
||||
accessId: string = '';
|
||||
accessKey: string = '';
|
||||
region: 'au';
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
validate() {
|
||||
return Boolean(this.accessKey && this.accessId);
|
||||
}
|
||||
|
||||
exists() {
|
||||
return this.projectId >= 0;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
accessId: this.accessId,
|
||||
accessKey: this.accessKey,
|
||||
region: this.region,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class JiraInt implements Integration {
|
||||
projectId: number;
|
||||
username: string = '';
|
||||
token: string = '';
|
||||
url: string = '';
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
validateFetchProjects() {
|
||||
return this.username !== '' && this.token !== '' && validateURL(this.url);
|
||||
}
|
||||
|
||||
validate() {
|
||||
return this.validateFetchProjects();
|
||||
}
|
||||
|
||||
exists() {
|
||||
return !!this.token;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
username: this.username,
|
||||
token: this.token,
|
||||
url: this.url,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class GithubInt implements Integration {
|
||||
projectId: number;
|
||||
provider: string = 'github';
|
||||
token: string = '';
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
projectId: config.projectId || -1,
|
||||
});
|
||||
}
|
||||
|
||||
validate() {
|
||||
return this.token !== '';
|
||||
}
|
||||
|
||||
exists() {
|
||||
return !!this.token;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
provider: this.provider,
|
||||
token: this.token,
|
||||
projectId: this.projectId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class IssueTracker implements Integration {
|
||||
username: string = '';
|
||||
token: string = '';
|
||||
url: string = '';
|
||||
provider = 'jira';
|
||||
|
||||
constructor(config: any) {
|
||||
Object.assign(this, {
|
||||
...config,
|
||||
});
|
||||
}
|
||||
|
||||
validateFetchProjects() {
|
||||
return this.username !== '' && this.token !== '' && validateURL(this.url);
|
||||
}
|
||||
|
||||
validate() {
|
||||
return !!this.url;
|
||||
}
|
||||
|
||||
exists() {
|
||||
return !!this.token;
|
||||
}
|
||||
|
||||
toData() {
|
||||
return {
|
||||
username: this.username,
|
||||
token: this.token,
|
||||
url: this.url,
|
||||
provider: this.provider,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const sumoRegionLabels = {
|
||||
au: 'Asia Pacific (Sydney)',
|
||||
ca: 'Canada (Central)',
|
||||
de: 'EU (Frankfurt)',
|
||||
eu: 'EU (Ireland)',
|
||||
fed: 'US East (N. Virginia)',
|
||||
in: 'Asia Pacific (Mumbai)',
|
||||
jp: 'Asia Pacific (Tokyo)',
|
||||
us1: 'US East (N. Virginia)',
|
||||
us2: 'US West (Oregon)',
|
||||
};
|
||||
export const API_KEY_ID_LENGTH = 5;
|
||||
export const API_KEY_LENGTH = 5;
|
||||
export const SECRET_ACCESS_KEY_LENGTH = 40;
|
||||
export const ACCESS_KEY_ID_LENGTH = 20;
|
||||
export const tokenRE =
|
||||
/^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/i;
|
||||
export const awsRegionLabels = {
|
||||
'us-east-1': 'US East (N. Virginia)',
|
||||
'us-east-2': 'US East (Ohio)',
|
||||
'us-west-1': 'US West (N. California)',
|
||||
'us-west-2': 'US West (Oregon)',
|
||||
'ap-east-1': 'Asia Pacific (Hong Kong)',
|
||||
'ap-south-1': 'Asia Pacific (Mumbai)',
|
||||
'ap-northeast-2': 'Asia Pacific (Seoul)',
|
||||
'ap-southeast-1': 'Asia Pacific (Singapore)',
|
||||
'ap-southeast-2': 'Asia Pacific (Sydney)',
|
||||
'ap-northeast-1': 'Asia Pacific (Tokyo)',
|
||||
'ca-central-1': 'Canada (Central)',
|
||||
'eu-central-1': 'EU (Frankfurt)',
|
||||
'eu-west-1': 'EU (Ireland)',
|
||||
'eu-west-2': 'EU (London)',
|
||||
'eu-west-3': 'EU (Paris)',
|
||||
'eu-north-1': 'EU (Stockholm)',
|
||||
'me-south-1': 'Middle East (Bahrain)',
|
||||
'sa-east-1': 'South America (São Paulo)',
|
||||
};
|
||||
33
frontend/app/services/IntegrationsService.ts
Normal file
33
frontend/app/services/IntegrationsService.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import BaseService from "./BaseService";
|
||||
|
||||
export default class IntegrationsService extends BaseService {
|
||||
fetchList = async (name) => {
|
||||
const r = await this.client.get(`/integrations/${name}`)
|
||||
const data = await r.json()
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
fetchIntegration = async (name: string, siteId: string) => {
|
||||
const url = siteId && name !== 'github' && name !== 'jira' ? `/${siteId}/integrations/${name}` : `/integrations/${name}`
|
||||
const r = await this.client.get(url)
|
||||
const data = await r.json()
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
saveIntegration = async (name: string, siteId: string, data: any) => {
|
||||
const url = (siteId ? `/${siteId}` : '') + `/integrations/${name}`
|
||||
const r = await this.client.post(url, data)
|
||||
const res = await r.json()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
removeIntegration = async (name: string, siteId: string) => {
|
||||
const url = (siteId ? `/${siteId}` : '') + `/integrations/${name}`
|
||||
const r = await this.client.delete(url)
|
||||
const res = await r.json()
|
||||
|
||||
return res
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ import SpotService from './spotService';
|
|||
import LoginService from "./loginService";
|
||||
import FilterService from "./FilterService";
|
||||
import IssueReportsService from "./IssueReportsService";
|
||||
import IntegrationsService from './IntegrationsService';
|
||||
|
||||
export const dashboardService = new DashboardService();
|
||||
export const metricService = new MetricService();
|
||||
|
|
@ -44,6 +45,7 @@ export const spotService = new SpotService();
|
|||
export const loginService = new LoginService();
|
||||
export const filterService = new FilterService();
|
||||
export const issueReportsService = new IssueReportsService();
|
||||
export const integrationsService = new IntegrationsService();
|
||||
|
||||
export const services = [
|
||||
dashboardService,
|
||||
|
|
@ -68,4 +70,5 @@ export const services = [
|
|||
loginService,
|
||||
filterService,
|
||||
issueReportsService,
|
||||
integrationsService,
|
||||
];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue