vault/ui/app/adapters/named-path.js
hashicorp-copywrite[bot] 0b12cdcfd1
[COMPLIANCE] License changes (#22290)
* Adding explicit MPL license for sub-package.

This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository.

* Adding explicit MPL license for sub-package.

This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository.

* Updating the license from MPL to Business Source License.

Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at https://hashi.co/bsl-blog, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl.

* add missing license headers

* Update copyright file headers to BUS-1.1

* Fix test that expected exact offset on hcl file

---------

Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
Co-authored-by: Sarah Thompson <sthompson@hashicorp.com>
Co-authored-by: Brian Kassouf <bkassouf@hashicorp.com>
2023-08-10 18:14:03 -07:00

82 lines
3.4 KiB
JavaScript

/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
/**
* base adapter for resources that are saved to a path whose unique identifier is name
* save requests are made to the same endpoint and the resource is either created if not found or updated
* */
import ApplicationAdapter from './application';
import { assert } from '@ember/debug';
export default class NamedPathAdapter extends ApplicationAdapter {
namespace = 'v1';
saveMethod = 'POST'; // override when extending if PUT is used rather than POST
_saveRecord(store, { modelName }, snapshot) {
// since the response is empty return the serialized data rather than nothing
const data = store.serializerFor(modelName).serialize(snapshot);
return this.ajax(this.urlForUpdateRecord(snapshot.attr('name'), modelName, snapshot), this.saveMethod, {
data,
}).then(() => data);
}
// create does not return response similar to PUT request
createRecord() {
const [store, { modelName }, snapshot] = arguments;
const name = snapshot.attr('name');
// throw error if user attempts to create a record with same name, otherwise POST request silently overrides (updates) the existing model
if (store.hasRecordForId(modelName, name)) {
throw new Error(`A record already exists with the name: ${name}`);
} else {
return this._saveRecord(...arguments);
}
}
// update uses same endpoint and method as create
updateRecord() {
return this._saveRecord(...arguments);
}
// if backend does not return name in response Ember Data will throw an error for pushing a record with no id
// use the id (name) supplied to findRecord to set property on response data
findRecord(store, type, name) {
return super.findRecord(...arguments).then((resp) => {
if (!resp.data.name) {
resp.data.name = name;
}
return resp;
});
}
// GET request with list=true as query param
async query(store, type, query) {
const url = this.urlForQuery(query, type.modelName);
const { paramKey, filterFor, allowed_client_id } = query;
// * 'paramKey' is a string of the param name (model attr) we're filtering for, e.g. 'client_id'
// * 'filterFor' is an array of values to filter for (value type must match the attr type), e.g. array of ID strings
// * 'allowed_client_id' is a valid query param to the /provider endpoint
const queryParams = { list: true, ...(allowed_client_id && { allowed_client_id }) };
const response = await this.ajax(url, 'GET', { data: queryParams });
// filter LIST response only if key_info exists and query includes both 'paramKey' & 'filterFor'
if (filterFor) assert('filterFor must be an array', Array.isArray(filterFor));
if (response.data.key_info && filterFor && paramKey && !filterFor.includes('*')) {
const data = this.filterListResponse(paramKey, filterFor, response.data.key_info);
return { ...response, data };
}
return response;
}
filterListResponse(paramKey, matchValues, key_info) {
const keyInfoAsArray = Object.entries(key_info);
const filtered = keyInfoAsArray.filter((key) => {
const value = key[1]; // value is an object of model attributes
return matchValues.includes(value[paramKey]);
});
const filteredKeyInfo = Object.fromEntries(filtered);
const filteredKeys = Object.keys(filteredKeyInfo);
return { keys: filteredKeys, key_info: filteredKeyInfo };
}
}