Skip to content

Commit

Permalink
NAS-133621 / 25.04 / Bring back One Drive (#11357)
Browse files Browse the repository at this point in the history
  • Loading branch information
undsoft authored Jan 20, 2025
1 parent 362cac6 commit c2e5fbc
Show file tree
Hide file tree
Showing 96 changed files with 709 additions and 3 deletions.
8 changes: 8 additions & 0 deletions src/app/enums/cloudsync-provider.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export enum CloudSyncProviderName {
Hubic = 'HUBIC',
Mega = 'MEGA',
MicrosoftAzure = 'AZUREBLOB',
MicrosoftOneDrive = 'ONEDRIVE',
OpenstackSwift = 'OPENSTACK_SWIFT',
Pcloud = 'PCLOUD',
Sftp = 'SFTP',
Expand All @@ -21,6 +22,12 @@ export enum CloudSyncProviderName {
Yandex = 'YANDEX',
}

export enum OneDriveType {
Personal = 'PERSONAL',
Business = 'BUSINESS',
DocumentLibrary = 'DOCUMENT_LIBRARY',
}

export const cloudSyncProviderNameMap = new Map<CloudSyncProviderName, string>([
[CloudSyncProviderName.AmazonS3, T('Amazon S3')],
[CloudSyncProviderName.BackblazeB2, T('Backblaze B2')],
Expand All @@ -34,6 +41,7 @@ export const cloudSyncProviderNameMap = new Map<CloudSyncProviderName, string>([
[CloudSyncProviderName.Http, T('HTTP')],
[CloudSyncProviderName.Mega, T('Mega')],
[CloudSyncProviderName.MicrosoftAzure, T('Microsoft Azure')],
[CloudSyncProviderName.MicrosoftOneDrive, T('Microsoft OneDrive')],
[CloudSyncProviderName.OpenstackSwift, T('OpenStack Swift')],
[CloudSyncProviderName.Pcloud, T('pCloud')],
[CloudSyncProviderName.Sftp, T('SFTP')],
Expand Down
3 changes: 2 additions & 1 deletion src/app/interfaces/api/api-call-directory.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import {
CloudSyncBucket,
CloudSyncCredential,
CloudSyncCredentialUpdate,
CloudSyncCredentialVerify, CloudSyncCredentialVerifyResult,
CloudSyncCredentialVerify, CloudSyncCredentialVerifyResult, CloudSyncOneDriveDrive, CloudSyncOneDriveParams,
} from 'app/interfaces/cloudsync-credential.interface';
import { CloudSyncProvider, CloudSyncRestoreParams } from 'app/interfaces/cloudsync-provider.interface';
import {
Expand Down Expand Up @@ -406,6 +406,7 @@ export interface ApiCallDirectory {
'cloudsync.delete': { params: [id: number]; response: boolean };
'cloudsync.list_buckets': { params: [id: number]; response: CloudSyncBucket[] };
'cloudsync.list_directory': { params: [CloudSyncListDirectoryParams]; response: CloudSyncDirectoryListing[] };
'cloudsync.onedrive_list_drives': { params: [CloudSyncOneDriveParams]; response: CloudSyncOneDriveDrive[] };
'cloudsync.providers': { params: void; response: CloudSyncProvider[] };
'cloudsync.query': { params: QueryParams<CloudSyncTask>; response: CloudSyncTask[] };
'cloudsync.restore': { params: CloudSyncRestoreParams; response: void };
Expand Down
15 changes: 14 additions & 1 deletion src/app/interfaces/cloudsync-credential.interface.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CloudSyncProviderName } from 'app/enums/cloudsync-provider.enum';
import { CloudSyncProviderName, OneDriveType } from 'app/enums/cloudsync-provider.enum';

export type SomeProviderAttributes = Record<string, string | number | boolean | string[] | number[] | boolean[]>;

Expand All @@ -25,3 +25,16 @@ export interface CloudSyncBucket {
Path: string;
Enabled: boolean;
}

export interface CloudSyncOneDriveDrive {
name: string;
description: string;
drive_type: OneDriveType;
drive_id: string;
}

export interface CloudSyncOneDriveParams {
client_id: string;
client_secret: string;
token: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
[queryParams]="{ userName: user.pw_name }"
[ixUiSearch]="searchableElements.elements.myApiKeys"
>
<ix-icon name="laptop"></ix-icon>
<ix-icon name="mdi-laptop"></ix-icon>
{{ 'My API Keys' | translate }}
</a>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<ix-oauth-provider-authentication
[oauthUrl]="provider.credentials_oauth"
(authenticated)="onOauthAuthenticated($event)"
></ix-oauth-provider-authentication>

<ix-fieldset [title]="'Authentication' | translate" [formGroup]="form">
<ix-input
formControlName="token"
type="password"
[label]="'Access Token' | translate"
[required]="true"
[tooltip]="helptext.token_onedrive.tooltip | translate"
></ix-input>

<ix-select
formControlName="drives"
[options]="drives$"
[label]="'Drives List' | translate"
[tooltip]="helptext.drives_onedrive.tooltip | translate"
></ix-select>

<ix-select
formControlName="drive_type"
[label]="'Drive Account Type' | translate"
[required]="true"
[options]="driveTypes$"
[tooltip]="helptext.drive_type_onedrive.tooltip | translate"
></ix-select>

<ix-input
formControlName="drive_id"
[label]="'Drive ID' | translate"
[required]="true"
[tooltip]="helptext.drive_id_onedrive.tooltip | translate"
></ix-input>
</ix-fieldset>
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ReactiveFormsModule } from '@angular/forms';
import { createComponentFactory, mockProvider, Spectator } from '@ngneat/spectator/jest';
import { mockApi, mockCall } from 'app/core/testing/utils/mock-api.utils';
import { OneDriveType } from 'app/enums/cloudsync-provider.enum';
import { CloudSyncProvider } from 'app/interfaces/cloudsync-provider.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
import { IxSelectHarness } from 'app/modules/forms/ix-forms/components/ix-select/ix-select.harness';
import { IxFormHarness } from 'app/modules/forms/ix-forms/testing/ix-form.harness';
import { ApiService } from 'app/modules/websocket/api.service';
import {
OauthProviderComponent,
} from 'app/pages/credentials/backup-credentials/cloud-credentials-form/oauth-provider/oauth-provider.component';
import {
OneDriveProviderFormComponent,
} from 'app/pages/credentials/backup-credentials/cloud-credentials-form/provider-forms/one-drive-provider-form/one-drive-provider-form.component';

describe('OneDriveProviderFormComponent', () => {
let spectator: Spectator<OneDriveProviderFormComponent>;
let form: IxFormHarness;
const createComponent = createComponentFactory({
component: OneDriveProviderFormComponent,
detectChanges: false,
imports: [
ReactiveFormsModule,
OauthProviderComponent,
],
providers: [
mockProvider(DialogService),
mockApi([
mockCall('cloudsync.onedrive_list_drives', [
{
drive_type: OneDriveType.Business,
drive_id: 'business1',
name: 'ODCMetadataArchive',
description: 'ODC Archived Metadata',
},
{
drive_type: OneDriveType.DocumentLibrary,
drive_id: 'library1',
name: 'OneDrive',
description: '',
},
]),
]),
],
});

beforeEach(async () => {
spectator = createComponent();
spectator.component.provider = {
credentials_oauth: 'http://truenas.com/oauth',
} as CloudSyncProvider;
spectator.detectChanges();
form = await TestbedHarnessEnvironment.harnessForFixture(spectator.fixture, IxFormHarness);
});

it('show existing provider attributes when they are set as form values', async () => {
spectator.component.getFormSetter$().next({
client_id: 'client',
client_secret: 'secret',
token: 'token',
drive_type: OneDriveType.Personal,
drive_id: 'driveid',
});

const values = await form.getValues();
expect(values).toEqual({
'OAuth Client ID': 'client',
'OAuth Client Secret': 'secret',

'Access Token': 'token',
'Drives List': '',
'Drive Account Type': 'PERSONAL',
'Drive ID': 'driveid',
});
});

it('loads a list of OneDrive drives and populates Drives List select when oAuth flow is completed', async () => {
const oauthComponent = spectator.query(OauthProviderComponent);
oauthComponent.form.setValue({
client_id: 'newclient',
client_secret: 'newsecret',
});
oauthComponent.authenticated.emit({
token: 'newtoken',
});

expect(spectator.inject(ApiService).call).toHaveBeenCalledWith('cloudsync.onedrive_list_drives', [{
client_id: 'newclient',
client_secret: 'newsecret',
token: 'newtoken',
}]);

const drivesSelect = await form.getControl('Drives List') as IxSelectHarness;
expect(await drivesSelect.getOptionLabels()).toEqual([
'--',
'ODCMetadataArchive - ODC Archived Metadata',
'OneDrive',
]);
});

it('updates Drive Account Type and ID when a drive is selected from Drives List', async () => {
const oauthComponent = spectator.query(OauthProviderComponent);
oauthComponent.form.setValue({
client_id: 'newclient',
client_secret: 'newsecret',
});
oauthComponent.authenticated.emit({
token: 'newtoken',
});

const drivesSelect = await form.getControl('Drives List') as IxSelectHarness;
await drivesSelect.setValue('ODCMetadataArchive - ODC Archived Metadata');

const values = spectator.component.getSubmitAttributes();
expect(values).toMatchObject({
drive_id: 'business1',
drive_type: OneDriveType.Business,
});
});

it('returns form attributes for submission when getSubmitAttributes() is called', async () => {
await form.fillForm({
'OAuth Client ID': 'newclient',
'OAuth Client Secret': 'newsecret',

'Access Token': 'newtoken',
'Drive Account Type': 'PERSONAL',
'Drive ID': 'driveid',
});

const values = spectator.component.getSubmitAttributes();
expect(values).toEqual({
client_id: 'newclient',
client_secret: 'newsecret',
token: 'newtoken',
drive_id: 'driveid',
drive_type: OneDriveType.Personal,
});
});
});
Loading

0 comments on commit c2e5fbc

Please sign in to comment.