2023-03-01 09:39:41 -06:00
|
|
|
/**
|
|
|
|
|
* Copyright (c) HashiCorp, Inc.
|
2024-05-31 11:29:24 -07:00
|
|
|
* SPDX-License-Identifier: BUSL-1.1
|
2023-03-01 09:39:41 -06:00
|
|
|
*/
|
|
|
|
|
|
2020-05-19 16:33:31 -04:00
|
|
|
import Model from '@ember-data/model';
|
2021-07-23 16:57:37 -04:00
|
|
|
import { attr } from '@ember-data/model';
|
2020-05-21 09:22:56 -04:00
|
|
|
import { computed } from '@ember/object';
|
2022-11-07 15:17:23 -08:00
|
|
|
import { inject as service } from '@ember/service';
|
2020-05-19 16:33:31 -04:00
|
|
|
|
2020-07-22 12:08:10 -04:00
|
|
|
/**
|
|
|
|
|
* Base model class provides common functionality for all models.
|
|
|
|
|
*
|
|
|
|
|
* One of the most interesting features of most resources is the
|
|
|
|
|
* `scope` field, which arrives from the API as an embedded JSON fragment.
|
|
|
|
|
* It contains information such as the parent scope ID and type. This scope ID
|
|
|
|
|
* is then used when generation scoped resource URLs via the
|
|
|
|
|
* `adapterOptions.scopeID` option (see `save` method below).
|
|
|
|
|
*
|
|
|
|
|
* For convenience, developers may interact with scope in a number of ways.
|
|
|
|
|
* The simplest method, when you don't care about other information, is to set
|
|
|
|
|
* the `scopeID`, e.g. `record.scopeID = 'o_123'`. The scope JSON fragment
|
|
|
|
|
* may be set directly, `record.scope = { scope_id: 'o_123' }`.
|
|
|
|
|
* For convenience, you may even set the scope using a `Scope` model:
|
|
|
|
|
* `record.scopeModel = scopeModelInstance`, which automatically converts the
|
|
|
|
|
* scope to a JSON fragment of the proper shape and assigns it to `scope`.
|
|
|
|
|
*
|
|
|
|
|
* A record's scope may be read in one of two ways:
|
|
|
|
|
*
|
|
|
|
|
* 1) As a JSON fragment: `record.scope`,
|
|
|
|
|
* 2) Or as an ID: `record.scopeID`.
|
|
|
|
|
*/
|
2020-05-21 09:22:56 -04:00
|
|
|
export default class BaseModel extends Model {
|
2022-11-07 15:17:23 -08:00
|
|
|
// =services
|
|
|
|
|
|
|
|
|
|
@service store;
|
|
|
|
|
|
2020-07-15 12:41:58 -04:00
|
|
|
// =relationships
|
|
|
|
|
|
|
|
|
|
/**
|
2020-07-22 11:47:33 -04:00
|
|
|
* Scope of this resource, if any, represented as a JSON fragment.
|
2020-07-15 12:41:58 -04:00
|
|
|
*/
|
2022-07-18 11:30:53 -07:00
|
|
|
@attr() scope;
|
2020-07-15 12:41:58 -04:00
|
|
|
|
2020-05-21 09:22:56 -04:00
|
|
|
// =attributes
|
|
|
|
|
|
2021-07-23 16:57:37 -04:00
|
|
|
@attr({
|
|
|
|
|
readOnly: true,
|
|
|
|
|
emptyArrayIfMissing: true,
|
2021-08-04 11:31:07 -04:00
|
|
|
})
|
|
|
|
|
authorized_actions;
|
2021-07-23 16:57:37 -04:00
|
|
|
|
2021-08-31 15:17:57 -07:00
|
|
|
@attr({
|
|
|
|
|
readOnly: true,
|
|
|
|
|
})
|
|
|
|
|
authorized_collection_actions;
|
|
|
|
|
|
2021-12-15 09:43:20 -05:00
|
|
|
get scopeModel() {
|
|
|
|
|
const id = this.scopeID;
|
2023-05-30 10:37:35 -07:00
|
|
|
return id ? this.store.peekRecord('scope', id) : null;
|
2021-12-15 09:43:20 -05:00
|
|
|
}
|
2022-12-06 14:29:58 -05:00
|
|
|
|
|
|
|
|
// Ember seems to have a bug with its internals and can't correctly set
|
|
|
|
|
// the `scopeModel` when passed in as part of the `inputProperties`
|
|
|
|
|
// of a `createRecord` call
|
2020-07-22 12:08:10 -04:00
|
|
|
set scopeModel(model) {
|
|
|
|
|
if (model) {
|
|
|
|
|
const json = model.serialize();
|
|
|
|
|
json.scope_id = model.id;
|
2022-07-18 11:30:53 -07:00
|
|
|
json.type = model.type;
|
|
|
|
|
json.isGlobal = model.isGlobal;
|
|
|
|
|
json.isOrg = model.isOrg;
|
|
|
|
|
json.isProject = model.isProject;
|
2020-07-22 12:08:10 -04:00
|
|
|
this.scope = json;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-22 11:47:33 -04:00
|
|
|
/**
|
|
|
|
|
* Convenience for getting and setting the parent scope ID.
|
2021-08-31 15:17:57 -07:00
|
|
|
* @type {string}
|
2020-07-22 11:47:33 -04:00
|
|
|
*/
|
|
|
|
|
@computed('scope.scope_id')
|
|
|
|
|
get scopeID() {
|
2020-10-06 10:31:00 -04:00
|
|
|
return this?.scope?.scope_id;
|
2020-07-22 11:47:33 -04:00
|
|
|
}
|
|
|
|
|
set scopeID(id) {
|
|
|
|
|
if (!this.scope) this.scope = {};
|
|
|
|
|
this.scope.scope_id = id;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-25 09:00:55 -04:00
|
|
|
/**
|
|
|
|
|
* Names are optional on models in our API. Thus we need to fallback on ID
|
|
|
|
|
* for display purposes.
|
|
|
|
|
* @type {string}
|
|
|
|
|
*/
|
|
|
|
|
@computed('name', 'id')
|
|
|
|
|
get displayName() {
|
|
|
|
|
return this.name || this.id;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-21 09:22:56 -04:00
|
|
|
/**
|
|
|
|
|
* @type {boolean}
|
|
|
|
|
*/
|
|
|
|
|
get canSave() {
|
|
|
|
|
return this.hasDirtyAttributes && !this.isSaving;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @type {boolean}
|
|
|
|
|
*/
|
|
|
|
|
get cannotSave() {
|
|
|
|
|
return !this.canSave;
|
|
|
|
|
}
|
|
|
|
|
}
|