mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-21 22:51:09 +02:00
* refactor crumbs * add subdirectory library route and hierarchical nav * update library breadcrumbs; * fix role popup menus * add getter to library model for full path * cleanup model getters * add changelog * add bug fix note * add transition after deleting * fix function definition * update adapter test * add test coverage * fix crumb typo
141 lines
5.4 KiB
JavaScript
141 lines
5.4 KiB
JavaScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import { Response } from 'miragejs';
|
|
|
|
export default function (server) {
|
|
const query = (req) => {
|
|
const { name, backend } = req.params;
|
|
return name ? { name } : { backend };
|
|
};
|
|
const getRecord = (schema, req, dbKey) => {
|
|
const record = schema.db[dbKey].findBy(query(req));
|
|
if (record) {
|
|
delete record.id;
|
|
delete record.name;
|
|
delete record.backend;
|
|
delete record.type;
|
|
return { data: record };
|
|
}
|
|
return new Response(404, {}, { errors: [] });
|
|
};
|
|
const createOrUpdateRecord = (schema, req, dbKey) => {
|
|
const data = JSON.parse(req.requestBody);
|
|
const dbCollection = schema.db[dbKey];
|
|
dbCollection.firstOrCreate(query(req), data);
|
|
dbCollection.update(query(req), data);
|
|
return new Response(204);
|
|
};
|
|
const listRecords = (schema, dbKey, query = {}) => {
|
|
const records = schema.db[dbKey].where(query);
|
|
const keys = records.map(({ name }) => {
|
|
if (name.includes('/')) {
|
|
const [parent, child] = name.split('/');
|
|
// query.name is only passed by listOrGetRecord and means we want to list children of admin/
|
|
// otherwise this is the request for all roles in an engine so we return the top-level paths
|
|
return query?.name ? child : `${parent}/`;
|
|
}
|
|
return name;
|
|
});
|
|
|
|
return {
|
|
data: { keys },
|
|
};
|
|
};
|
|
|
|
const listOrGetRecord = (schema, req, type) => {
|
|
const dbKey = type ? 'ldapRoles' : 'ldapLibraries';
|
|
const query = type ? { type, name: `admin/child-${type}-role` } : { name: 'admin/test-library' };
|
|
if (req.queryParams.list) {
|
|
// the mirage database has setup all hierarchical names to be prefixed with "admin/"
|
|
// while passing a query with specific name is not flexible, for simplicity
|
|
// we only seeded the mirage db with one hierarchical resource for each role and a library
|
|
return listRecords(schema, dbKey, query);
|
|
}
|
|
// otherwise we want to view details for a specific resource
|
|
return getRecord(schema, req, dbKey);
|
|
};
|
|
|
|
// config
|
|
server.post('/:backend/config', (schema, req) => createOrUpdateRecord(schema, req, 'ldapConfigs'));
|
|
server.get('/:backend/config', (schema, req) => getRecord(schema, req, 'ldapConfigs'));
|
|
// roles
|
|
server.post('/:backend/static-role/:name', (schema, req) => createOrUpdateRecord(schema, req, 'ldapRoles'));
|
|
server.post('/:backend/role/:name', (schema, req) => createOrUpdateRecord(schema, req, 'ldapRoles'));
|
|
// if the role is hierarchical the name ends in a forward slash so we make a list request
|
|
server.get('/:backend/static-role/*name', (schema, req) => listOrGetRecord(schema, req, 'static'));
|
|
server.get('/:backend/role/*name', (schema, req) => listOrGetRecord(schema, req, 'dynamic'));
|
|
|
|
server.get('/:backend/static-role', (schema) => listRecords(schema, 'ldapRoles', { type: 'static' }));
|
|
server.get('/:backend/role', (schema) => listRecords(schema, 'ldapRoles', { type: 'dynamic' }));
|
|
// role credentials
|
|
server.get('/:backend/static-cred/:name', (schema) => ({
|
|
data: schema.db.ldapCredentials.firstOrCreate({ type: 'static' }),
|
|
}));
|
|
server.get('/:backend/creds/:name', (schema) => ({
|
|
data: schema.db.ldapCredentials.firstOrCreate({ type: 'dynamic' }),
|
|
}));
|
|
// libraries
|
|
server.post('/:backend/library/:name', (schema, req) => createOrUpdateRecord(schema, req, 'ldapLibraries'));
|
|
server.get('/:backend/library/*name', (schema, req) => listOrGetRecord(schema, req));
|
|
server.get('/:backend/library', (schema) => listRecords(schema, 'ldapLibraries'));
|
|
server.get('/:backend/library/*name/status', (schema) => {
|
|
const data = schema.db['ldapAccountStatuses'].reduce((prev, curr) => {
|
|
prev[curr.account] = {
|
|
available: curr.available,
|
|
borrower_client_token: curr.borrower_client_token,
|
|
};
|
|
return prev;
|
|
}, {});
|
|
return { data };
|
|
});
|
|
// check-out / check-in
|
|
server.post('/:backend/library/:set_name/check-in', (schema, req) => {
|
|
// Check-in makes an unavailable account available again
|
|
const { service_account_names } = JSON.parse(req.requestBody);
|
|
const dbCollection = schema.db['ldapAccountStatuses'];
|
|
const updated = dbCollection.find(service_account_names).map((f) => ({
|
|
...f,
|
|
available: true,
|
|
borrower_client_token: undefined,
|
|
}));
|
|
updated.forEach((u) => {
|
|
dbCollection.update(u.id, u);
|
|
});
|
|
return {
|
|
data: {
|
|
check_ins: service_account_names,
|
|
},
|
|
};
|
|
});
|
|
server.post('/:backend/library/:set_name/check-out', (schema, req) => {
|
|
const { set_name, backend } = req.params;
|
|
const dbCollection = schema.db['ldapAccountStatuses'];
|
|
const available = dbCollection.where({ available: true });
|
|
if (available) {
|
|
return Response(404, {}, { errors: ['no accounts available to check out'] });
|
|
}
|
|
const checkOut = {
|
|
...available[0],
|
|
available: false,
|
|
borrower_client_token: crypto.randomUUID(),
|
|
};
|
|
dbCollection.update(checkOut.id, checkOut);
|
|
return {
|
|
request_id: '364a17d4-e5ab-998b-ceee-b49929229e0c',
|
|
lease_id: `${backend}/library/${set_name}/check-out/aoBsaBEI4PK96VnukubvYDlZ`,
|
|
renewable: true,
|
|
lease_duration: 36000,
|
|
data: {
|
|
password: crypto.randomUUID(),
|
|
service_account_name: checkOut.account,
|
|
},
|
|
wrap_info: null,
|
|
warnings: null,
|
|
auth: null,
|
|
};
|
|
});
|
|
}
|