Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ services:
- ./angular.json:/app/angular.json
- ./tsconfig.json:/app/tsconfig.json
- ./tsconfig.app.json:/app/tsconfig.app.json
- ./docker/scripts:/app/docker
# (CMD comes from Dockerfile, but you could override here if you wanted)
command: ['npm', 'run', 'start:docker']

Expand Down
13 changes: 13 additions & 0 deletions docker/scripts/check-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const fs = require('fs');
const path = require('path');
const { config } = require('process');

const configPath = path.join(__dirname, '../src/assets/config/config.json');
const templatePath = path.join(__dirname, '../src/assets/config/template.json');

if (!fs.existsSync(configPath)) {
console.log('[INFO] config.json not found. Copying from template.json...');
fs.copyFileSync(templatePath, configPath);
} else {
console.log('[INFO] config.json already exists.');
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"ng": "ng",
"analyze-bundle": "ng build --configuration=analyze-bundle && source-map-explorer dist/**/*.js --no-border-checks",
"build": "ng build",
"check:config": "node ./docker/check-config.js",
"ci:test": "jest",
"ci:test:coverage": "jest --coverage",
"docs": "./node_modules/.bin/compodoc -p tsconfig.docs.json --name 'OSF Angular Documentation' --theme 'laravel' -s",
Expand All @@ -19,8 +20,8 @@
"prepare": "husky",
"start": "ng serve",
"start:test": "ng serve --configuration test-osf",
"start:docker": "ng serve --host 0.0.0.0 --port 4200 --poll 2000",
"start:docker:local": "ng serve --host 0.0.0.0 --port 4200 --poll 2000 --configuration local",
"start:docker": "npm run check:config && ng serve --host 0.0.0.0 --port 4200 --poll 2000",
"start:docker:local": "npm run check:config && ng serve --host 0.0.0.0 --port 4200 --poll 2000 --configuration local",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage && npm run test:display",
Expand Down
16 changes: 16 additions & 0 deletions src/app/core/models/config.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ export interface ConfigModel {
*/
googleTagManagerId: string;

/**
* API Key used to load the Google Picker API.
* This key should be restricted in the Google Cloud Console to limit usage.
*
* @example "AIzaSyA...your_api_key"
*/
googleFilePickerApiKey: string;

/**
* Google Cloud Project App ID used by the Google Picker SDK.
* This numeric ID identifies your Google project and is required for some configurations.
*
* @example 123456789012
*/
googleFilePickerAppId: number;

/**
* A catch-all for additional configuration keys not explicitly defined.
* Each dynamic property maps to a `ConfigModelType` value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Observable, of, throwError } from 'rxjs';
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { SENTRY_TOKEN } from '@core/factory/sentry.factory';
import { OSFConfigService } from '@core/services/osf-config.service';

import { GoogleFilePickerDownloadService } from './service/google-file-picker.download.service';
import { GoogleFilePickerComponent } from './google-file-picker.component';
Expand All @@ -24,6 +25,17 @@ describe('Component: Google File Picker', () => {
}),
};

const OSFConfigServiceProvider = {
provide: OSFConfigService,
useValue: {
get: (key: string) => {
if (key === 'googleFilePickerApiKey') return 'test-api-key';
if (key === 'googleFilePickerAppId') return 'test-app-id';
return null;
},
},
};

let sentrySpy: any;

let throwLoadScriptError = false;
Expand Down Expand Up @@ -111,6 +123,7 @@ describe('Component: Google File Picker', () => {
provide: Store,
useValue: storeMock,
},
OSFConfigServiceProvider,
],
}).compileComponents();

Expand Down Expand Up @@ -232,6 +245,7 @@ describe('Component: Google File Picker', () => {
provide: Store,
useValue: storeMock,
},
OSFConfigServiceProvider,
],
}).compileComponents();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Button } from 'primeng/button';

import { ChangeDetectionStrategy, Component, inject, input, OnInit, signal } from '@angular/core';

import { ENVIRONMENT } from '@core/constants/environment.token';
import { SENTRY_TOKEN } from '@core/factory/sentry.factory';
import { OSFConfigService } from '@core/services/osf-config.service';
import { StorageItemModel } from '@osf/shared/models';
import { GoogleFileDataModel } from '@osf/shared/models/files/google-file.data.model';
import { GoogleFilePickerModel } from '@osf/shared/models/files/google-file.picker.model';
Expand All @@ -26,9 +26,9 @@ import { GoogleFilePickerDownloadService } from './service/google-file-picker.do
})
export class GoogleFilePickerComponent implements OnInit {
private readonly Sentry = inject(SENTRY_TOKEN);
private configService = inject(OSFConfigService);
readonly #translateService = inject(TranslateService);
readonly #googlePicker = inject(GoogleFilePickerDownloadService);
readonly #environment = inject(ENVIRONMENT);

public isFolderPicker = input.required<boolean>();
public rootFolder = input<StorageItemModel | null>(null);
Expand All @@ -39,8 +39,8 @@ export class GoogleFilePickerComponent implements OnInit {
public accessToken = signal<string | null>(null);
public visible = signal(false);
public isGFPDisabled = signal(true);
private readonly apiKey = this.#environment.google?.GOOGLE_FILE_PICKER_API_KEY ?? '';
private readonly appId = this.#environment.google?.GOOGLE_FILE_PICKER_APP_ID ?? 0;
private readonly apiKey = this.configService.get('googleFilePickerApiKey');
private readonly appId = this.configService.get('googleFilePickerAppId');

private readonly store = inject(Store);
private parentId = '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,10 @@ export class StorageItemSelectorComponent implements OnInit {
this.cancelSelection.emit();
}

handleFolderSelection(folder: StorageItem): void {
handleFolderSelection = (folder: StorageItem): void => {
this.selectedStorageItem.set(folder);
this.hasFolderChanged.set(folder?.itemId !== this.initiallySelectedStorageItem()?.itemId);
}
};

private updateBreadcrumbs(
operationName: OperationNames,
Expand Down
6 changes: 0 additions & 6 deletions src/app/shared/models/environment.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ export interface AppEnvironment {
dataciteTrackerRepoId: string | null;
dataciteTrackerAddress: string;

google?: {
GOOGLE_FILE_PICKER_CLIENT_ID: string;
GOOGLE_FILE_PICKER_API_KEY: string;
GOOGLE_FILE_PICKER_APP_ID: number;
};

activityLogs?: {
pageSize?: number;
};
Expand Down
4 changes: 3 additions & 1 deletion src/assets/config/template.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"sentryDsn": "",
"googleTagManagerId": ""
"googleTagManagerId": "",
"googleFilePickerApiKey": "",
"googleFilePickerAppId": 0
}
25 changes: 0 additions & 25 deletions src/environments/environment.development.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,29 +56,4 @@ export const environment = {
defaultProvider: 'osf',
dataciteTrackerRepoId: null,
dataciteTrackerAddress: 'https://analytics.datacite.org/api/metric',
/**
* Google File Picker configuration values.
*/
google: {
/**
* OAuth 2.0 Client ID used to identify the application during Google authentication.
* Registered in Google Cloud Console under "OAuth 2.0 Client IDs".
* Safe to expose in frontend code.
* @see https://console.cloud.google.com/apis/credentials
*/
GOOGLE_FILE_PICKER_CLIENT_ID: '610901277352-m5krehjdtu8skh2teq85fb7mvk411qa6.apps.googleusercontent.com',
/**
* Public API key used to load Google Picker and other Google APIs that don’t require user auth.
* Must be restricted by referrer in Google Cloud Console.
* Exposing this key is acceptable if restricted properly.
* @see https://developers.google.com/maps/api-key-best-practices
*/
GOOGLE_FILE_PICKER_API_KEY: 'AIzaSyA3EnD0pOv4v7sJt7BGuR1i2Gcj-Gju6C0',
/**
* Google Cloud Project App ID.
* Used for associating API requests with the specific Google project.
* Required for Google Picker configuration.
*/
GOOGLE_FILE_PICKER_APP_ID: 610901277352,
},
};
22 changes: 0 additions & 22 deletions src/environments/environment.local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,4 @@ export const environment = {
defaultProvider: 'osf',
dataciteTrackerRepoId: null,
dataciteTrackerAddress: 'https://analytics.datacite.org/api/metric',
google: {
/**
* OAuth 2.0 Client ID used to identify the application during Google authentication.
* Registered in Google Cloud Console under "OAuth 2.0 Client IDs".
* Safe to expose in frontend code.
* @see https://console.cloud.google.com/apis/credentials
*/
GOOGLE_FILE_PICKER_CLIENT_ID: '610901277352-m5krehjdtu8skh2teq85fb7mvk411qa6.apps.googleusercontent.com',
/**
* Public API key used to load Google Picker and other Google APIs that don’t require user auth.
* Must be restricted by referrer in Google Cloud Console.
* Exposing this key is acceptable if restricted properly.
* @see https://developers.google.com/maps/api-key-best-practices
*/
GOOGLE_FILE_PICKER_API_KEY: 'AIzaSyA3EnD0pOv4v7sJt7BGuR1i2Gcj-Gju6C0',
/**
* Google Cloud Project App ID.
* Used for associating API requests with the specific Google project.
* Required for Google Picker configuration.
*/
GOOGLE_FILE_PICKER_APP_ID: 610901277352,
},
};
5 changes: 0 additions & 5 deletions src/environments/environment.test-osf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,4 @@ export const environment = {
defaultProvider: 'osf',
dataciteTrackerRepoId: null,
dataciteTrackerAddress: 'https://analytics.datacite.org/api/metric',
google: {
GOOGLE_FILE_PICKER_CLIENT_ID: '610901277352-m5krehjdtu8skh2teq85fb7mvk411qa6.apps.googleusercontent.com',
GOOGLE_FILE_PICKER_API_KEY: 'AIzaSyA3EnD0pOv4v7sJt7BGuR1i2Gcj-Gju6C0',
GOOGLE_FILE_PICKER_APP_ID: 610901277352,
},
};
9 changes: 0 additions & 9 deletions src/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,4 @@ export const environment = {
defaultProvider: 'osf',
dataciteTrackerRepoId: null,
dataciteTrackerAddress: 'https://analytics.datacite.org/api/metric',

/**
* Google File Picker configuration values.
*/
google: {
GOOGLE_FILE_PICKER_CLIENT_ID: '610901277352-m5krehjdtu8skh2teq85fb7mvk411qa6.apps.googleusercontent.com',
GOOGLE_FILE_PICKER_API_KEY: 'AIzaSyA3EnD0pOv4v7sJt7BGuR1i2Gcj-Gju6C0',
GOOGLE_FILE_PICKER_APP_ID: 610901277352,
},
};
4 changes: 0 additions & 4 deletions src/testing/mocks/environment.token.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,5 @@ export const EnvironmentTokenMock = {
provide: ENVIRONMENT,
useValue: {
production: false,
google: {
GOOGLE_FILE_PICKER_API_KEY: 'test-api-key',
GOOGLE_FILE_PICKER_APP_ID: 'test-app-id',
},
},
};