diff --git a/connectors/src/connectors/microsoft/index.ts b/connectors/src/connectors/microsoft/index.ts index c5bd8c18842a..414c9d279a37 100644 --- a/connectors/src/connectors/microsoft/index.ts +++ b/connectors/src/connectors/microsoft/index.ts @@ -6,19 +6,55 @@ import type { NangoConnectionId, Result, } from "@dust-tt/types"; -import { Ok } from "@dust-tt/types"; +import { Err, Ok } from "@dust-tt/types"; +import { Client } from "@microsoft/microsoft-graph-client"; import type { ConnectorPermissionRetriever } from "@connectors/connectors/interface"; +import { microsoftConfig } from "@connectors/connectors/microsoft/lib/config"; +import { + getSites, + getTeams, +} from "@connectors/connectors/microsoft/lib/graph_api"; import { launchMicrosoftFullSyncWorkflow } from "@connectors/connectors/microsoft/temporal/client"; +import { getAccessTokenFromNango } from "@connectors/lib/nango_helpers"; import { syncSucceeded } from "@connectors/lib/sync_status"; +import logger from "@connectors/logger/logger"; import { ConnectorResource } from "@connectors/resources/connector_resource"; import type { DataSourceConfig } from "@connectors/types/data_source_config"; +async function getClient(connectionId: NangoConnectionId) { + const nangoConnectionId = connectionId; + + const msAccessToken = await getAccessTokenFromNango({ + connectionId: nangoConnectionId, + integrationId: microsoftConfig.getRequiredNangoMicrosoftConnectorId(), + useCache: false, + }); + + return Client.init({ + authProvider: (done) => done(null, msAccessToken), + }); +} + export async function createMicrosoftConnector( dataSourceConfig: DataSourceConfig, connectionId: NangoConnectionId -): Promise> { - console.log("createMicrosoftConnector", dataSourceConfig, connectionId); +) { + const client = await getClient(connectionId); + + try { + // Sanity checks - check connectivity and permissions. User should be able to access the sites and teams list. + await getSites(client); + await getTeams(client); + } catch (err) { + logger.error( + { + err, + }, + "Error creating Microsoft connector" + ); + return new Err(new Error("Error creating Microsoft connector")); + } const connector = await ConnectorResource.makeNew( "microsoft", diff --git a/connectors/src/connectors/microsoft/lib/config.ts b/connectors/src/connectors/microsoft/lib/config.ts new file mode 100644 index 000000000000..44dbda380659 --- /dev/null +++ b/connectors/src/connectors/microsoft/lib/config.ts @@ -0,0 +1,7 @@ +import { EnvironmentConfig } from "@dust-tt/types"; + +export const microsoftConfig = { + getRequiredNangoMicrosoftConnectorId: (): string => { + return EnvironmentConfig.getEnvVariable("NANGO_MICROSOFT_CONNECTOR_ID"); + }, +}; diff --git a/connectors/src/connectors/microsoft/lib/graph_api.ts b/connectors/src/connectors/microsoft/lib/graph_api.ts new file mode 100644 index 000000000000..6c449893e3e5 --- /dev/null +++ b/connectors/src/connectors/microsoft/lib/graph_api.ts @@ -0,0 +1,73 @@ +import type { Client } from "@microsoft/microsoft-graph-client"; +import type * as MicrosoftGraph from "@microsoft/microsoft-graph-types"; + +export async function getSites(client: Client): Promise { + const res = await client + .api("/sites?search=*") + .select("id,name,displayName") + .get(); + return res.value; +} + +export async function getDrives( + client: Client, + siteId: string +): Promise { + const res = await client + .api(`/sites/${siteId}/drives`) + .select("id,name") + .get(); + return res.value; +} + +export async function getFilesAndFolders( + client: Client, + driveId: string, + parentId?: string +): Promise { + const parent = parentId ? `items/${parentId}` : "root"; + const res = await client + .api(`/drives/${driveId}/${parent}/children`) + .select("id,displayName") + .get(); + return res.value; +} + +export async function getFolders( + client: Client, + driveId: string, + parentId?: string +): Promise { + const res = await getFilesAndFolders(client, driveId, parentId); + return res.filter((item) => item.folder); +} + +export async function getTeams(client: Client): Promise { + const res = await client + .api("/me/joinedTeams") + .select("id,displayName") + .get(); + return res.value; +} + +export async function getChannels( + client: Client, + teamId: string +): Promise { + const res = await client + .api(`/teams/${teamId}/channels`) + .select("id,displayName") + .get(); + return res.value; +} + +export async function getMessages( + client: Client, + teamId: string, + channelId: string +): Promise { + const res = await client + .api(`/teams/${teamId}/channels/${channelId}/messages`) + .get(); + return res.value; +}