ESLint: Fix more warnings and errors.
This commit is contained in:
parent
66fb4e5004
commit
bfd6ca1d26
|
@ -10,6 +10,7 @@ import { Request, Response } from "express";
|
||||||
import {
|
import {
|
||||||
CreateOrUpdateNode,
|
CreateOrUpdateNode,
|
||||||
DomainSpecificNodeResponse,
|
DomainSpecificNodeResponse,
|
||||||
|
filterUndefinedFromJSON,
|
||||||
isCreateOrUpdateNode,
|
isCreateOrUpdateNode,
|
||||||
isNodeSortField,
|
isNodeSortField,
|
||||||
isString,
|
isString,
|
||||||
|
@ -108,7 +109,7 @@ export const get = handleJSONWithData<NodeResponse>(async (data) => {
|
||||||
|
|
||||||
async function doGetAll(
|
async function doGetAll(
|
||||||
req: Request
|
req: Request
|
||||||
): Promise<{ total: number; pageNodes: any }> {
|
): Promise<{ total: number; pageNodes: DomainSpecificNodeResponse[] }> {
|
||||||
const restParams = await Resources.getValidRestParams("list", "node", req);
|
const restParams = await Resources.getValidRestParams("list", "node", req);
|
||||||
|
|
||||||
const nodes = await NodeService.getAllNodes();
|
const nodes = await NodeService.getAllNodes();
|
||||||
|
@ -159,9 +160,17 @@ async function doGetAll(
|
||||||
|
|
||||||
export function getAll(req: Request, res: Response): void {
|
export function getAll(req: Request, res: Response): void {
|
||||||
doGetAll(req)
|
doGetAll(req)
|
||||||
.then((result: { total: number; pageNodes: any[] }) => {
|
.then(
|
||||||
|
(result: {
|
||||||
|
total: number;
|
||||||
|
pageNodes: DomainSpecificNodeResponse[];
|
||||||
|
}) => {
|
||||||
res.set("X-Total-Count", result.total.toString(10));
|
res.set("X-Total-Count", result.total.toString(10));
|
||||||
return Resources.success(res, result.pageNodes);
|
return Resources.success(
|
||||||
})
|
res,
|
||||||
.catch((err: any) => Resources.error(res, err));
|
result.pageNodes.map(filterUndefinedFromJSON)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch((err) => Resources.error(res, err));
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,21 +196,23 @@ export async function sendPendingMails(): Promise<void> {
|
||||||
|
|
||||||
const startTime = moment();
|
const startTime = moment();
|
||||||
|
|
||||||
while (true) {
|
let pendingMails = await findPendingMailsBefore(
|
||||||
Logger.tag("mail", "queue").debug("Sending next batch...");
|
|
||||||
|
|
||||||
const pendingMails = await findPendingMailsBefore(
|
|
||||||
startTime,
|
startTime,
|
||||||
MAIL_QUEUE_DB_BATCH_SIZE
|
MAIL_QUEUE_DB_BATCH_SIZE
|
||||||
);
|
);
|
||||||
|
|
||||||
if (_.isEmpty(pendingMails)) {
|
while (!_.isEmpty(pendingMails)) {
|
||||||
Logger.tag("mail", "queue").debug("Done sending pending mails.");
|
Logger.tag("mail", "queue").debug("Sending next batch...");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const pendingMail of pendingMails) {
|
for (const pendingMail of pendingMails) {
|
||||||
await sendPendingMail(pendingMail);
|
await sendPendingMail(pendingMail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pendingMails = await findPendingMailsBefore(
|
||||||
|
startTime,
|
||||||
|
MAIL_QUEUE_DB_BATCH_SIZE
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.tag("mail", "queue").debug("Done sending pending mails.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ const templateFunctions: {
|
||||||
| ((unix: number) => string);
|
| ((unix: number) => string);
|
||||||
} = {};
|
} = {};
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
function renderSnippet(this: any, name: string, data: MailData): string {
|
function renderSnippet(this: any, name: string, data: MailData): string {
|
||||||
const snippetFile = snippetsBasePath + "/" + name + ".html";
|
const snippetFile = snippetsBasePath + "/" + name + ".html";
|
||||||
|
|
||||||
|
@ -34,7 +35,9 @@ function renderSnippet(this: any, name: string, data: MailData): string {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
function snippet(name: string): (this: any, data: MailData) => string {
|
function snippet(name: string): (this: any, data: MailData) => string {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
return function (this: any, data: MailData): string {
|
return function (this: any, data: MailData): string {
|
||||||
return renderSnippet.bind(this)(name, data);
|
return renderSnippet.bind(this)(name, data);
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,15 +25,6 @@ beforeEach(() => {
|
||||||
mockedLogger.reset();
|
mockedLogger.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("parseNode() should fail parsing node for undefined node data", () => {
|
|
||||||
// given
|
|
||||||
const importTimestamp = now();
|
|
||||||
const nodeData = undefined;
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(() => parseNode(importTimestamp, nodeData)).toThrowError();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("parseNode() should fail parsing node for empty node data", () => {
|
test("parseNode() should fail parsing node for empty node data", () => {
|
||||||
// given
|
// given
|
||||||
const importTimestamp = now();
|
const importTimestamp = now();
|
||||||
|
|
|
@ -24,9 +24,11 @@ import {
|
||||||
isDomain,
|
isDomain,
|
||||||
isMonitoringSortField,
|
isMonitoringSortField,
|
||||||
isOnlineState,
|
isOnlineState,
|
||||||
|
isPlainObject,
|
||||||
isSite,
|
isSite,
|
||||||
isString,
|
isString,
|
||||||
isUndefined,
|
isUndefined,
|
||||||
|
JSONValue,
|
||||||
MAC,
|
MAC,
|
||||||
MailType,
|
MailType,
|
||||||
MonitoringSortField,
|
MonitoringSortField,
|
||||||
|
@ -35,6 +37,7 @@ import {
|
||||||
NodeId,
|
NodeId,
|
||||||
NodeStateData,
|
NodeStateData,
|
||||||
OnlineState,
|
OnlineState,
|
||||||
|
parseJSON,
|
||||||
RunResult,
|
RunResult,
|
||||||
Site,
|
Site,
|
||||||
StoredNode,
|
StoredNode,
|
||||||
|
@ -206,13 +209,13 @@ const isValidMac = forConstraint(CONSTRAINTS.node.mac, false);
|
||||||
|
|
||||||
export function parseNode(
|
export function parseNode(
|
||||||
importTimestamp: UnixTimestampSeconds,
|
importTimestamp: UnixTimestampSeconds,
|
||||||
nodeData: any
|
nodeData: JSONValue
|
||||||
): ParsedNode {
|
): ParsedNode {
|
||||||
if (!_.isPlainObject(nodeData)) {
|
if (!isPlainObject(nodeData)) {
|
||||||
throw new Error("Unexpected node type: " + typeof nodeData);
|
throw new Error("Unexpected node type: " + typeof nodeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_.isPlainObject(nodeData.nodeinfo)) {
|
if (!isPlainObject(nodeData.nodeinfo)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Unexpected nodeinfo type: " + typeof nodeData.nodeinfo
|
"Unexpected nodeinfo type: " + typeof nodeData.nodeinfo
|
||||||
);
|
);
|
||||||
|
@ -225,7 +228,7 @@ export function parseNode(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_.isPlainObject(nodeData.nodeinfo.network)) {
|
if (!isPlainObject(nodeData.nodeinfo.network)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Node " +
|
"Node " +
|
||||||
nodeId +
|
nodeId +
|
||||||
|
@ -239,9 +242,9 @@ export function parseNode(
|
||||||
"Node " + nodeId + ": Invalid MAC: " + nodeData.nodeinfo.network.mac
|
"Node " + nodeId + ": Invalid MAC: " + nodeData.nodeinfo.network.mac
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const mac = normalizeMac(nodeData.nodeinfo.network.mac) as MAC;
|
const mac = normalizeMac(nodeData.nodeinfo.network.mac as MAC);
|
||||||
|
|
||||||
if (!_.isPlainObject(nodeData.flags)) {
|
if (!isPlainObject(nodeData.flags)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Node " +
|
"Node " +
|
||||||
nodeId +
|
nodeId +
|
||||||
|
@ -271,7 +274,7 @@ export function parseNode(
|
||||||
|
|
||||||
let site: Site | undefined;
|
let site: Site | undefined;
|
||||||
if (
|
if (
|
||||||
_.isPlainObject(nodeData.nodeinfo.system) &&
|
isPlainObject(nodeData.nodeinfo.system) &&
|
||||||
isSite(nodeData.nodeinfo.system.site_code)
|
isSite(nodeData.nodeinfo.system.site_code)
|
||||||
) {
|
) {
|
||||||
site = nodeData.nodeinfo.system.site_code;
|
site = nodeData.nodeinfo.system.site_code;
|
||||||
|
@ -279,7 +282,7 @@ export function parseNode(
|
||||||
|
|
||||||
let domain: Domain | undefined;
|
let domain: Domain | undefined;
|
||||||
if (
|
if (
|
||||||
_.isPlainObject(nodeData.nodeinfo.system) &&
|
isPlainObject(nodeData.nodeinfo.system) &&
|
||||||
isDomain(nodeData.nodeinfo.system.domain_code)
|
isDomain(nodeData.nodeinfo.system.domain_code)
|
||||||
) {
|
) {
|
||||||
domain = nodeData.nodeinfo.system.domain_code;
|
domain = nodeData.nodeinfo.system.domain_code;
|
||||||
|
@ -300,9 +303,9 @@ export function parseNodesJson(body: string): NodesParsingResult {
|
||||||
"Parsing nodes.json..."
|
"Parsing nodes.json..."
|
||||||
);
|
);
|
||||||
|
|
||||||
const json = JSON.parse(body);
|
const json = parseJSON(body);
|
||||||
|
|
||||||
if (!_.isPlainObject(json)) {
|
if (!isPlainObject(json)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Expecting a JSON object as the nodes.json root, but got: ${typeof json}`
|
`Expecting a JSON object as the nodes.json root, but got: ${typeof json}`
|
||||||
);
|
);
|
||||||
|
|
|
@ -405,7 +405,7 @@ function setNodeValue(
|
||||||
case LINE_PREFIX.TOKEN:
|
case LINE_PREFIX.TOKEN:
|
||||||
node.token = value as Token;
|
node.token = value as Token;
|
||||||
break;
|
break;
|
||||||
case LINE_PREFIX.MONITORING:
|
case LINE_PREFIX.MONITORING: {
|
||||||
const active = value === "aktiv";
|
const active = value === "aktiv";
|
||||||
const pending = value === "pending";
|
const pending = value === "pending";
|
||||||
node.monitoringState = active
|
node.monitoringState = active
|
||||||
|
@ -414,6 +414,7 @@ function setNodeValue(
|
||||||
? MonitoringState.PENDING
|
? MonitoringState.PENDING
|
||||||
: MonitoringState.DISABLED;
|
: MonitoringState.DISABLED;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case LINE_PREFIX.MONITORING_TOKEN:
|
case LINE_PREFIX.MONITORING_TOKEN:
|
||||||
nodeSecrets.monitoringToken = value as MonitoringToken;
|
nodeSecrets.monitoringToken = value as MonitoringToken;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -77,6 +77,10 @@ export function isObject(arg: unknown): arg is object {
|
||||||
return arg !== null && typeof arg === "object";
|
return arg !== null && typeof arg === "object";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isPlainObject(arg: unknown): arg is { [key: string]: unknown } {
|
||||||
|
return isObject(arg) && !Array.isArray(arg);
|
||||||
|
}
|
||||||
|
|
||||||
export function hasOwnProperty<Key extends PropertyKey>(
|
export function hasOwnProperty<Key extends PropertyKey>(
|
||||||
arg: unknown,
|
arg: unknown,
|
||||||
key: Key
|
key: Key
|
||||||
|
@ -84,6 +88,13 @@ export function hasOwnProperty<Key extends PropertyKey>(
|
||||||
return isObject(arg) && key in arg;
|
return isObject(arg) && key in arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getFieldIfExists(
|
||||||
|
arg: unknown,
|
||||||
|
key: PropertyKey
|
||||||
|
): unknown | undefined {
|
||||||
|
return hasOwnProperty(arg, key) ? arg[key] : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export function isArray<T>(arg: unknown, isT: TypeGuard<T>): arg is Array<T> {
|
export function isArray<T>(arg: unknown, isT: TypeGuard<T>): arg is Array<T> {
|
||||||
if (!Array.isArray(arg)) {
|
if (!Array.isArray(arg)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -25,6 +25,9 @@ export interface Constraint {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Constraints = { [key: string]: Constraint };
|
export type Constraints = { [key: string]: Constraint };
|
||||||
|
export type NestedConstraints = {
|
||||||
|
[key: string]: Constraint | Constraints | NestedConstraints;
|
||||||
|
};
|
||||||
export type Values = { [key: string]: unknown };
|
export type Values = { [key: string]: unknown };
|
||||||
|
|
||||||
export function isConstraint(arg: unknown): arg is Constraint {
|
export function isConstraint(arg: unknown): arg is Constraint {
|
||||||
|
|
|
@ -7,12 +7,14 @@ import {
|
||||||
Constraints,
|
Constraints,
|
||||||
forConstraints,
|
forConstraints,
|
||||||
isConstraints,
|
isConstraints,
|
||||||
|
NestedConstraints,
|
||||||
} from "../shared/validation/validator";
|
} from "../shared/validation/validator";
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import {
|
import {
|
||||||
EnumTypeGuard,
|
EnumTypeGuard,
|
||||||
EnumValue,
|
EnumValue,
|
||||||
type GenericSortField,
|
type GenericSortField,
|
||||||
|
getFieldIfExists,
|
||||||
isJSONObject,
|
isJSONObject,
|
||||||
isNumber,
|
isNumber,
|
||||||
isString,
|
isString,
|
||||||
|
@ -26,7 +28,7 @@ import {
|
||||||
export type RequestData = JSONObject;
|
export type RequestData = JSONObject;
|
||||||
export type RequestHandler = (request: Request, response: Response) => void;
|
export type RequestHandler = (request: Request, response: Response) => void;
|
||||||
|
|
||||||
export type Entity = { [key: string]: any };
|
export type Entity = { [key: string]: unknown };
|
||||||
|
|
||||||
export type RestParams = {
|
export type RestParams = {
|
||||||
q?: string;
|
q?: string;
|
||||||
|
@ -180,7 +182,7 @@ export async function getValidRestParams(
|
||||||
subtype: string | null,
|
subtype: string | null,
|
||||||
req: Request
|
req: Request
|
||||||
): Promise<RestParams> {
|
): Promise<RestParams> {
|
||||||
const restConstraints = CONSTRAINTS.rest as { [key: string]: any };
|
const restConstraints = CONSTRAINTS.rest as { [key: string]: Constraints };
|
||||||
if (!(type in restConstraints) || !isConstraints(restConstraints[type])) {
|
if (!(type in restConstraints) || !isConstraints(restConstraints[type])) {
|
||||||
Logger.tag("validation", "rest").error(
|
Logger.tag("validation", "rest").error(
|
||||||
"Unknown REST resource type: {}",
|
"Unknown REST resource type: {}",
|
||||||
|
@ -193,18 +195,16 @@ export async function getValidRestParams(
|
||||||
let filterConstraints: Constraints = {};
|
let filterConstraints: Constraints = {};
|
||||||
if (subtype) {
|
if (subtype) {
|
||||||
const subtypeFilters = subtype + "Filters";
|
const subtypeFilters = subtype + "Filters";
|
||||||
const constraintsObj = CONSTRAINTS as { [key: string]: any };
|
const nestedConstraints = CONSTRAINTS as NestedConstraints;
|
||||||
if (
|
const subConstraints = nestedConstraints[subtypeFilters];
|
||||||
!(subtypeFilters in constraintsObj) ||
|
if (!isConstraints(subConstraints)) {
|
||||||
!isConstraints(constraintsObj[subtypeFilters])
|
|
||||||
) {
|
|
||||||
Logger.tag("validation", "rest").error(
|
Logger.tag("validation", "rest").error(
|
||||||
"Unknown REST resource subtype: {}",
|
"Unknown REST resource subtype: {}",
|
||||||
subtype
|
subtype
|
||||||
);
|
);
|
||||||
throw { data: "Internal error.", type: ErrorTypes.internalError };
|
throw { data: "Internal error.", type: ErrorTypes.internalError };
|
||||||
}
|
}
|
||||||
filterConstraints = constraintsObj[subtypeFilters];
|
filterConstraints = subConstraints;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = getData(req);
|
const data = getData(req);
|
||||||
|
@ -232,7 +232,7 @@ export function filter<E>(
|
||||||
query = query.trim().toLowerCase();
|
query = query.trim().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryMatches(entity: Entity): boolean {
|
function queryMatches(entity: E): boolean {
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,7 @@ export function filter<E>(
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let value = entity[field];
|
let value = getFieldIfExists(entity, field);
|
||||||
if (isNumber(value)) {
|
if (isNumber(value)) {
|
||||||
value = value.toString();
|
value = value.toString();
|
||||||
}
|
}
|
||||||
|
@ -249,21 +249,21 @@ export function filter<E>(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = value.toLowerCase();
|
const lowerCaseValue = value.toLowerCase();
|
||||||
if (field === "mac") {
|
if (field === "mac") {
|
||||||
return _.includes(
|
return _.includes(
|
||||||
value.replace(/:/g, ""),
|
lowerCaseValue.replace(/:/g, ""),
|
||||||
query.replace(/:/g, "")
|
query.replace(/:/g, "")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _.includes(value, query);
|
return _.includes(lowerCaseValue, query);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = restParams.filters;
|
const filters = restParams.filters;
|
||||||
|
|
||||||
function filtersMatch(entity: Entity): boolean {
|
function filtersMatch(entity: E): boolean {
|
||||||
if (isUndefined(filters) || _.isEmpty(filters)) {
|
if (isUndefined(filters) || _.isEmpty(filters)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -275,9 +275,13 @@ export function filter<E>(
|
||||||
if (key.startsWith("has")) {
|
if (key.startsWith("has")) {
|
||||||
const entityKey =
|
const entityKey =
|
||||||
key.substring(3, 4).toLowerCase() + key.substring(4);
|
key.substring(3, 4).toLowerCase() + key.substring(4);
|
||||||
return _.isEmpty(entity[entityKey]).toString() !== value;
|
return (
|
||||||
|
_.isEmpty(
|
||||||
|
getFieldIfExists(entity, entityKey)
|
||||||
|
).toString() !== value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return entity[key] === value;
|
return getFieldIfExists(entity, key) === value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +291,8 @@ export function filter<E>(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sort<
|
export function sort<
|
||||||
Type extends { [Key in SortField]: unknown },
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
Type extends { [Key in SortField]: any },
|
||||||
SortField extends string
|
SortField extends string
|
||||||
>(
|
>(
|
||||||
entities: Type[],
|
entities: Type[],
|
||||||
|
@ -303,8 +308,8 @@ export function sort<
|
||||||
|
|
||||||
const sorted = entities.slice(0);
|
const sorted = entities.slice(0);
|
||||||
sorted.sort((a, b) => {
|
sorted.sort((a, b) => {
|
||||||
let as: any = a[sortField];
|
let as = a[sortField];
|
||||||
let bs: any = b[sortField];
|
let bs = b[sortField];
|
||||||
|
|
||||||
if (isString(as)) {
|
if (isString(as)) {
|
||||||
as = as.toLowerCase();
|
as = as.toLowerCase();
|
||||||
|
|
Loading…
Reference in a new issue