Files
plane/web/ee/store/integrations/github/auth.store.ts
Saurabh Kumar 207e85e3a1 [SILO] : Importer and integrations db migration changes (#2363)
* `silo` refactoring changes  (#2304)

* add sdk and services for workspace connection and import jobs

* rename service

* move worker folder to root + remove controller folder

* remove controller folder

* add external api service in silo

* fix params in service

* fix params in service

* fix services + remove projectid in job endpoints

* chore: added generic config types for job store (#2158)

* chore: made import job as generic

* chore: added generic parameter inside the job service

* chore: added generic parameter inside the job service

* feat: remove projectId from jobs endpoint

* chore: modified job store for new services

* chore: revert go.mod.sum

* chore: spaces

* gitlab auth callback

* github controllers update with plane api

* create api client fix

* base integration importer store

* remove junk store

* silo external api token middleware + plane api to generate user tokens

* add ahmac permission method in apiserver + ahmac sign flow on silo

* remove junk

* getapi client remove unwanted options

* modify api route for silo access + github gitlab and slack controller clean up

* types modify + jira importer cleanup

* fix: nodemon setup

* make getAPIClient as a singleton

* chore: added new definitions in base-import-worker

* chore: modified jira migrator to adhere to the modified types

* feat: modified base migrator to adhere new types

* chore: modified jira-server-migrator to adhere new changes

* chore: modified asana importer to adhere to new types

* fix: migrated importer controllers for new schema

* fix: build

* chore: asana and linear controller

* feat: updated job controller for new schema changes

* chore: added permissions

* integrations api migrations changes (#2193)

* chore: added workspace_slug inside job data

* replaced ahmac with hmac implementation

* add new service base api view for microservices

* fix: apiserver changes and base view

* feat: added changes to services

* feat: modified engine controller for using api services

* feat: modified UI stores for modified jira importer

* remove-log

* resolve hmac issue + silo endpoint url fixes

* add silo target access token rotation in get

* integration ui migration changes

* revert changes in il8n

* fix crud for api

* fix crud for api

* fix: batch lock config

* fix silo bundler issue (#2233)

* chore: combined common dashboard components for silo (#2166)

* chore: added new types to job store

* feat: updated job store dependencies for new params

* feat: created common components for importers dashboard

* feat: modified jira importer to comply with new common components

* feat: modified jira server dashboard to comply with the new component changes

* feat: modified asana to comply with the common dashboard changes

* fix: linear to comply with the new changes

* reset job store

* feat: migrated importers to new schema

* fix: removed unused code

* fix: base job importer model and serializer

* fix-lint-errors

---------

Co-authored-by: Saurabh Kumar <70131915+Saurabhkmr98@users.noreply.github.com>

* fix api serialisers

* fix: stabilized all integrations and jira importer

* fix: linear, asana and jira-server importers

* fix: reinstantiated hmac permission

* chore: removed the db folder for silo

* feat: added types for integration config

* feat: added check for supported integration in silo and web

* feat: added self hosted and cloud message differences

* add en translations for importers and jira importer (#2264)

* feat: Added language support for integrations (#2277)

* feat: added translations for github, slack and gitlab integrations

* fix: slack integration project modal

* fix: gitlab organization disconnect

* fix: silo build fixes

* feat: added more language to integration language support

* fix: review

* feat: modified caddy and compose for silo selfhosted changes (#2276)

* silo - fixes for keys and integrations form reset (#2283)

* fix hardcoded values for integration importer keys

* reset state after integration form submit

* fix missing key integration

* fix gitlab connection update

* fix: added slack images being updated while creating issues (#2288)

Co-authored-by: Saurabh Kumar <70131915+Saurabhkmr98@users.noreply.github.com>

* silo - fix integration lang support (#2291)

* fix hardcoded values for integration importer keys

* reset state after integration form submit

* fix missing translation key integration

* fix gitlab connection update

* fix integration lang support

* fix integration lang support

---------

Co-authored-by: Saurabhkmr98 <saurabhkapur73@gmail.com>
Co-authored-by: Saurabh Kumar <70131915+Saurabhkmr98@users.noreply.github.com>

* [SILO-71] flatfile importer v1 (#2156)

* feat: initialized CSV importer

* feat: added flatfile components

* feat: setup workbook and listener for csv importer

* feat: added store structure for flatfile importer

* chore: translated csv importer to flatfile importer

* feat: setup listener

* fix: event listener for creating agent

* feat: added flatfile importer skeleton

* feat: added flatfile etl logic for pulling and transforming data

* feat: added flatfile controller and migrator

* feat: curated flatfile root store and importer UI

* feat: initialized flatfile migrator

* fix: flatfile

* feat: added transformers for cycles and issues

* feat: added mapping and transformation for flatfile

* feat: added assignee field for fixing migrator bugs

* fix:build

* feat: added metrics inside the data import task'

* fix:workbook

* feat: added validation of email and date for flatfile

* add sdk and services for workspace connection and import jobs

* rename service

* move worker folder to root + remove controller folder

* remove controller folder

* feat: added modules and issue types inside flatfile

* fix: build

* fix:response-handler

* fix:errors

* fix:deleted-file

* fix: readded jobs route

* add external api service in silo

* fix params in service

* fix params in service

* fix services + remove projectid in job endpoints

* chore: added generic config types for job store (#2158)

* chore: made import job as generic

* chore: added generic parameter inside the job service

* chore: added generic parameter inside the job service

* feat: remove projectId from jobs endpoint

* chore: modified job store for new services

* chore: revert go.mod.sum

* chore: spaces

* gitlab auth callback

* github controllers update with plane api

* create api client fix

* base integration importer store

* remove junk store

* silo external api token middleware + plane api to generate user tokens

* add ahmac permission method in apiserver + ahmac sign flow on silo

* remove junk

* getapi client remove unwanted options

* modify api route for silo access + github gitlab and slack controller clean up

* types modify + jira importer cleanup

* fix: nodemon setup

* make getAPIClient as a singleton

* chore: added new definitions in base-import-worker

* chore: modified jira migrator to adhere to the modified types

* feat: modified base migrator to adhere new types

* chore: modified jira-server-migrator to adhere new changes

* chore: modified asana importer to adhere to new types

* fix: migrated importer controllers for new schema

* fix: build

* chore: asana and linear controller

* feat: updated job controller for new schema changes

* chore: added permissions

* integrations api migrations changes (#2193)

* chore: added workspace_slug inside job data

* replaced ahmac with hmac implementation

* add new service base api view for microservices

* fix: apiserver changes and base view

* feat: added changes to services

* feat: modified engine controller for using api services

* feat: modified UI stores for modified jira importer

* remove-log

* resolve hmac issue + silo endpoint url fixes

* add silo target access token rotation in get

* integration ui migration changes

* revert changes in il8n

* fix crud for api

* fix crud for api

* fix: batch lock config

* fix silo bundler issue (#2233)

* chore: combined common dashboard components for silo (#2166)

* chore: added new types to job store

* feat: updated job store dependencies for new params

* feat: created common components for importers dashboard

* feat: modified jira importer to comply with new common components

* feat: modified jira server dashboard to comply with the new component changes

* feat: modified asana to comply with the common dashboard changes

* fix: linear to comply with the new changes

* reset job store

* feat: migrated importers to new schema

* fix: removed unused code

* fix: base job importer model and serializer

* fix-lint-errors

---------

Co-authored-by: Saurabh Kumar <70131915+Saurabhkmr98@users.noreply.github.com>

* fix api serialisers

* fix: stabilized all integrations and jira importer

* fix: linear, asana and jira-server importers

* fix: reinstantiated hmac permission

* chore: removed the db folder for silo

* feat: added types for integration config

* feat: added check for supported integration in silo and web

* feat: added self hosted and cloud message differences

* add en translations for importers and jira importer (#2264)

* feat: Added language support for integrations (#2277)

* feat: added translations for github, slack and gitlab integrations

* fix: slack integration project modal

* fix: gitlab organization disconnect

* fix: silo build fixes

* feat: added more language to integration language support

* fix: review

* feat: modified caddy and compose for silo selfhosted changes (#2276)

* silo - fixes for keys and integrations form reset (#2283)

* fix hardcoded values for integration importer keys

* reset state after integration form submit

* fix missing key integration

* fix gitlab connection update

* fix: added slack images being updated while creating issues (#2288)

Co-authored-by: Saurabh Kumar <70131915+Saurabhkmr98@users.noreply.github.com>

* silo - fix integration lang support (#2291)

* fix hardcoded values for integration importer keys

* reset state after integration form submit

* fix missing translation key integration

* fix gitlab connection update

* fix integration lang support

* fix integration lang support

* feat: added controllers as default exports

* feat: modified flatfile worker and controller to adhere new changes

* feat: modified flatfile importer to ahere silo api migration

* fix: source project and workspace hide props

---------

Co-authored-by: Saurabhkmr98 <saurabhkapur73@gmail.com>
Co-authored-by: Saurabh Kumar <70131915+Saurabhkmr98@users.noreply.github.com>

* add fuzzy find in state and priority mapping (#2310)

Co-authored-by: Saurabhkmr98 <saurabhkapur73@gmail.com>
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>

* fix: build

* chore: moved flatfile agent to external

* chore:build-fixes

* fix: credential breaking for slack

* fix: credential route for api

* SILO - chore: Importers translation (#2352)

* add en translations for importers and jira importer

* add en translations for all the importers

* add importers language translation changes

* chore silo importer translation

* chore silo importer translation

* fix: env removing trailing slashes

* fix: trailing slashed env

* fix duplicate entity connection issue (#2362)

---------

Co-authored-by: Henit Chobisa <chobisa.henit@gmail.com>
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
2025-01-31 20:18:17 +05:30

278 lines
9.1 KiB
TypeScript

/* eslint-disable no-useless-catch */
import set from "lodash/set";
import unset from "lodash/unset";
import { action, computed, makeObservable, observable, runInAction } from "mobx";
import { computedFn } from "mobx-utils";
import { API_BASE_URL, SILO_BASE_PATH, SILO_BASE_URL } from "@plane/constants";
import { GithubAuthorizeState, GithubUserAuthState } from "@plane/etl/github";
// plane web services
import { GithubAuthService } from "@/plane-web/services/integrations/github";
// plane web store
import { IGithubStore } from "@/plane-web/store/integrations";
// plane web types
import { TGithubWorkspaceConnection, TGithubWorkspaceUserConnection } from "@/plane-web/types/integrations";
export interface IGithubAuthStore {
// observables
workspaceConnectionMap: Record<string, Record<string, TGithubWorkspaceConnection>>; // workspaceId -> organizationId -> TGithubWorkspaceConnection
githubUserCredentialsMap: Record<string, Record<string, TGithubWorkspaceUserConnection>>; // workspaceId -> userId -> TGithubWorkspaceUserConnection
// computed
workspaceConnectionIds: string[];
githubUserCredentialIds: string[];
// computed functions
workspaceConnectionById: (organizationId: string) => TGithubWorkspaceConnection | undefined;
githubUserCredentialById: (userId: string) => TGithubWorkspaceUserConnection | undefined;
// actions
fetchWorkspaceConnection: () => Promise<TGithubWorkspaceConnection[] | undefined>;
connectWorkspaceConnection: () => Promise<string | undefined>;
disconnectWorkspaceConnection: () => Promise<void>;
fetchGithubUserCredential: (
workspace_id?: string,
user_id?: string
) => Promise<TGithubWorkspaceUserConnection | undefined>;
connectGithubUserCredential: (
workspace_id?: string,
workspace_slug?: string,
user_id?: string,
profileRedirect?: boolean
) => Promise<string | undefined>;
disconnectGithubUserCredential: (workspace_id?: string, user_id?: string) => Promise<void>;
}
export class GithubAuthStore implements IGithubAuthStore {
// observables
workspaceConnectionMap: Record<string, Record<string, TGithubWorkspaceConnection>> = {}; // workspaceId -> organizationId -> TGithubWorkspaceConnection
githubUserCredentialsMap: Record<string, Record<string, TGithubWorkspaceUserConnection>> = {}; // workspaceId -> userId -> TGithubWorkspaceUserConnection
// service
private service: GithubAuthService;
constructor(protected store: IGithubStore) {
makeObservable(this, {
// observables
workspaceConnectionMap: observable,
githubUserCredentialsMap: observable,
// computed
workspaceConnectionIds: computed,
githubUserCredentialIds: computed,
// actions
fetchWorkspaceConnection: action,
connectWorkspaceConnection: action,
disconnectWorkspaceConnection: action,
fetchGithubUserCredential: action,
connectGithubUserCredential: action,
disconnectGithubUserCredential: action,
});
this.service = new GithubAuthService(encodeURI(SILO_BASE_URL + SILO_BASE_PATH));
}
// computed
/**
* @description get organization ids
* @returns { string[] }
*/
get workspaceConnectionIds(): string[] {
const workspaceId = this.store.workspace?.id;
if (!workspaceId || !this.workspaceConnectionMap[workspaceId]) return [];
return Object.keys(this.workspaceConnectionMap[workspaceId]) || [];
}
/**
* @description get user ids
* @returns { string[] }
*/
get githubUserCredentialIds(): string[] {
const workspaceId = this.store.workspace?.id;
if (!workspaceId || !this.githubUserCredentialsMap[workspaceId]) return [];
return Object.keys(this.githubUserCredentialsMap[workspaceId]) || [];
}
// computed functions
/**
* @description get github organization by id
* @param { string } organizationId
* @returns { object | undefined }
*/
workspaceConnectionById = computedFn((organizationId: string) => {
const workspaceId = this.store.workspace?.id;
if (!workspaceId) return undefined;
return this.workspaceConnectionMap[workspaceId][organizationId] || undefined;
});
/**
* @description get github user by id
* @param { string } userId
* @returns { object | undefined }
*/
githubUserCredentialById = computedFn((userId: string) => {
const workspaceId = this.store.workspace?.id;
if (!workspaceId) return undefined;
return this.githubUserCredentialsMap[workspaceId][userId] || undefined;
});
// actions
/**
* @description fetch github organization
* @returns { Promise<TGithubWorkspaceConnection[] | undefined> }
*/
fetchWorkspaceConnection = async (): Promise<TGithubWorkspaceConnection[] | undefined> => {
try {
const workspaceId = this.store.workspace?.id;
if (!workspaceId) return undefined;
const response = await this.service.fetchOrganizationConnection(workspaceId);
if (response) {
runInAction(() => {
response.forEach((data) => {
if (data.id) set(this.workspaceConnectionMap, [workspaceId, data.id], data);
});
});
}
return response;
} catch (error) {
throw error;
}
};
/**
* @description connect github organization
* @returns { Promise<string | undefined> }
*/
connectWorkspaceConnection = async (): Promise<string | undefined> => {
try {
const workspaceId = this.store.workspace?.id;
const workspaceSlug = this.store.workspace?.slug;
const externalApiToken = this.store.externalApiToken;
const targetHostname = API_BASE_URL;
const userId = this.store.user?.id;
if (!workspaceId || !workspaceSlug || !externalApiToken || !userId) return undefined;
const payload: GithubAuthorizeState = {
workspace_id: workspaceId,
workspace_slug: workspaceSlug,
plane_api_token: externalApiToken,
target_host: targetHostname,
user_id: userId,
};
const response = await this.service.connectOrganization(payload);
await this.store.fetchWebhookConnection(`${SILO_BASE_PATH}/api/github/plane-webhook`);
return response;
} catch (error) {
throw error;
}
};
/**
* @description disconnect github organization
* @returns { Promise<void> }
*/
disconnectWorkspaceConnection = async (): Promise<void> => {
try {
const workspaceId = this.store.workspace?.id;
const organizationId = this.workspaceConnectionIds[0] || undefined;
if (!workspaceId || !organizationId) return undefined;
const organization = this.workspaceConnectionById(organizationId) || undefined;
const connectionId = organization?.connection_id || undefined;
if (!connectionId) return undefined;
await this.service.disconnectOrganization(workspaceId, connectionId);
runInAction(() => unset(this.workspaceConnectionMap, [workspaceId]));
return undefined;
} catch (error) {
throw error;
}
};
/**
* @description fetch github user
* @returns { Promise<TGithubWorkspaceUserConnection | undefined> }
*/
fetchGithubUserCredential = async (
workspace_id?: string,
user_id?: string
): Promise<TGithubWorkspaceUserConnection | undefined> => {
try {
const workspaceId = workspace_id ?? this.store.workspace?.id;
const userId = user_id ?? this.store.user?.id;
if (!workspaceId || !userId) return undefined;
const response = await this.service.fetchUserConnection(workspaceId, userId);
if (response) {
runInAction(() => {
if (response) set(this.githubUserCredentialsMap, [workspaceId, userId], response);
});
}
return response;
} catch (error) {
throw error;
}
};
/**
* @description connect github user
* @returns { Promise<string | undefined> }
*/
connectGithubUserCredential = async (
workspace_id?: string,
workspace_slug?: string,
user_id?: string,
profileRedirect?: boolean
): Promise<string | undefined> => {
try {
const workspaceId = workspace_id ?? this.store.workspace?.id;
const workspaceSlug = workspace_slug ?? this.store.workspace?.slug;
const userId = user_id ?? this.store.user?.id;
const targetHostname = API_BASE_URL;
if (!workspaceId || !workspaceSlug || !userId) return undefined;
const payload: GithubUserAuthState = {
workspace_id: workspaceId,
workspace_slug: workspaceSlug,
profile_redirect: profileRedirect,
user_id: userId,
target_host: targetHostname,
};
const response = await this.service.connectUser(payload);
return response;
} catch (error) {
throw error;
}
};
/**
* @description disconnect github user
* @returns { Promise<void> }
*/
disconnectGithubUserCredential = async (workspace_id?: string, user_id?: string): Promise<void> => {
try {
const workspaceId = workspace_id ?? this.store.workspace?.id;
const userId = user_id ?? this.store.user?.id;
if (!workspaceId || !userId) return undefined;
await this.service.disconnectUser(workspaceId, userId);
runInAction(() => unset(this.githubUserCredentialsMap, [workspaceId]));
return undefined;
} catch (error) {
throw error;
}
};
}