52a62f2b8d
UI to accompany the new ACLs APIs
200 lines
6.5 KiB
JavaScript
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;
|
|
},
|
|
});
|