Skip to content

Commit

Permalink
Add drive object for one-drive integration
Browse files Browse the repository at this point in the history
  • Loading branch information
amuwal committed Sep 5, 2024
1 parent c60e5e3 commit 7e91440
Show file tree
Hide file tree
Showing 11 changed files with 428 additions and 41 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ LINEAR_TICKETING_CLOUD_CLIENT_SECRET=
# Box
BOX_FILESTORAGE_CLOUD_CLIENT_ID=
BOX_FILESTORAGE_CLOUD_CLIENT_SECRET=
# Onedrive
ONEDRIVE_FILESTORAGE_CLOUD_CLIENT_ID=
ONEDRIVE_FILESTORAGE_CLOUD_CLIENT_SECRET=


# ================================================
Expand Down
49 changes: 23 additions & 26 deletions packages/api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -1321,32 +1321,29 @@ model connections {
}

model connector_sets {
id_connector_set String @id(map: "pk_project_connector") @db.Uuid
crm_hubspot Boolean?
crm_zoho Boolean?
crm_attio Boolean?
crm_pipedrive Boolean?
tcg_zendesk Boolean?
tcg_jira Boolean?
tcg_gorgias Boolean?
tcg_gitlab Boolean?
tcg_front Boolean?
crm_zendesk Boolean?
crm_close Boolean?
fs_box Boolean?
tcg_github Boolean?
hris_gusto Boolean?
hris_deel Boolean?
hris_sage Boolean?
ecom_woocommerce Boolean?
ecom_shopify Boolean?
ecom_amazon Boolean?
ecom_squarespace Boolean?
tcg_linear Boolean?
ats_ashby Boolean?
ecom_webflow Boolean?
crm_microsoftdynamicssales Boolean?
projects projects[]
id_connector_set String @id(map: "pk_project_connector") @db.Uuid
crm_hubspot Boolean?
crm_zoho Boolean?
crm_attio Boolean?
crm_pipedrive Boolean?
tcg_zendesk Boolean?
tcg_jira Boolean?
tcg_gorgias Boolean?
tcg_gitlab Boolean?
tcg_front Boolean?
crm_zendesk Boolean?
crm_close Boolean?
fs_box Boolean?
tcg_github Boolean?
hris_gusto Boolean?
hris_deel Boolean?
hris_sage Boolean?
ecom_woocommerce Boolean?
ecom_shopify Boolean?
ecom_amazon Boolean?
ecom_squarespace Boolean?
ats_ashby Boolean?
projects projects[]
}

/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { OnedriveDriveInput, OnedriveDriveOutput } from '@filestorage/drive/services/onedrive/types';

/* INPUT */

import {
Expand Down Expand Up @@ -30,7 +32,7 @@ export type OriginalPermissionInput = any;
export type OriginalSharedLinkInput = any;

/* drive */
export type OriginalDriveInput = any;
export type OriginalDriveInput = any | OnedriveDriveInput;

/* group */
export type OriginalGroupInput = BoxGroupInput;
Expand Down Expand Up @@ -62,7 +64,7 @@ export type OriginalPermissionOutput = any;
export type OriginalSharedLinkOutput = any;

/* drive */
export type OriginalDriveOutput = any;
export type OriginalDriveOutput = any | OnedriveDriveOutput;

/* group */
export type OriginalGroupOutput = BoxGroupOutput;
Expand Down
4 changes: 4 additions & 0 deletions packages/api/src/filestorage/drive/drive.module.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { OnedriveDriveMapper } from './services/onedrive/mappers';
import { OnedriveService } from './services/onedrive';
import { BullQueueModule } from '@@core/@core-services/queues/queue.module';
import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service';
import { Module } from '@nestjs/common';
Expand All @@ -17,6 +19,8 @@ import { Utils } from '@filestorage/@lib/@utils';
ServiceRegistry,
Utils,
/* PROVIDERS SERVICES */
OnedriveService,
OnedriveDriveMapper,
],
exports: [SyncService],
})
Expand Down
70 changes: 70 additions & 0 deletions packages/api/src/filestorage/drive/services/onedrive/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
import { ApiResponse } from '@@core/utils/types';
import { SyncParam } from '@@core/utils/types/interface';
import { FileStorageObject } from '@filestorage/@lib/@types';
import { IDriveService } from '@filestorage/drive/types';
import { Injectable } from '@nestjs/common';
import axios from 'axios';
import { ServiceRegistry } from '../registry.service';
import { OnedriveDriveOutput } from './types';
import { DesunifyReturnType } from '@@core/utils/types/desunify.input';
import { OriginalDriveOutput } from '@@core/utils/types/original/original.file-storage';

@Injectable()
export class OnedriveService implements IDriveService {
constructor(
private prisma: PrismaService,
private logger: LoggerService,
private cryptoService: EncryptionService,
private registry: ServiceRegistry,
) {
this.logger.setContext(
`${FileStorageObject.file.toUpperCase()}:${OnedriveService.name}`,
);
this.registry.registerService('onedrive', this);
}

async addDrive(
driveData: DesunifyReturnType,
linkedUserId: string,
): Promise<ApiResponse<OriginalDriveOutput>> {
// No API to add drive in onedrive
return;
}

async sync(data: SyncParam): Promise<ApiResponse<OnedriveDriveOutput[]>> {
try {
const { linkedUserId } = data;

const connection = await this.prisma.connections.findFirst({
where: {
id_linked_user: linkedUserId,
provider_slug: 'onedrive',
vertical: 'filestorage',
},
});

const resp = await axios.get(`${connection.account_url}/v1.0/drives`, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.cryptoService.decrypt(
connection.access_token,
)}`,
},
});

const drives: OnedriveDriveOutput[] = resp.data.value;
this.logger.log(`Synced onedrive drives !`);

return {
data: drives,
message: 'Onedrive drive retrived',
statusCode: 200,
};
} catch (error) {
throw error;
}
}
}
86 changes: 86 additions & 0 deletions packages/api/src/filestorage/drive/services/onedrive/mappers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
import { Utils } from '@filestorage/@lib/@utils';
import {
UnifiedFilestorageDriveInput,
UnifiedFilestorageDriveOutput,
} from '@filestorage/drive/types/model.unified';
import { Injectable } from '@nestjs/common';
import { OnedriveDriveInput, OnedriveDriveOutput } from './types';
import { IDriveMapper } from '@filestorage/drive/types';

@Injectable()
export class OnedriveDriveMapper implements IDriveMapper {
constructor(
private mappersRegistry: MappersRegistry,
private utils: Utils,
private coreUnificationService: CoreUnification,
) {
this.mappersRegistry.registerService(
'filestorage',
'drive',
'onedrive',
this,
);
}

async desunify(
source: UnifiedFilestorageDriveInput,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): Promise<OnedriveDriveInput> {
return;
}

async unify(
source: OnedriveDriveOutput | OnedriveDriveOutput[],
connectionId: string,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): Promise<UnifiedFilestorageDriveOutput | UnifiedFilestorageDriveOutput[]> {
if (!Array.isArray(source)) {
return await this.mapSingleDriveToUnified(
source,
connectionId,
customFieldMappings,
);
}
// Handling array of OnedriveDriveOutput
return Promise.all(
source.map((drive) =>
this.mapSingleDriveToUnified(drive, connectionId, customFieldMappings),
),
);
}

private async mapSingleDriveToUnified(
drive: OnedriveDriveOutput,
connectionId: string,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): Promise<UnifiedFilestorageDriveOutput> {
const field_mappings: { [key: string]: any } = {};
if (customFieldMappings) {
for (const mapping of customFieldMappings) {
field_mappings[mapping.slug] = drive[mapping.remote_id];
}
}

const result: UnifiedFilestorageDriveOutput = {
remote_id: drive.id,
remote_data: drive,
name: drive.name,
remote_created_at: drive.createdDateTime,
drive_url: drive.webUrl,
field_mappings,
};

return result;
}
}
130 changes: 130 additions & 0 deletions packages/api/src/filestorage/drive/services/onedrive/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/**
* Represents the response from the OneDrive API for a specific drive.
* @see https://learn.microsoft.com/en-us/graph/api/resources/drive?view=graph-rest-1.0
*/
export interface OnedriveDriveOutput {
/** The date and time when the drive was created. */
readonly createdDateTime: string;
/** A user-visible description of the drive. */
description: string;
/** The unique identifier of the drive. */
readonly id: string;
/** The date and time when the drive was last modified. */
readonly lastModifiedDateTime: string;
/** The name of the drive. */
name: string;
/** URL that displays the resource in the browser. */
readonly webUrl: string;
/** Describes the type of drive represented by this resource. */
readonly driveType: 'personal' | 'business' | 'documentLibrary';
/** Identity of the user, device, or application which created the item. Read-only. */
readonly createdBy: IdentitySet;
/** Identity of the user, device, and application which last modified the item. Read-only. */
readonly lastModifiedBy: IdentitySet;
/** The user account that owns the drive. */
readonly owner?: IdentitySet;
/** Information about the drive's storage space quota. */
readonly quota?: Quota;
/** SharePoint identifiers for REST compatibility. */
readonly sharepointIds?: SharepointIds;
/** Indicates that this is a system-managed drive. */
readonly system?: SystemFacet;
}

/**
* Represents a set of identities, such as user, device, or application identities.
* @see https://learn.microsoft.com/en-us/graph/api/resources/identityset?view=graph-rest-1.0
*/
export interface IdentitySet {
/** Identity representing an application. */
readonly application?: Identity;
/** Identity representing an application instance. */
readonly applicationInstance?: Identity;
/** Identity representing a conversation. */
readonly conversation?: Identity;
/** Identity representing a conversation identity type. */
readonly conversationIdentityType?: Identity;
/** Identity representing a device. */
readonly device?: Identity;
/** Identity representing encrypted identity information. */
readonly encrypted?: Identity;
/** Identity representing an on-premises identity. */
readonly onPremises?: Identity;
/** Identity representing a guest user. */
readonly guest?: Identity;
/** Identity representing a phone identity. */
readonly phone?: Identity;
/** Identity representing a user. */
readonly user?: Identity;
}

/**
* Represents a generic identity used in various identity sets.
* @see https://learn.microsoft.com/en-us/graph/api/resources/identity?view=graph-rest-1.0
*/
export interface Identity {
/** The display name of the identity. */
readonly displayName?: string;
/** The ID of the identity. */
readonly id?: string;
/** The identity type (such as user, application, or device). */
readonly identityType?: string;
/** The email address of the identity. */
readonly email?: string;
}

/**
* Represents the storage quota information of a drive.
*/
export interface Quota {
/** The total number of bytes deleted from the drive. */
readonly deleted: number;
/** The total number of bytes remaining in the drive's quota. */
readonly remaining: number;
/** The state of the drive's quota (e.g., normal, nearing, exceeded). */
readonly state: 'normal' | 'nearing' | 'critical' | 'exceeded';
/** The total number of bytes in the drive's quota. */
readonly total: number;
/** The total number of bytes used in the drive. */
readonly used: number;
/** Information about storage plan upgrades, if available. */
readonly storagePlanInformation?: StoragePlanInformation;
}

/**
* Represents storage plan upgrade information.
*/
export interface StoragePlanInformation {
/** Indicates whether an upgrade is available for the storage plan. */
readonly upgradeAvailable: boolean;
}

/**
* Represents SharePoint-specific identifiers for an item.
*/
export interface SharepointIds {
/** The unique identifier (GUID) for the item's list in SharePoint. */
readonly listId: string;
/** An integer identifier for the item within the containing list. */
readonly listItemId: string;
/** The unique identifier (GUID) for the item within OneDrive for Business or a SharePoint site. */
readonly listItemUniqueId: string;
/** The unique identifier (GUID) for the item's site collection (SPSite). */
readonly siteId: string;
/** The SharePoint URL for the site that contains the item. */
readonly siteUrl: string;
/** The unique identifier (GUID) for the tenancy. */
readonly tenantId: string;
/** The unique identifier (GUID) for the item's site (SPWeb). */
readonly webId: string;
}

/**
* Represents system-related metadata for the drive.
*/
export interface SystemFacet {
// Add properties specific to the system facet if needed.
readonly [key: string]: any;
}

export type OnedriveDriveInput = Partial<OnedriveDriveOutput>;
Loading

0 comments on commit 7e91440

Please sign in to comment.