Skip to content

Commit

Permalink
feat: onedrive: setup group-user mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
amuwal committed Dec 21, 2024
1 parent 1159ed9 commit 6d13386
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 6 deletions.
2 changes: 1 addition & 1 deletion packages/api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ model fs_drives {
model fs_groups {
id_fs_group String @id(map: "pk_fs_groups") @db.Uuid
name String?
users String[]
users String[] @db.Uuid
remote_id String?
remote_was_deleted Boolean
created_at DateTime @db.Timestamptz(6)
Expand Down
2 changes: 1 addition & 1 deletion packages/api/scripts/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ CREATE TABLE fs_groups
(
id_fs_group uuid NOT NULL,
name text NULL,
users text[] NULL,
users uuid[] NULL,
remote_id text NULL,
remote_was_deleted boolean NOT NULL,
created_at timestamp with time zone NOT NULL,
Expand Down
4 changes: 2 additions & 2 deletions packages/api/src/@core/sync/sync.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,12 +412,12 @@ export class CoreSyncService {
async handleFileStorageSync(provider: string, linkedUserId: string) {
const tasks = [
() =>
this.registry.getService('filestorage', 'group').syncForLinkedUser({
this.registry.getService('filestorage', 'user').syncForLinkedUser({
integrationId: provider,
linkedUserId: linkedUserId,
}),
() =>
this.registry.getService('filestorage', 'user').syncForLinkedUser({
this.registry.getService('filestorage', 'group').syncForLinkedUser({
integrationId: provider,
linkedUserId: linkedUserId,
}),
Expand Down
56 changes: 55 additions & 1 deletion packages/api/src/filestorage/group/services/onedrive/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Injectable } from '@nestjs/common';
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { ServiceRegistry } from '../registry.service';
import { OnedriveGroupOutput } from './types';
import { connections } from '@prisma/client';

@Injectable()
export class OnedriveService implements IGroupService {
Expand Down Expand Up @@ -58,7 +59,8 @@ export class OnedriveService implements IGroupService {
const resp: AxiosResponse = await this.makeRequestWithRetry(config);

const groups: OnedriveGroupOutput[] = resp.data.value;
this.logger.log(`Synced OneDrive groups successfully.`);
await this.assignUsersForGroups(groups, connection);
this.logger.log(`Synced ${groups.length} OneDrive groups successfully.`);

return {
data: groups,
Expand All @@ -74,6 +76,58 @@ export class OnedriveService implements IGroupService {
}
}

private async assignUsersForGroups(
groups: OnedriveGroupOutput[],
connection: connections,
) {
const userLookupCache: Map<string, string> = new Map();

for (const group of groups) {
const users = await this.fetchUsersForGroup(group, connection);
const internalUsers = await Promise.all(
users.map(async (user) => {
if (userLookupCache.has(user.id)) {
return userLookupCache.get(user.id);
}
const internalUser = await this.prisma.fs_users.findFirst({
where: {
remote_id: user.id,
},
select: {
id_fs_user: true,
},
});
userLookupCache.set(user.id, internalUser?.id_fs_user || null);
return internalUser?.id_fs_user || null;
}),
);
group.internal_users = internalUsers.filter(
(user) => user !== null,
) as string[];
}
}

private async fetchUsersForGroup(
group: OnedriveGroupOutput,
connection: connections,
) {
const config: AxiosRequestConfig = {
timeout: 10000,
method: 'get',
url: `${connection.account_url}/v1.0/groups/${group.id}/members`,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.cryptoService.decrypt(
connection.access_token,
)}`,
},
};

const resp: AxiosResponse = await this.makeRequestWithRetry(config);

return resp.data.value;
}

/**
* Makes an HTTP request with retry logic for handling 500 and 429 errors.
* @param config - Axios request configuration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export class OnedriveGroupMapper implements IGroupMapper {
name: group.displayName || group.mailNickname,
remote_was_deleted: group.deletedDateTime !== null,
field_mappings,
users: [],
users: group.internal_users || [],
};
}
}
6 changes: 6 additions & 0 deletions packages/api/src/filestorage/group/services/onedrive/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ export interface OnedriveGroupInput {
* /groups?$filter=startsWith(displayName,'Role')&amp;$select=id,displayName&amp;$expand=owners($select=id,userPrincipalName,displayName).
*/
owners?: DirectoryObject[];

// INTERNAL
/**
* Internal UUIDs of users that are members of this group.
*/
internal_users?: string[];
}

/**
Expand Down
6 changes: 6 additions & 0 deletions packages/api/swagger/swagger-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,12 @@ paths:
responses:
'200':
description: Pull frequency updated successfully
'201':
description: ''
content:
application/json:
schema:
type: object
tags: *ref_5
x-speakeasy-group: sync
get:
Expand Down

0 comments on commit 6d13386

Please sign in to comment.