/** * 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, }; }); }