fix(striker-ui-api): migrate dbQuery->query in access module

main
Tsu-ba-me 2 years ago
parent 06ad2a5353
commit 32ecfec762
  1. 28
      striker-ui-api/src/app.ts
  2. 8
      striker-ui-api/src/index.ts
  3. 150
      striker-ui-api/src/lib/accessModule.ts
  4. 8
      striker-ui-api/src/lib/getSessionSecret.ts
  5. 51
      striker-ui-api/src/lib/request_handlers/buildGetRequestHandler.ts
  6. 93
      striker-ui-api/src/lib/request_handlers/command/getHostSSH.ts
  7. 21
      striker-ui-api/src/lib/request_handlers/manifest/getManifestTemplate.ts
  8. 143
      striker-ui-api/src/lib/request_handlers/server/createServer.ts
  9. 35
      striker-ui-api/src/lib/request_handlers/server/getServerDetail.ts
  10. 86
      striker-ui-api/src/routes/file.ts
  11. 15
      striker-ui-api/src/types/ApiCommand.d.ts

@ -7,25 +7,27 @@ import routes from './routes';
import { rrouters } from './lib/rrouters';
import session from './session';
const app = express();
export default (async () => {
const app = express();
app.use(json());
app.use(json());
app.use(cors());
app.use(cors());
// Add session handler to the chain **after** adding other handlers that do
// not depend on session(s).
app.use(session);
// Add session handler to the chain **after** adding other handlers that do
// not depend on session(s).
app.use(await session);
app.use(passport.initialize());
app.use(passport.authenticate('session'));
app.use(passport.initialize());
app.use(passport.authenticate('session'));
rrouters(app, routes.private, {
rrouters(app, routes.private, {
assign: (router) => [guardApi, router],
route: '/api',
});
rrouters(app, routes.public, { route: '/api' });
});
rrouters(app, routes.public, { route: '/api' });
app.use(routes.static);
app.use(routes.static);
export default app;
return app;
})();

@ -5,9 +5,10 @@ import { PGID, PUID, PORT, ECODE_DROP_PRIVILEGES } from './lib/consts';
import app from './app';
import { stderr, stdout } from './lib/shell';
stdout(`Starting process with ownership ${getuid()}:${getgid()}`);
(async () => {
stdout(`Starting process with ownership ${getuid()}:${getgid()}`);
app.listen(PORT, () => {
(await app).listen(PORT, () => {
try {
// Group must be set before user to avoid permission error.
setgid(PGID);
@ -21,4 +22,5 @@ app.listen(PORT, () => {
}
stdout(`Listening on localhost:${PORT}.`);
});
});
})();

@ -1,11 +1,144 @@
import { spawn, spawnSync, SpawnSyncOptions } from 'child_process';
import {
ChildProcess,
spawn,
SpawnOptions,
spawnSync,
SpawnSyncOptions,
} from 'child_process';
import EventEmitter from 'events';
import { readFileSync } from 'fs';
import { SERVER_PATHS } from './consts';
import { SERVER_PATHS, PGID, PUID } from './consts';
import { formatSql } from './formatSql';
import { isObject } from './isObject';
import { date, stderr as sherr, stdout as shout } from './shell';
import {
date,
stderr as sherr,
stdout as shout,
stdoutVar as shvar,
uuid,
} from './shell';
type AccessStartOptions = {
args?: readonly string[];
} & SpawnOptions;
class Access extends EventEmitter {
private ps: ChildProcess;
private queue: string[] = [];
constructor({
eventEmitterOptions = {},
spawnOptions = {},
}: {
eventEmitterOptions?: ConstructorParameters<typeof EventEmitter>[0];
spawnOptions?: SpawnOptions;
} = {}) {
super(eventEmitterOptions);
this.ps = this.start(spawnOptions);
}
private start({
args = [],
gid = PGID,
stdio = 'pipe',
timeout = 10000,
uid = PUID,
...restSpawnOptions
}: AccessStartOptions = {}) {
shvar({ gid, stdio, timeout, uid, ...restSpawnOptions });
const ps = spawn(SERVER_PATHS.usr.sbin['anvil-access-module'].self, args, {
gid,
stdio,
timeout,
uid,
...restSpawnOptions,
});
let stderr = '';
let stdout = '';
ps.stderr?.setEncoding('utf-8').on('data', (chunk: string) => {
stderr += chunk;
const scriptId = this.queue.at(0);
if (scriptId) {
sherr(`${Access.event(scriptId, 'stderr')}: ${stderr}`);
stderr = '';
}
});
ps.stdout?.setEncoding('utf-8').on('data', (chunk: string) => {
stdout += chunk;
let nindex: number = stdout.indexOf('\n');
// 1. ~a is the shorthand for -(a + 1)
// 2. negatives are evaluated to true
while (~nindex) {
const scriptId = this.queue.shift();
if (scriptId) this.emit(scriptId, stdout.substring(0, nindex));
stdout = stdout.substring(nindex + 1);
nindex = stdout.indexOf('\n');
}
});
return ps;
}
private stop() {
this.ps.once('error', () => !this.ps.killed && this.ps.kill('SIGKILL'));
this.ps.kill();
}
private restart(options?: AccessStartOptions) {
this.ps.once('close', () => this.start(options));
this.stop();
}
private static event(scriptId: string, category: 'stderr'): string {
return `${scriptId}-${category}`;
}
public interact<T>(command: string, ...args: string[]) {
const { stdin } = this.ps;
const scriptId = uuid();
const script = `${command} ${args.join(' ')}\n`;
const promise = new Promise<T>((resolve, reject) => {
this.once(scriptId, (data) => {
let result: T;
try {
result = JSON.parse(data);
} catch (error) {
return reject(`Failed to parse line ${scriptId}; got [${data}]`);
}
return resolve(result);
});
});
shvar({ scriptId, script });
this.queue.push(scriptId);
stdin?.write(script);
return promise;
}
}
const access = new Access();
const asyncAnvilAccessModule = (
args: string[],
@ -171,11 +304,8 @@ const dbJobAnvilSyncShared = (
return dbInsertOrUpdateJob(subParams);
};
const dbQuery = (query: string, options?: SpawnSyncOptions) => {
shout(formatSql(query));
return execAnvilAccessModule(['--query', query], options);
};
const query = <T extends (number | null | string)[][]>(sqlscript: string) =>
access.interact<T>('r', formatSql(sqlscript));
const dbSubRefreshTimestamp = () => {
let result: string;
@ -304,12 +434,12 @@ export {
dbInsertOrUpdateJob as job,
dbInsertOrUpdateVariable as variable,
dbJobAnvilSyncShared,
dbQuery,
dbSubRefreshTimestamp as timestamp,
dbWrite,
execModuleSubroutine as sub,
getAnvilData,
getLocalHostName,
getLocalHostUUID,
getPeerData,
execModuleSubroutine as sub,
query,
};

@ -2,18 +2,18 @@ import assert from 'assert';
import { ECODE_SESSION_SECRET, VNAME_SESSION_SECRET } from './consts';
import { dbQuery, variable } from './accessModule';
import { query, variable } from './accessModule';
import { openssl, stderr, stdout } from './shell';
export const getSessionSecret = (): string => {
export const getSessionSecret = async (): Promise<string> => {
let sessionSecret: string;
try {
const rows: [sessionSecret: string][] = dbQuery(
const rows: [sessionSecret: string][] = await query(
`SELECT variable_value
FROM variables
WHERE variable_name = '${VNAME_SESSION_SECRET}';`,
).stdout;
);
assert(rows.length > 0, 'No existing session secret found.');

@ -1,64 +1,53 @@
import { Request, Response } from 'express';
import { dbQuery } from '../accessModule';
import { query } from '../accessModule';
import call from '../call';
import { stderr, stdout, stdoutVar } from '../shell';
const buildGetRequestHandler =
(
query: string | BuildQueryFunction,
sqlscript: string | BuildQueryFunction,
{ beforeRespond }: BuildGetRequestHandlerOptions = {},
) =>
(request: Request, response: Response) => {
console.log('Calling CLI script to get data.');
async (request: Request, response: Response) => {
stdout('Calling CLI script to get data.');
const buildQueryOptions: BuildQueryOptions = {};
let queryStdout;
let result: (number | null | string)[][];
try {
({ stdout: queryStdout } = dbQuery(
call<string>(query, {
result = await query(
call<string>(sqlscript, {
parameters: [request, buildQueryOptions],
notCallableReturn: query,
notCallableReturn: sqlscript,
}),
));
);
} catch (queryError) {
console.log(`Failed to execute query; CAUSE: ${queryError}`);
stderr(`Failed to execute query; CAUSE: ${queryError}`);
response.status(500).send();
return;
}
console.log(
`Query stdout pre-hooks (type=[${typeof queryStdout}]): ${JSON.stringify(
queryStdout,
null,
2,
)}`,
);
stdoutVar(result, `Query stdout pre-hooks (type=[${typeof result}]): `);
const { afterQueryReturn } = buildQueryOptions;
queryStdout = call(afterQueryReturn, {
parameters: [queryStdout],
notCallableReturn: queryStdout,
result = call(afterQueryReturn, {
parameters: [result],
notCallableReturn: result,
});
queryStdout = call(beforeRespond, {
parameters: [queryStdout],
notCallableReturn: queryStdout,
result = call(beforeRespond, {
parameters: [result],
notCallableReturn: result,
});
console.log(
`Query stdout post-hooks (type=[${typeof queryStdout}]): ${JSON.stringify(
queryStdout,
null,
2,
)}`,
);
stdoutVar(result, `Query stdout post-hooks (type=[${typeof result}]): `);
response.json(queryStdout);
response.json(result);
};
export default buildGetRequestHandler;

@ -1,71 +1,68 @@
import assert from 'assert';
import { RequestHandler } from 'express';
import { REP_IPV4, REP_PEACEFUL_STRING } from '../../consts';
import { HOST_KEY_CHANGED_PREFIX } from '../../consts/HOST_KEY_CHANGED_PREFIX';
import { dbQuery, getLocalHostUUID, getPeerData } from '../../accessModule';
import { sanitizeSQLParam } from '../../sanitizeSQLParam';
import { getLocalHostUUID, getPeerData, query } from '../../accessModule';
import { sanitize } from '../../sanitize';
import { stderr } from '../../shell';
export const getHostSSH: RequestHandler<
unknown,
{
badSSHKeys?: DeleteSshKeyConflictRequestBody;
hostName: string;
hostOS: string;
hostUUID: string;
isConnected: boolean;
isInetConnected: boolean;
isOSRegistered: boolean;
},
{
password: string;
port?: number;
ipAddress: string;
}
> = (request, response) => {
GetHostSshResponseBody,
GetHostSshRequestBody
> = async (request, response) => {
const {
body: { password, port = 22, ipAddress: target },
body: { password: rpassword, port: rport = 22, ipAddress: rtarget },
} = request;
let hostName: string;
let hostOS: string;
let hostUUID: string;
let isConnected: boolean;
let isInetConnected: boolean;
let isOSRegistered: boolean;
const password = sanitize(rpassword, 'string');
const port = sanitize(rport, 'number');
const target = sanitize(rtarget, 'string', { modifierType: 'sql' });
try {
assert(
REP_PEACEFUL_STRING.test(password),
`Password must be a peaceful string; got [${password}]`,
);
assert(
Number.isInteger(port),
`Port must be a valid integer; got [${port}]`,
);
assert(
REP_IPV4.test(target),
`IP address must be a valid IPv4 address; got [${target}]`,
);
} catch (assertError) {
stderr(`Assert failed when getting host SSH data; CAUSE: ${assertError}`);
return response.status(400).send();
}
const localHostUUID = getLocalHostUUID();
let rsbody: GetHostSshResponseBody;
try {
({
hostName,
hostOS,
hostUUID,
isConnected,
isInetConnected,
isOSRegistered,
} = getPeerData(target, { password, port }));
rsbody = getPeerData(target, { password, port });
} catch (subError) {
stderr(`Failed to get peer data; CAUSE: ${subError}`);
response.status(500).send();
return;
return response.status(500).send();
}
let badSSHKeys: DeleteSshKeyConflictRequestBody | undefined;
if (!isConnected) {
const rows = dbQuery(`
if (!rsbody.isConnected) {
const rows: [stateNote: string, stateUUID: string][] = await query(`
SELECT sta.state_note, sta.state_uuid
FROM states AS sta
WHERE sta.state_host_uuid = '${localHostUUID}'
AND sta.state_name = '${HOST_KEY_CHANGED_PREFIX}${sanitizeSQLParam(
target,
)}';`).stdout as [stateNote: string, stateUUID: string][];
AND sta.state_name = '${HOST_KEY_CHANGED_PREFIX}${target}';`);
if (rows.length > 0) {
badSSHKeys = rows.reduce<DeleteSshKeyConflictRequestBody>(
rsbody.badSSHKeys = rows.reduce<DeleteSshKeyConflictRequestBody>(
(previous, [, stateUUID]) => {
previous[localHostUUID].push(stateUUID);
@ -76,13 +73,5 @@ export const getHostSSH: RequestHandler<
}
}
response.status(200).send({
badSSHKeys,
hostName,
hostOS,
hostUUID,
isConnected,
isInetConnected,
isOSRegistered,
});
response.status(200).send(rsbody);
};

@ -1,6 +1,6 @@
import { RequestHandler } from 'express';
import { dbQuery, getLocalHostName } from '../../accessModule';
import { getLocalHostName, query } from '../../accessModule';
import {
getHostNameDomain,
getHostNamePrefix,
@ -8,17 +8,18 @@ import {
} from '../../disassembleHostName';
import { stderr } from '../../shell';
export const getManifestTemplate: RequestHandler = (request, response) => {
let localHostName = '';
export const getManifestTemplate: RequestHandler = async (
request,
response,
) => {
let localHostName: string;
try {
localHostName = getLocalHostName();
} catch (subError) {
stderr(String(subError));
response.status(500).send();
return;
return response.status(500).send();
}
const localShortHostName = getShortHostName(localHostName);
@ -38,7 +39,7 @@ export const getManifestTemplate: RequestHandler = (request, response) => {
>;
try {
({ stdout: rawQueryResult } = dbQuery(
rawQueryResult = await query(
`SELECT
a.fence_uuid,
a.fence_name,
@ -71,13 +72,11 @@ export const getManifestTemplate: RequestHandler = (request, response) => {
ORDER BY manifest_name DESC
LIMIT 1
) AS c ON a.row_number = c.row_number;`,
));
);
} catch (queryError) {
stderr(`Failed to execute query; CAUSE: ${queryError}`);
response.status(500).send();
return;
return response.status(500).send();
}
const queryResult = rawQueryResult.reduce<

@ -1,107 +1,120 @@
import assert from 'assert';
import { RequestHandler } from 'express';
import { REP_UUID, SERVER_PATHS } from '../../consts';
import { OS_LIST_MAP } from '../../consts/OS_LIST';
import { REP_INTEGER, REP_UUID } from '../../consts/REG_EXP_PATTERNS';
import SERVER_PATHS from '../../consts/SERVER_PATHS';
import { dbQuery, job } from '../../accessModule';
import { stderr, stdout } from '../../shell';
import { job, query } from '../../accessModule';
import { sanitize } from '../../sanitize';
import { stderr, stdout, stdoutVar } from '../../shell';
export const createServer: RequestHandler = ({ body }, response) => {
stdout(`Creating server.\n${JSON.stringify(body, null, 2)}`);
export const createServer: RequestHandler = async (request, response) => {
const { body: rqbody = {} } = request;
stdoutVar({ rqbody }, 'Creating server.\n');
const {
serverName,
cpuCores,
memory,
serverName: rServerName,
cpuCores: rCpuCores,
memory: rMemory,
virtualDisks: [
{ storageSize = undefined, storageGroupUUID = undefined } = {},
{
storageSize: rStorageSize = undefined,
storageGroupUUID: rStorageGroupUuid = undefined,
} = {},
] = [],
installISOFileUUID,
driverISOFileUUID,
anvilUUID,
optimizeForOS,
} = body || {};
const dataServerName = String(serverName);
const dataOS = String(optimizeForOS);
const dataCPUCores = String(cpuCores);
const dataRAM = String(memory);
const dataStorageGroupUUID = String(storageGroupUUID);
const dataStorageSize = String(storageSize);
const dataInstallISO = String(installISOFileUUID);
const dataDriverISO = String(driverISOFileUUID) || 'none';
const dataAnvilUUID = String(anvilUUID);
installISOFileUUID: rInstallIsoUuid,
driverISOFileUUID: rDriverIsoUuid,
anvilUUID: rAnvilUuid,
optimizeForOS: rOptimizeForOs,
} = rqbody;
const serverName = sanitize(rServerName, 'string');
const os = sanitize(rOptimizeForOs, 'string');
const cpuCores = sanitize(rCpuCores, 'number');
const memory = sanitize(rMemory, 'number');
const storageGroupUUID = sanitize(rStorageGroupUuid, 'string');
const storageSize = sanitize(rStorageSize, 'number');
const installIsoUuid = sanitize(rInstallIsoUuid, 'string');
const driverIsoUuid = sanitize(rDriverIsoUuid, 'string', {
fallback: 'none',
});
const anvilUuid = sanitize(rAnvilUuid, 'string');
try {
assert(
/^[0-9a-z_-]+$/i.test(dataServerName),
`Data server name can only contain alphanumeric, underscore, and hyphen characters; got [${dataServerName}].`,
/^[0-9a-z_-]+$/i.test(serverName),
`Data server name can only contain alphanumeric, underscore, and hyphen characters; got [${serverName}]`,
);
const [[serverNameCount]] = dbQuery(
`SELECT COUNT(server_uuid) FROM servers WHERE server_name = '${dataServerName}'`,
).stdout;
const [[serverNameCount]] = await query(
`SELECT COUNT(server_uuid) FROM servers WHERE server_name = '${serverName}'`,
);
assert(
serverNameCount === 0,
`Data server name already exists; got [${dataServerName}]`,
`Data server name already exists; got [${serverName}]`,
);
assert(
OS_LIST_MAP[dataOS] !== undefined,
`Data OS not recognized; got [${dataOS}].`,
OS_LIST_MAP[os] !== undefined,
`Data OS not recognized; got [${os}]`,
);
assert(
REP_INTEGER.test(dataCPUCores),
`Data CPU cores can only contain digits; got [${dataCPUCores}].`,
Number.isInteger(cpuCores),
`Data CPU cores can only contain digits; got [${cpuCores}]`,
);
assert(
REP_INTEGER.test(dataRAM),
`Data RAM can only contain digits; got [${dataRAM}].`,
Number.isInteger(memory),
`Data RAM can only contain digits; got [${memory}]`,
);
assert(
REP_UUID.test(dataStorageGroupUUID),
`Data storage group UUID must be a valid UUID; got [${dataStorageGroupUUID}].`,
REP_UUID.test(storageGroupUUID),
`Data storage group UUID must be a valid UUID; got [${storageGroupUUID}]`,
);
assert(
REP_INTEGER.test(dataStorageSize),
`Data storage size can only contain digits; got [${dataStorageSize}].`,
Number.isInteger(storageSize),
`Data storage size can only contain digits; got [${storageSize}]`,
);
assert(
REP_UUID.test(dataInstallISO),
`Data install ISO must be a valid UUID; got [${dataInstallISO}].`,
REP_UUID.test(installIsoUuid),
`Data install ISO must be a valid UUID; got [${installIsoUuid}]`,
);
assert(
dataDriverISO === 'none' || REP_UUID.test(dataDriverISO),
`Data driver ISO must be a valid UUID when provided; got [${dataDriverISO}].`,
driverIsoUuid === 'none' || REP_UUID.test(driverIsoUuid),
`Data driver ISO must be a valid UUID when provided; got [${driverIsoUuid}]`,
);
assert(
REP_UUID.test(dataAnvilUUID),
`Data anvil UUID must be a valid UUID; got [${dataAnvilUUID}].`,
REP_UUID.test(anvilUuid),
`Data anvil UUID must be a valid UUID; got [${anvilUuid}]`,
);
} catch (assertError) {
stdout(
`Failed to assert value when trying to provision a server; CAUSE: ${assertError}.`,
`Failed to assert value when trying to provision a server; CAUSE: ${assertError}`,
);
response.status(400).send();
return;
return response.status(400).send();
}
const provisionServerJobData = `server_name=${dataServerName}
os=${dataOS}
cpu_cores=${dataCPUCores}
ram=${dataRAM}
storage_group_uuid=${dataStorageGroupUUID}
storage_size=${dataStorageSize}
install_iso=${dataInstallISO}
driver_iso=${dataDriverISO}`;
const provisionServerJobData = `server_name=${serverName}
os=${os}
cpu_cores=${cpuCores}
ram=${memory}
storage_group_uuid=${storageGroupUUID}
storage_size=${storageSize}
install_iso=${installIsoUuid}
driver_iso=${driverIsoUuid}`;
stdout(`provisionServerJobData=[${provisionServerJobData}]`);
const [[provisionServerJobHostUUID]] = dbQuery(
const [[provisionServerJobHostUUID]]: [[string]] = await query(
`SELECT
CASE
WHEN pri_hos.primary_host_uuid IS NULL
@ -120,7 +133,7 @@ driver_iso=${dataDriverISO}`;
AND sca_clu_nod.scan_cluster_node_crmd_member
AND sca_clu_nod.scan_cluster_node_cluster_member
AND (NOT sca_clu_nod.scan_cluster_node_maintenance_mode)
AND anv.anvil_uuid = '${dataAnvilUUID}'
AND anv.anvil_uuid = '${anvilUuid}'
ORDER BY sca_clu_nod.scan_cluster_node_name
LIMIT 1
) AS pri_hos
@ -129,10 +142,10 @@ driver_iso=${dataDriverISO}`;
1 AS phr,
anv.anvil_node1_host_uuid AS node1_host_uuid
FROM anvils AS anv
WHERE anv.anvil_uuid = '${dataAnvilUUID}'
WHERE anv.anvil_uuid = '${anvilUuid}'
) AS nod_1
ON pri_hos.phl = nod_1.phr;`,
).stdout;
);
stdout(`provisionServerJobHostUUID=[${provisionServerJobHostUUID}]`);
@ -149,9 +162,7 @@ driver_iso=${dataDriverISO}`;
} catch (subError) {
stderr(`Failed to provision server; CAUSE: ${subError}`);
response.status(500).send();
return;
return response.status(500).send();
}
response.status(202).send();

@ -3,10 +3,9 @@ import { RequestHandler } from 'express';
import { createReadStream } from 'fs';
import path from 'path';
import { REP_UUID } from '../../consts/REG_EXP_PATTERNS';
import SERVER_PATHS from '../../consts/SERVER_PATHS';
import { REP_UUID, SERVER_PATHS } from '../../consts';
import { dbQuery, getLocalHostUUID, job } from '../../accessModule';
import { getLocalHostUUID, job, query } from '../../accessModule';
import { sanitize } from '../../sanitize';
import { mkfifo, rm, stderr, stdout } from '../../shell';
@ -18,7 +17,7 @@ const rmfifo = (path: string) => {
}
};
export const getServerDetail: RequestHandler = (request, response) => {
export const getServerDetail: RequestHandler = async (request, response) => {
const { serverUUID } = request.params;
const { ss, resize } = request.query;
@ -39,9 +38,7 @@ export const getServerDetail: RequestHandler = (request, response) => {
`Failed to assert value when trying to get server detail; CAUSE: ${assertError}.`,
);
response.status(500).send();
return;
return response.status(500).send();
}
if (isScreenshot) {
@ -52,24 +49,20 @@ export const getServerDetail: RequestHandler = (request, response) => {
} catch (subError) {
stderr(String(subError));
response.status(500).send();
return;
return response.status(500).send();
}
stdout(`requestHostUUID=[${requestHostUUID}]`);
try {
[[serverHostUUID]] = dbQuery(`
[[serverHostUUID]] = await query(`
SELECT server_host_uuid
FROM servers
WHERE server_uuid = '${serverUUID}';`).stdout;
WHERE server_uuid = '${serverUUID}';`);
} catch (queryError) {
stderr(`Failed to get server host UUID; CAUSE: ${queryError}`);
response.status(500).send();
return;
return response.status(500).send();
}
stdout(`serverHostUUID=[${serverHostUUID}]`);
@ -94,9 +87,9 @@ export const getServerDetail: RequestHandler = (request, response) => {
namedPipeReadStream.once('close', () => {
stdout(`On close; removing named pipe at ${imageFilePath}.`);
response.status(200).send({ screenshot: imageData });
rmfifo(imageFilePath);
return response.status(200).send({ screenshot: imageData });
});
namedPipeReadStream.on('data', (data) => {
@ -123,11 +116,9 @@ export const getServerDetail: RequestHandler = (request, response) => {
`Failed to prepare named pipe and/or receive image data; CAUSE: ${prepPipeError}`,
);
response.status(500).send();
rmfifo(imageFilePath);
return;
return response.status(500).send();
}
let resizeArgs = sanitize(resize, 'string');
@ -152,9 +143,7 @@ out-file-id=${epoch}`,
} catch (subError) {
stderr(`Failed to queue fetch server screenshot job; CAUSE: ${subError}`);
response.status(500).send();
return;
return response.status(500).send();
}
} else {
// For getting sever detail data.

@ -1,31 +1,33 @@
import express from 'express';
import { DELETED } from '../lib/consts';
import {
dbJobAnvilSyncShared,
dbQuery,
timestamp,
dbWrite,
query,
} from '../lib/accessModule';
import getFile from '../lib/request_handlers/file/getFile';
import getFileDetail from '../lib/request_handlers/file/getFileDetail';
import uploadSharedFiles from '../middlewares/uploadSharedFiles';
import { stderr, stdout, stdoutVar } from '../lib/shell';
const router = express.Router();
router
.delete('/:fileUUID', (request, response) => {
.delete('/:fileUUID', async (request, response) => {
const { fileUUID } = request.params;
const FILE_TYPE_DELETED = 'DELETED';
const [[oldFileType]] = dbQuery(
const [[oldFileType]] = await query(
`SELECT file_type FROM files WHERE file_uuid = '${fileUUID}';`,
).stdout;
);
if (oldFileType !== FILE_TYPE_DELETED) {
if (oldFileType !== DELETED) {
dbWrite(
`UPDATE files
SET
file_type = '${FILE_TYPE_DELETED}',
file_type = '${DELETED}',
modified_date = '${timestamp()}'
WHERE file_uuid = '${fileUUID}';`,
).stdout;
@ -40,11 +42,10 @@ router
.get('/', getFile)
.get('/:fileUUID', getFileDetail)
.post('/', uploadSharedFiles.single('file'), ({ file, body }, response) => {
console.log('Receiving shared file.');
stdout('Receiving shared file.');
if (file) {
console.log(`file: ${JSON.stringify(file, null, 2)}`);
console.log(`body: ${JSON.stringify(body, null, 2)}`);
stdoutVar({ body, file });
dbJobAnvilSyncShared(
'move_incoming',
@ -56,24 +57,26 @@ router
response.status(200).send();
}
})
.put('/:fileUUID', (request, response) => {
console.log('Begin edit single file.');
console.dir(request.body);
.put('/:fileUUID', async (request, response) => {
const { body = {}, params } = request;
const { fileUUID } = request.params;
const { fileName, fileLocations, fileType } = request.body;
stdoutVar(body, 'Begin edit single file. body=');
const { fileUUID } = params;
const { fileName, fileLocations, fileType } = body;
const anvilSyncSharedFunctions = [];
let query = '';
let sqlscript = '';
if (fileName) {
const [[oldFileName]] = dbQuery(
const [[oldFileName]] = await query(
`SELECT file_name FROM files WHERE file_uuid = '${fileUUID}';`,
).stdout;
console.log(`oldFileName=[${oldFileName}],newFileName=[${fileName}]`);
);
stdoutVar({ oldFileName, fileName });
if (fileName !== oldFileName) {
query += `
sqlscript += `
UPDATE files
SET
file_name = '${fileName}',
@ -93,7 +96,7 @@ router
}
if (fileType) {
query += `
sqlscript += `
UPDATE files
SET
file_type = '${fileType}',
@ -113,7 +116,7 @@ router
if (fileLocations) {
fileLocations.forEach(
({
async ({
fileLocationUUID,
isFileLocationActive,
}: {
@ -132,14 +135,18 @@ router
jobDescription = '0133';
}
query += `
sqlscript += `
UPDATE file_locations
SET
file_location_active = '${fileLocationActive}',
modified_date = '${timestamp()}'
WHERE file_location_uuid = '${fileLocationUUID}';`;
const targetHosts = dbQuery(
const targetHosts: [
n1uuid: string,
n2uuid: string,
dr1uuid: null | string,
][] = await query(
`SELECT
anv.anvil_node1_host_uuid,
anv.anvil_node2_host_uuid,
@ -148,9 +155,9 @@ router
JOIN file_locations AS fil_loc
ON anv.anvil_uuid = fil_loc.file_location_anvil_uuid
WHERE fil_loc.file_location_uuid = '${fileLocationUUID}';`,
).stdout;
);
targetHosts.flat().forEach((hostUUID: string) => {
targetHosts.flat().forEach((hostUUID: null | string) => {
if (hostUUID) {
anvilSyncSharedFunctions.push(() =>
dbJobAnvilSyncShared(
@ -167,34 +174,23 @@ router
);
}
console.log(`Query (type=[${typeof query}]): [${query}]`);
stdout(`Query (type=[${typeof sqlscript}]): [${sqlscript}]`);
let queryStdout;
try {
({ stdout: queryStdout } = dbWrite(query));
({ stdout: queryStdout } = dbWrite(sqlscript));
} catch (queryError) {
console.log(`Failed to execute query; CAUSE: ${queryError}`);
stderr(`Failed to execute query; CAUSE: ${queryError}`);
response.status(500).send();
return response.status(500).send();
}
console.log(
`Query stdout (type=[${typeof queryStdout}]): ${JSON.stringify(
queryStdout,
null,
2,
)}`,
);
anvilSyncSharedFunctions.forEach((fn, index) => {
console.log(
`Anvil sync shared [${index}] output: [${JSON.stringify(
fn(),
null,
2,
)}]`,
stdoutVar(queryStdout, `Query stdout (type=[${typeof queryStdout}]): `);
anvilSyncSharedFunctions.forEach((fn, index) =>
stdoutVar(fn(), `Anvil sync shared [${index}] output: `),
);
});
response.status(200).send(queryStdout);
});

@ -0,0 +1,15 @@
type GetHostSshRequestBody = {
password: string;
port?: number;
ipAddress: string;
};
type GetHostSshResponseBody = {
badSSHKeys?: DeleteSshKeyConflictRequestBody;
hostName: string;
hostOS: string;
hostUUID: string;
isConnected: boolean;
isInetConnected: boolean;
isOSRegistered: boolean;
};
Loading…
Cancel
Save