consul/ui-v2/app/adapters/token.js

200 lines
6.5 KiB
JavaScript

import { inject as service } from '@ember/service';
import Adapter, {
REQUEST_CREATE,
REQUEST_UPDATE,
DATACENTER_QUERY_PARAM as API_DATACENTER_KEY,
} from './application';
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/token';
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
import { PUT as HTTP_PUT } from 'consul-ui/utils/http/method';
import { get } from '@ember/object';
const REQUEST_CLONE = 'cloneRecord';
const REQUEST_SELF = 'querySelf';
export default Adapter.extend({
store: service('store'),
cleanQuery: function(_query) {
const query = this._super(...arguments);
// TODO: Make sure policy is being passed through
delete _query.policy;
// take off the secret for /self
delete query.secret;
return query;
},
urlForQuery: function(query, modelName) {
return this.appendURL('acl/tokens', [], this.cleanQuery(query));
},
urlForQueryRecord: function(query, modelName) {
if (typeof query.id === 'undefined') {
throw new Error('You must specify an id');
}
return this.appendURL('acl/token', [query.id], this.cleanQuery(query));
},
urlForQuerySelf: function(query, modelName) {
return this.appendURL('acl/token/self', [], this.cleanQuery(query));
},
urlForCreateRecord: function(modelName, snapshot) {
return this.appendURL('acl/token', [], {
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
});
},
urlForUpdateRecord: function(id, modelName, snapshot) {
// If a token has Rules, use the old API
if (typeof snapshot.attr('Rules') !== 'undefined') {
return this.appendURL('acl/update', [], {
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
});
}
return this.appendURL('acl/token', [snapshot.attr(SLUG_KEY)], {
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
});
},
urlForDeleteRecord: function(id, modelName, snapshot) {
return this.appendURL('acl/token', [snapshot.attr(SLUG_KEY)], {
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
});
},
urlForRequest: function({ type, snapshot, requestType }) {
switch (requestType) {
case 'cloneRecord':
return this.urlForCloneRecord(type.modelName, snapshot);
case 'querySelf':
return this.urlForQuerySelf(snapshot, type.modelName);
}
return this._super(...arguments);
},
urlForCloneRecord: function(modelName, snapshot) {
return this.appendURL('acl/token', [snapshot.attr(SLUG_KEY), 'clone'], {
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
});
},
self: function(store, modelClass, snapshot) {
const params = {
store: store,
type: modelClass,
snapshot: snapshot,
requestType: 'querySelf',
};
// _requestFor is private... but these methods aren't, until they disappear..
const request = {
method: this.methodForRequest(params),
url: this.urlForRequest(params),
headers: this.headersForRequest(params),
data: this.dataForRequest(params),
};
// TODO: private..
return this._makeRequest(request);
},
clone: function(store, modelClass, id, snapshot) {
const params = {
store: store,
type: modelClass,
id: id,
snapshot: snapshot,
requestType: 'cloneRecord',
};
// _requestFor is private... but these methods aren't, until they disappear..
const request = {
method: this.methodForRequest(params),
url: this.urlForRequest(params),
headers: this.headersForRequest(params),
data: this.dataForRequest(params),
};
// TODO: private..
return this._makeRequest(request);
},
handleSingleResponse: function(url, response, primary, slug) {
// Sometimes we get `Policies: null`, make null equal an empty array
if (typeof response.Policies === 'undefined' || response.Policies === null) {
response.Policies = [];
}
// Convert an old style update response to a new style
if (typeof response['ID'] !== 'undefined') {
const item = get(this, 'store')
.peekAll('token')
.findBy('SecretID', response['ID']);
if (item) {
response['SecretID'] = response['ID'];
response['AccessorID'] = get(item, 'AccessorID');
}
}
return this._super(url, response, primary, slug);
},
handleResponse: function(status, headers, payload, requestData) {
let response = payload;
if (status === HTTP_OK) {
const url = this.parseURL(requestData.url);
switch (true) {
case response === true:
response = this.handleBooleanResponse(url, response, PRIMARY_KEY, SLUG_KEY);
break;
case Array.isArray(response):
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
break;
default:
response = this.handleSingleResponse(url, response, PRIMARY_KEY, SLUG_KEY);
}
}
return this._super(status, headers, response, requestData);
},
methodForRequest: function(params) {
switch (params.requestType) {
case REQUEST_CLONE:
case REQUEST_CREATE:
return HTTP_PUT;
}
return this._super(...arguments);
},
headersForRequest: function(params) {
switch (params.requestType) {
case REQUEST_SELF:
return {
'X-Consul-Token': params.snapshot.secret,
};
}
return this._super(...arguments);
},
dataForRequest: function(params) {
let data = this._super(...arguments);
switch (params.requestType) {
case REQUEST_UPDATE:
// If a token has Rules, use the old API
if (typeof data.token['Rules'] !== 'undefined') {
data.token['ID'] = data.token['SecretID'];
data.token['Name'] = data.token['Description'];
}
// falls through
case REQUEST_CREATE:
if (Array.isArray(data.token.Policies)) {
data.token.Policies = data.token.Policies.filter(function(item) {
// Just incase, don't save any policies that aren't saved
return !get(item, 'isNew');
}).map(function(item) {
return {
ID: get(item, 'ID'),
Name: get(item, 'Name'),
};
});
} else {
delete data.token.Policies;
}
data = data.token;
break;
case REQUEST_SELF:
return {};
case REQUEST_CLONE:
data = {};
break;
}
// make sure we never send the SecretID
if (data && typeof data['SecretID'] !== 'undefined') {
delete data['SecretID'];
}
return data;
},
});