ffffng/server/resources/nodeResource.ts

151 lines
4.9 KiB
TypeScript
Raw Normal View History

import _ from "lodash";
import deepExtend from "deep-extend";
import Constraints from "../validation/constraints";
import ErrorTypes from "../utils/errorTypes";
import * as MonitoringService from "../services/monitoringService";
import * as NodeService from "../services/nodeService";
import {normalizeMac, normalizeString} from "../utils/strings";
import {forConstraint, forConstraints} from "../validation/validator";
import * as Resources from "../utils/resources";
import {Request, Response} from "express";
2022-07-18 17:49:42 +02:00
import {EnhancedNode, isNodeSortField, MAC, Node, Token} from "../types";
const nodeFields = ['hostname', 'key', 'email', 'nickname', 'mac', 'coords', 'monitoring'];
function getNormalizedNodeData(reqData: any): Node {
const node: {[key: string]: any} = {};
_.each(nodeFields, function (field) {
let value = normalizeString(reqData[field]);
if (field === 'mac') {
value = normalizeMac(value);
}
node[field] = value;
});
return node as Node;
}
const isValidNode = forConstraints(Constraints.node, false);
const isValidToken = forConstraint(Constraints.token, false);
export function create (req: Request, res: Response): void {
const data = Resources.getData(req);
const node = getNormalizedNodeData(data);
if (!isValidNode(node)) {
return Resources.error(res, {data: 'Invalid node data.', type: ErrorTypes.badRequest});
}
NodeService.createNode(node)
.then(result => Resources.success(res, result))
.catch(err => Resources.error(res, err));
}
export function update (req: Request, res: Response): void {
const data = Resources.getData(req);
const token = normalizeString(data.token);
if (!isValidToken(token)) {
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
}
2022-07-18 17:49:42 +02:00
const validatedToken: Token = token as Token;
const node = getNormalizedNodeData(data);
if (!isValidNode(node)) {
return Resources.error(res, {data: 'Invalid node data.', type: ErrorTypes.badRequest});
}
NodeService.updateNode(validatedToken, node)
.then(result => Resources.success(res, result))
.catch(err => Resources.error(res, err));
}
export function remove(req: Request, res: Response): void {
const data = Resources.getData(req);
const token = normalizeString(data.token);
if (!isValidToken(token)) {
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
}
2022-07-18 17:49:42 +02:00
const validatedToken: Token = token as Token;
NodeService.deleteNode(validatedToken)
.then(() => Resources.success(res, {}))
.catch(err => Resources.error(res, err));
}
export function get(req: Request, res: Response): void {
const token = normalizeString(Resources.getData(req).token);
if (!isValidToken(token)) {
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
}
2022-07-18 17:49:42 +02:00
const validatedToken: Token = token as Token;
NodeService.getNodeDataByToken(validatedToken)
.then(node => Resources.success(res, node))
.catch(err => Resources.error(res, err));
}
async function doGetAll(req: Request): Promise<{ total: number; pageNodes: any }> {
const restParams = await Resources.getValidRestParams('list', 'node', req);
const nodes = await NodeService.getAllNodes();
const realNodes = _.filter(nodes, node =>
// We ignore nodes without tokens as those are only manually added ones like gateways.
!!node.token
);
const macs: MAC[] = _.map(realNodes, (node: Node): MAC => node.mac);
const nodeStateByMac = await MonitoringService.getByMacs(macs);
2022-05-26 13:58:01 +02:00
const enhancedNodes: EnhancedNode[] = _.map(realNodes, (node: Node): EnhancedNode => {
2022-07-18 17:49:42 +02:00
const nodeState = nodeStateByMac[node.mac];
if (nodeState) {
return deepExtend({}, node, {
site: nodeState.site,
domain: nodeState.domain,
onlineState: nodeState.state
});
}
2022-05-26 13:58:01 +02:00
return node as EnhancedNode;
});
2022-05-26 13:58:01 +02:00
const filteredNodes = Resources.filter<EnhancedNode>(
enhancedNodes,
[
'hostname',
'nickname',
'email',
'token',
'mac',
'site',
'domain',
'key',
'onlineState'
],
restParams
);
const total = filteredNodes.length;
const sortedNodes = Resources.sort(
filteredNodes,
isNodeSortField,
restParams
);
const pageNodes = Resources.getPageEntities(sortedNodes, restParams);
return {total, pageNodes};
}
export function getAll(req: Request, res: Response): void {
doGetAll(req)
.then((result: {total: number, pageNodes: any[]}) => {
res.set('X-Total-Count', result.total.toString(10));
return Resources.success(res, result.pageNodes);
})
.catch((err: any) => Resources.error(res, err));
}