summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts')
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts264
1 files changed, 264 insertions, 0 deletions
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts
new file mode 100644
index 000000000..1d5aede39
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts
@@ -0,0 +1,264 @@
+import { Component, OnInit } from '@angular/core';
+import { Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import _ from 'lodash';
+import { forkJoin } from 'rxjs';
+
+import { RgwBucketService } from '~/app/shared/api/rgw-bucket.service';
+import { RgwSiteService } from '~/app/shared/api/rgw-site.service';
+import { RgwUserService } from '~/app/shared/api/rgw-user.service';
+import { ActionLabelsI18n, URLVerbs } from '~/app/shared/constants/app.constants';
+import { Icons } from '~/app/shared/enum/icons.enum';
+import { NotificationType } from '~/app/shared/enum/notification-type.enum';
+import { CdForm } from '~/app/shared/forms/cd-form';
+import { CdFormBuilder } from '~/app/shared/forms/cd-form-builder';
+import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
+import { CdValidators } from '~/app/shared/forms/cd-validators';
+import { NotificationService } from '~/app/shared/services/notification.service';
+import { RgwBucketMfaDelete } from '../models/rgw-bucket-mfa-delete';
+import { RgwBucketVersioning } from '../models/rgw-bucket-versioning';
+
+@Component({
+ selector: 'cd-rgw-bucket-form',
+ templateUrl: './rgw-bucket-form.component.html',
+ styleUrls: ['./rgw-bucket-form.component.scss']
+})
+export class RgwBucketFormComponent extends CdForm implements OnInit {
+ bucketForm: CdFormGroup;
+ editing = false;
+ owners: string[] = null;
+ action: string;
+ resource: string;
+ zonegroup: string;
+ placementTargets: object[] = [];
+ isVersioningAlreadyEnabled = false;
+ isMfaDeleteAlreadyEnabled = false;
+ icons = Icons;
+
+ get isVersioningEnabled(): boolean {
+ return this.bucketForm.getValue('versioning');
+ }
+ get isMfaDeleteEnabled(): boolean {
+ return this.bucketForm.getValue('mfa-delete');
+ }
+
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ private formBuilder: CdFormBuilder,
+ private rgwBucketService: RgwBucketService,
+ private rgwSiteService: RgwSiteService,
+ private rgwUserService: RgwUserService,
+ private notificationService: NotificationService,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ super();
+ this.editing = this.router.url.startsWith(`/rgw/bucket/${URLVerbs.EDIT}`);
+ this.action = this.editing ? this.actionLabels.EDIT : this.actionLabels.CREATE;
+ this.resource = $localize`bucket`;
+ this.createForm();
+ }
+
+ createForm() {
+ const self = this;
+ const lockDaysValidator = CdValidators.custom('lockDays', () => {
+ if (!self.bucketForm || !_.get(self.bucketForm.getRawValue(), 'lock_enabled')) {
+ return false;
+ }
+ const lockDays = Number(self.bucketForm.getValue('lock_retention_period_days'));
+ return !Number.isInteger(lockDays) || lockDays === 0;
+ });
+ this.bucketForm = this.formBuilder.group({
+ id: [null],
+ bid: [
+ null,
+ [Validators.required],
+ this.editing
+ ? []
+ : [CdValidators.bucketName(), CdValidators.bucketExistence(false, this.rgwBucketService)]
+ ],
+ owner: [null, [Validators.required]],
+ 'placement-target': [null, this.editing ? [] : [Validators.required]],
+ versioning: [null],
+ 'mfa-delete': [null],
+ 'mfa-token-serial': [''],
+ 'mfa-token-pin': [''],
+ lock_enabled: [{ value: false, disabled: this.editing }],
+ lock_mode: ['COMPLIANCE'],
+ lock_retention_period_days: [0, [CdValidators.number(false), lockDaysValidator]]
+ });
+ }
+
+ ngOnInit() {
+ const promises = {
+ owners: this.rgwUserService.enumerate()
+ };
+
+ if (!this.editing) {
+ promises['getPlacementTargets'] = this.rgwSiteService.get('placement-targets');
+ }
+
+ // Process route parameters.
+ this.route.params.subscribe((params: { bid: string }) => {
+ if (params.hasOwnProperty('bid')) {
+ const bid = decodeURIComponent(params.bid);
+ promises['getBid'] = this.rgwBucketService.get(bid);
+ }
+
+ forkJoin(promises).subscribe((data: any) => {
+ // Get the list of possible owners.
+ this.owners = (<string[]>data.owners).sort();
+
+ // Get placement targets:
+ if (data['getPlacementTargets']) {
+ const placementTargets = data['getPlacementTargets'];
+ this.zonegroup = placementTargets['zonegroup'];
+ _.forEach(placementTargets['placement_targets'], (placementTarget) => {
+ placementTarget['description'] = `${placementTarget['name']} (${$localize`pool`}: ${
+ placementTarget['data_pool']
+ })`;
+ this.placementTargets.push(placementTarget);
+ });
+
+ // If there is only 1 placement target, select it by default:
+ if (this.placementTargets.length === 1) {
+ this.bucketForm.get('placement-target').setValue(this.placementTargets[0]['name']);
+ }
+ }
+
+ if (data['getBid']) {
+ const bidResp = data['getBid'];
+ // Get the default values (incl. the values from disabled fields).
+ const defaults = _.clone(this.bucketForm.getRawValue());
+
+ // Get the values displayed in the form. We need to do that to
+ // extract those key/value pairs from the response data, otherwise
+ // the Angular react framework will throw an error if there is no
+ // field for a given key.
+ let value: object = _.pick(bidResp, _.keys(defaults));
+ value['lock_retention_period_days'] = this.rgwBucketService.getLockDays(bidResp);
+ value['placement-target'] = bidResp['placement_rule'];
+ value['versioning'] = bidResp['versioning'] === RgwBucketVersioning.ENABLED;
+ value['mfa-delete'] = bidResp['mfa_delete'] === RgwBucketMfaDelete.ENABLED;
+
+ // Append default values.
+ value = _.merge(defaults, value);
+
+ // Update the form.
+ this.bucketForm.setValue(value);
+ if (this.editing) {
+ this.isVersioningAlreadyEnabled = this.isVersioningEnabled;
+ this.isMfaDeleteAlreadyEnabled = this.isMfaDeleteEnabled;
+ this.setMfaDeleteValidators();
+ if (value['lock_enabled']) {
+ this.bucketForm.controls['versioning'].disable();
+ }
+ }
+ }
+
+ this.loadingReady();
+ });
+ });
+ }
+
+ goToListView() {
+ this.router.navigate(['/rgw/bucket']);
+ }
+
+ submit() {
+ // Exit immediately if the form isn't dirty.
+ if (this.bucketForm.pristine) {
+ this.goToListView();
+ return;
+ }
+ const values = this.bucketForm.value;
+ if (this.editing) {
+ // Edit
+ const versioning = this.getVersioningStatus();
+ const mfaDelete = this.getMfaDeleteStatus();
+ this.rgwBucketService
+ .update(
+ values['bid'],
+ values['id'],
+ values['owner'],
+ versioning,
+ mfaDelete,
+ values['mfa-token-serial'],
+ values['mfa-token-pin'],
+ values['lock_mode'],
+ values['lock_retention_period_days']
+ )
+ .subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ $localize`Updated Object Gateway bucket '${values.bid}'.`
+ );
+ this.goToListView();
+ },
+ () => {
+ // Reset the 'Submit' button.
+ this.bucketForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ } else {
+ // Add
+ this.rgwBucketService
+ .create(
+ values['bid'],
+ values['owner'],
+ this.zonegroup,
+ values['placement-target'],
+ values['lock_enabled'],
+ values['lock_mode'],
+ values['lock_retention_period_days']
+ )
+ .subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ $localize`Created Object Gateway bucket '${values.bid}'`
+ );
+ this.goToListView();
+ },
+ () => {
+ // Reset the 'Submit' button.
+ this.bucketForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ }
+ }
+
+ areMfaCredentialsRequired() {
+ return (
+ this.isMfaDeleteEnabled !== this.isMfaDeleteAlreadyEnabled ||
+ (this.isMfaDeleteAlreadyEnabled &&
+ this.isVersioningEnabled !== this.isVersioningAlreadyEnabled)
+ );
+ }
+
+ setMfaDeleteValidators() {
+ const mfaTokenSerialControl = this.bucketForm.get('mfa-token-serial');
+ const mfaTokenPinControl = this.bucketForm.get('mfa-token-pin');
+
+ if (this.areMfaCredentialsRequired()) {
+ mfaTokenSerialControl.setValidators(Validators.required);
+ mfaTokenPinControl.setValidators(Validators.required);
+ } else {
+ mfaTokenSerialControl.setValidators(null);
+ mfaTokenPinControl.setValidators(null);
+ }
+
+ mfaTokenSerialControl.updateValueAndValidity();
+ mfaTokenPinControl.updateValueAndValidity();
+ }
+
+ getVersioningStatus() {
+ return this.isVersioningEnabled ? RgwBucketVersioning.ENABLED : RgwBucketVersioning.SUSPENDED;
+ }
+
+ getMfaDeleteStatus() {
+ return this.isMfaDeleteEnabled ? RgwBucketMfaDelete.ENABLED : RgwBucketMfaDelete.DISABLED;
+ }
+}