Skip to content

Commit

Permalink
Merge pull request #7705 from ever-co/feat/storage-providers
Browse files Browse the repository at this point in the history
[Feat] Support DigitalOcean Spaces Storage
  • Loading branch information
evereq authored Mar 27, 2024
2 parents 1ec4e77 + 4f4ebb0 commit 6e55ac8
Show file tree
Hide file tree
Showing 28 changed files with 1,022 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ <h4>
*ngTemplateOutlet="cloudinaryStorageFormTemplate; context: { group: form }">
</ng-container>
</ng-container>
<ng-container *ngSwitchCase="FileStorageProviderEnum.DIGITALOCEAN">
<ng-container
*ngTemplateOutlet="digitalOceanStorageFormTemplate; context: { group: form }">
</ng-container>
</ng-container>
</ng-container>
</nb-card-body>
<nb-card-footer>
Expand Down Expand Up @@ -244,6 +249,17 @@ <h6>
/>
</div>
</div>
<div class="form-group row">
<label class="label col-3 col-xl-2" for="wasabi_aws_force_path_style">
{{ 'SETTINGS_FILE_STORAGE.WASABI.LABELS.FORCE_PATH_STYLE' | translate }}
</label>
<div class="col-9 col-xl-4">
<nb-toggle
formControlName="wasabi_aws_force_path_style"
status="primary"
></nb-toggle >
</div>
</div>
</nb-card-body>
</nb-card>
</ng-template>
Expand Down Expand Up @@ -358,3 +374,120 @@ <h6>
</nb-card-body>
</nb-card>
</ng-template>

<!-- DigitalOcean Storage Configuration Template -->
<ng-template #digitalOceanStorageFormTemplate let-group="group">
<nb-card [formGroup]="group">
<nb-card-header>
<h6>{{ 'SETTINGS_FILE_STORAGE.DIGITALOCEAN.HEADER' | translate }}</h6>
</nb-card-header>
<nb-card-body [formGroupName]="FileStorageProviderEnum.DIGITALOCEAN">
<div class="form-group row">
<label class="label col-3 col-xl-2" for="digitalocean_access_key_id">
{{ 'SETTINGS_FILE_STORAGE.DIGITALOCEAN.LABELS.ACCESS_KEY_ID' | translate }}
</label>
<div class="col-9 col-xl-4">
<input
name="digitalocean_access_key_id"
formControlName="digitalocean_access_key_id"
nbInput
fullWidth
class="w-100"
[placeholder]="'SETTINGS_FILE_STORAGE.DIGITALOCEAN.PLACEHOLDERS.ACCESS_KEY_ID' | translate"
/>
</div>
</div>
<div class="form-group row">
<label class="label col-3 col-xl-2" for="digitalocean_secret_access_key">
{{ 'SETTINGS_FILE_STORAGE.DIGITALOCEAN.LABELS.SECRET_ACCESS_KEY' | translate }}
</label>
<div class="col-9 col-xl-4">
<input
id="digitalocean_secret_access_key"
name="digitalocean_secret_access_key"
formControlName="digitalocean_secret_access_key"
nbInput
fullWidth
class="w-100"
[placeholder]="'SETTINGS_FILE_STORAGE.DIGITALOCEAN.PLACEHOLDERS.SECRET_ACCESS_KEY' | translate"
/>
</div>
</div>
<div class="form-group row">
<label class="label col-sm-3 col-xl-2" for="digitalocean_default_region">
{{ 'SETTINGS_FILE_STORAGE.DIGITALOCEAN.LABELS.REGION' | translate }}
</label>
<div class="col-sm-9 col-xl-4">
<input
id="digitalocean_default_region"
name="digitalocean_default_region"
formControlName="digitalocean_default_region"
nbInput
fullWidth
class="w-100"
[placeholder]="'SETTINGS_FILE_STORAGE.DIGITALOCEAN.PLACEHOLDERS.REGION' | translate"
/>
</div>
</div>
<div class="form-group row">
<label class="label col-3 col-xl-2" for="digitalocean_service_url">
{{ 'SETTINGS_FILE_STORAGE.DIGITALOCEAN.LABELS.SERVICE_URL' | translate }}
</label>
<div class="col-9 col-xl-4">
<input
id="digitalocean_service_url"
name="digitalocean_service_url"
formControlName="digitalocean_service_url"
nbInput
fullWidth
class="w-100"
[placeholder]="'SETTINGS_FILE_STORAGE.DIGITALOCEAN.PLACEHOLDERS.SERVICE_URL' | translate"
/>
</div>
</div>
<div class="form-group row">
<label class="label col-3 col-xl-2" for="digitalocean_cdn_url">
{{ 'SETTINGS_FILE_STORAGE.DIGITALOCEAN.LABELS.CDN_URL' | translate }}
</label>
<div class="col-9 col-xl-4">
<input
id="digitalocean_cdn_url"
name="digitalocean_cdn_url"
formControlName="digitalocean_cdn_url"
nbInput
fullWidth
class="w-100"
[placeholder]="'SETTINGS_FILE_STORAGE.DIGITALOCEAN.PLACEHOLDERS.CDN_URL' | translate"
/>
</div>
</div>
<div class="form-group row">
<label class="label col-3 col-xl-2" for="digitalocean_s3_bucket">
{{ 'SETTINGS_FILE_STORAGE.DIGITALOCEAN.LABELS.BUCKET' | translate }}
</label>
<div class="col-9 col-xl-4">
<input
id="digitalocean_s3_bucket"
name="digitalocean_s3_bucket"
formControlName="digitalocean_s3_bucket"
nbInput
fullWidth
class="w-100"
[placeholder]="'SETTINGS_FILE_STORAGE.DIGITALOCEAN.PLACEHOLDERS.BUCKET' | translate"
/>
</div>
</div>
<div class="form-group row">
<label class="label col-3 col-xl-2" for="digitalocean_s3_force_path_style">
{{ 'SETTINGS_FILE_STORAGE.DIGITALOCEAN.LABELS.FORCE_PATH_STYLE' | translate }}
</label>
<div class="col-9 col-xl-4">
<nb-toggle
formControlName="digitalocean_s3_force_path_style"
status="primary"
></nb-toggle >
</div>
</div>
</nb-card-body>
</nb-card>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,18 @@ export class FileStorageComponent extends TranslationBaseComponent
loading: boolean = false;

public readonly form: UntypedFormGroup = FileStorageComponent.buildForm(this.fb);

/**
*
* @param fb
* @returns
*/
static buildForm(fb: UntypedFormBuilder): UntypedFormGroup {
const defaultFileStorageProvider = environment.FILE_PROVIDER.toUpperCase() as FileStorageProviderEnum || FileStorageProviderEnum.LOCAL;

//
const form = fb.group({
fileStorageProvider: [
(environment.FILE_PROVIDER).toUpperCase() as FileStorageProviderEnum || FileStorageProviderEnum.LOCAL,
Validators.required
],
fileStorageProvider: [defaultFileStorageProvider, Validators.required],
// Aws Configuration
S3: fb.group({
aws_access_key_id: [],
Expand All @@ -50,7 +56,8 @@ export class FileStorageComponent extends TranslationBaseComponent
wasabi_aws_secret_access_key: [],
wasabi_aws_default_region: ['us-east-1'],
wasabi_aws_service_url: ['https://s3.wasabisys.com'],
wasabi_aws_bucket: ['gauzy']
wasabi_aws_bucket: ['gauzy'],
wasabi_aws_force_path_style: [false]
}),
// Cloudinary Configuration
CLOUDINARY: fb.group({
Expand All @@ -60,6 +67,16 @@ export class FileStorageComponent extends TranslationBaseComponent
cloudinary_api_secure: ['true'],
cloudinary_delivery_url: ['https://res.cloudinary.com']
}),
// DigitalOcean Configuration
DIGITALOCEAN: fb.group({
digitalocean_access_key_id: [],
digitalocean_secret_access_key: [],
digitalocean_default_region: [{ value: 'us-east-1', disabled: true }],
digitalocean_service_url: [],
digitalocean_cdn_url: [],
digitalocean_s3_bucket: ['gauzy'],
digitalocean_s3_force_path_style: [false]
}),
});
return form;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NbButtonModule, NbCardModule, NbInputModule, NbSelectModule, NbSpinnerModule } from '@nebular/theme';
import { NbButtonModule, NbCardModule, NbInputModule, NbSelectModule, NbSpinnerModule, NbToggleModule } from '@nebular/theme';
import { NgxPermissionsModule } from 'ngx-permissions';
import { FileProviderModule } from '../../../@shared/selectors/file-provider/file-provider.module';
import { SharedModule } from '../../../@shared/shared.module';
Expand All @@ -14,20 +14,21 @@ import { FileStorageComponent } from './file-storage.component';
FormsModule,
ReactiveFormsModule,
FileStorageRoutingModule,
ThemeModule,
TranslateModule,
SharedModule,
NgxPermissionsModule.forChild(),
NbButtonModule,
NbCardModule,
NbInputModule,
NbSelectModule,
NbSpinnerModule,
NbToggleModule,
NgxPermissionsModule.forChild(),
ThemeModule,
TranslateModule,
SharedModule,
FileProviderModule,
NbSpinnerModule
],
declarations: [
FileStorageComponent
],
providers: []
})
export class FileStorageModule {}
export class FileStorageModule { }
23 changes: 22 additions & 1 deletion apps/gauzy/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4445,7 +4445,8 @@
"SECRET_ACCESS_KEY": "Secret access key",
"REGION": "Region",
"BUCKET": "Bucket",
"SERVICE_URL": "Service URL"
"SERVICE_URL": "Service URL",
"FORCE_PATH_STYLE": "Force path style URLs"
},
"PLACEHOLDERS": {
"ACCESS_KEY_ID": "Access key id",
Expand All @@ -4471,6 +4472,26 @@
"DELIVERY_URL": "Delivery URL",
"SECURE": "Secure"
}
},
"DIGITALOCEAN": {
"HEADER": "DigitalOcean Configuration",
"LABELS": {
"ACCESS_KEY_ID": "Access key id",
"SECRET_ACCESS_KEY": "Secret access key",
"REGION": "Region",
"BUCKET": "Bucket",
"SERVICE_URL": "Service URL",
"CDN_URL": "CDN URL",
"FORCE_PATH_STYLE": "Force path style URLs"
},
"PLACEHOLDERS": {
"ACCESS_KEY_ID": "Access key id",
"SECRET_ACCESS_KEY": "Secret access key",
"REGION": "Region",
"BUCKET": "Bucket",
"SERVICE_URL": "Service URL",
"CDN_URL": "CDN URL"
}
}
},
"CUSTOM_SMTP_PAGE": {
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/interfaces/IAwsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export interface IAwsConfig {
region: string;
s3: {
bucket: string;
forcePathStyle: boolean;
};
}
21 changes: 21 additions & 0 deletions packages/common/src/interfaces/IDigitalOceanConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* DigitalOcean Spaces Configuration
*/
export interface IDigitalOceanConfig {
/** DigitalOcean Access Key ID */
readonly accessKeyId: string;
/** DigitalOcean Secret Access Key */
readonly secretAccessKey: string;
/** DigitalOcean Region */
readonly region: string;
/** DigitalOcean Service URL */
readonly serviceUrl: string;
/** The CDN (Content Delivery Network) DigitalOcean configuration. */
readonly cdnUrl?: string;
/** S3 Bucket Configuration */
readonly s3: {
/** S3 Bucket Name */
readonly bucket: string;
readonly forcePathStyle: boolean;
};
}
1 change: 1 addition & 0 deletions packages/common/src/interfaces/IWasabiConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ export interface IWasabiConfig {
readonly s3: {
/** S3 Bucket Name */
readonly bucket: string;
readonly forcePathStyle: boolean;
};
}
1 change: 1 addition & 0 deletions packages/common/src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export * from './ITwitterConfig';
export * from './IUnleashConfig';
export * from './IUpworkConfig';
export * from './IWasabiConfig';
export * from './IDigitalOceanConfig';
export * from './IHubstaffConfig';
export * from './IJitsuConfig';
export * from './IJiraIntegrationConfig';
21 changes: 19 additions & 2 deletions packages/config/src/environments/environment.prod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ export const environment: IEnvironment = {
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: process.env.AWS_REGION || 'us-east-1',
s3: {
bucket: process.env.AWS_S3_BUCKET || 'gauzy'
bucket: process.env.AWS_S3_BUCKET || 'gauzy',
forcePathStyle: process.env.AWS_S3_FORCE_PATH_STYLE === 'true' || false
}
},

Expand All @@ -92,7 +93,23 @@ export const environment: IEnvironment = {
region: process.env.WASABI_REGION || 'us-east-1',
serviceUrl: process.env.WASABI_SERVICE_URL || 'https://s3.wasabisys.com',
s3: {
bucket: process.env.WASABI_S3_BUCKET || 'gauzy'
bucket: process.env.WASABI_S3_BUCKET || 'gauzy',
forcePathStyle: process.env.WASABI_S3_FORCE_PATH_STYLE === 'true' || false
}
},

/**
* DigitalOcean Spaces Configuration
*/
digitalOcean: {
accessKeyId: process.env.DIGITALOCEAN_ACCESS_KEY_ID,
secretAccessKey: process.env.DIGITALOCEAN_SECRET_ACCESS_KEY,
region: process.env.DIGITALOCEAN_REGION || 'us-east-1',
serviceUrl: process.env.DIGITALOCEAN_SERVICE_URL || 'https://gauzy.sfo2.digitaloceanspaces.com', // Find your endpoint in the control panel, under Settings. Prepend "https://".
cdnUrl: process.env.DIGITALOCEAN_CDN_URL,
s3: {
bucket: process.env.DIGITALOCEAN_S3_BUCKET || 'gauzy',
forcePathStyle: process.env.DIGITALOCEAN_S3_FORCE_PATH_STYLE === 'true' || false // Configures to use subdomain/virtual calling format.
}
},

Expand Down
21 changes: 19 additions & 2 deletions packages/config/src/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ export const environment: IEnvironment = {
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: process.env.AWS_REGION || 'us-east-1',
s3: {
bucket: process.env.AWS_S3_BUCKET || 'gauzy'
bucket: process.env.AWS_S3_BUCKET || 'gauzy',
forcePathStyle: process.env.AWS_S3_FORCE_PATH_STYLE === 'true' || false
}
},

Expand All @@ -93,7 +94,23 @@ export const environment: IEnvironment = {
region: process.env.WASABI_REGION || 'us-east-1',
serviceUrl: process.env.WASABI_SERVICE_URL || 'https://s3.wasabisys.com',
s3: {
bucket: process.env.WASABI_S3_BUCKET || 'gauzy'
bucket: process.env.WASABI_S3_BUCKET || 'gauzy',
forcePathStyle: process.env.WASABI_S3_FORCE_PATH_STYLE === 'true' || false
}
},

/**
* DigitalOcean Spaces Configuration
*/
digitalOcean: {
accessKeyId: process.env.DIGITALOCEAN_ACCESS_KEY_ID,
secretAccessKey: process.env.DIGITALOCEAN_SECRET_ACCESS_KEY,
region: process.env.DIGITALOCEAN_REGION || 'us-east-1',
serviceUrl: process.env.DIGITALOCEAN_SERVICE_URL || 'https://gauzy.sfo2.digitaloceanspaces.com', // Find your endpoint in the control panel, under Settings. Prepend "https://".
cdnUrl: process.env.DIGITALOCEAN_CDN_URL,
s3: {
bucket: process.env.DIGITALOCEAN_S3_BUCKET || 'gauzy',
forcePathStyle: process.env.DIGITALOCEAN_S3_FORCE_PATH_STYLE === 'true' || false // Configures to use subdomain/virtual calling format.
}
},

Expand Down
Loading

0 comments on commit 6e55ac8

Please sign in to comment.