Add Zod for runtime and compile-time type checking, use it in logging code

This commit is contained in:
Evan Hahn 2021-04-01 12:37:10 -05:00 committed by Josh Perez
parent c711fbe0c0
commit eb97c1194a
6 changed files with 58 additions and 56 deletions

View File

@ -3058,3 +3058,27 @@ Signal Desktop makes use of the following open source projects.
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
## zod
MIT License
Copyright (c) 2020 Colin McDonnell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -154,7 +154,8 @@
"underscore": "1.9.0",
"uuid": "3.3.2",
"websocket": "1.0.28",
"zkgroup": "https://github.com/signalapp/signal-zkgroup-node.git#2d7db946cc88492b65cc66e9aa9de0c9e664fd8d"
"zkgroup": "https://github.com/signalapp/signal-zkgroup-node.git#2d7db946cc88492b65cc66e9aa9de0c9e664fd8d",
"zod": "1.11.13"
},
"devDependencies": {
"@babel/core": "7.7.7",

View File

@ -1,6 +1,7 @@
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as z from 'zod';
import FormData from 'form-data';
import { gzip } from 'zlib';
import pify from 'pify';
@ -9,28 +10,21 @@ import { getUserAgent } from '../util/getUserAgent';
const BASE_URL = 'https://debuglogs.org';
const isObject = (value: unknown): value is Record<string, unknown> =>
typeof value === 'object' && !Array.isArray(value) && Boolean(value);
const tokenBodySchema = z
.object({
fields: z.record(z.unknown()),
url: z.string(),
})
.nonstrict();
const parseTokenBody = (
body: unknown
rawBody: unknown
): { fields: Record<string, unknown>; url: string } => {
if (!isObject(body)) {
throw new Error('Token body is not an object');
}
const body = tokenBodySchema.parse(rawBody);
const { fields, url } = body as Record<string, unknown>;
if (!isObject(fields)) {
throw new Error('Token body\'s "fields" key is not an object');
}
if (typeof url !== 'string') {
throw new Error('Token body\'s "url" key is not a string');
}
let parsedUrl: URL;
try {
parsedUrl = new URL(url);
parsedUrl = new URL(body.url);
} catch (err) {
throw new Error("Token body's URL was not a valid URL");
}
@ -38,7 +32,7 @@ const parseTokenBody = (
throw new Error("Token body's URL was not HTTPS");
}
return { fields, url };
return body;
};
export const uploadDebugLogs = async (

View File

@ -1,6 +1,7 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as z from 'zod';
import * as pino from 'pino';
import { redactAll } from '../../js/modules/privacy';
import { missingCaseError } from '../util/missingCaseError';
@ -19,37 +20,14 @@ export enum LogLevel {
// These match [Pino's core fields][1].
// [1]: https://getpino.io/#/?id=usage
export type LogEntryType = {
level: LogLevel;
msg: string;
time: string;
};
const logEntrySchema = z.object({
level: z.nativeEnum(LogLevel),
msg: z.string(),
time: z.string().refine(value => !Number.isNaN(new Date(value).getTime())),
});
export type LogEntryType = z.infer<typeof logEntrySchema>;
const logLevels = new Set<LogLevel>([
LogLevel.Fatal,
LogLevel.Error,
LogLevel.Warn,
LogLevel.Info,
LogLevel.Debug,
LogLevel.Trace,
]);
function isLogLevel(value: unknown): value is LogLevel {
return typeof value === 'number' && logLevels.has(value);
}
function isValidTime(value: unknown): value is string {
return typeof value === 'string' && !Number.isNaN(new Date(value).getTime());
}
export function isLogEntry(value: unknown): value is LogEntryType {
if (!value || typeof value !== 'object' || Array.isArray(value)) {
return false;
}
const { level, time, msg } = value as Record<string, unknown>;
return typeof msg === 'string' && isLogLevel(level) && isValidTime(time);
}
export const isLogEntry = logEntrySchema.check.bind(logEntrySchema);
export function getLogLevelString(value: LogLevel): pino.Level {
switch (value) {

View File

@ -14802,7 +14802,7 @@
"rule": "jQuery-append(",
"path": "ts/logging/debuglogs.js",
"line": " form.append('key', fields.key);",
"lineNumber": 45,
"lineNumber": 61,
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
@ -14810,7 +14810,7 @@
"rule": "jQuery-append(",
"path": "ts/logging/debuglogs.js",
"line": " form.append(key, value);",
"lineNumber": 49,
"lineNumber": 65,
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
@ -14818,7 +14818,7 @@
"rule": "jQuery-append(",
"path": "ts/logging/debuglogs.js",
"line": " form.append('Content-Type', contentType);",
"lineNumber": 53,
"lineNumber": 69,
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
@ -14826,7 +14826,7 @@
"rule": "jQuery-append(",
"path": "ts/logging/debuglogs.js",
"line": " form.append('file', contentBuffer, {",
"lineNumber": 54,
"lineNumber": 70,
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
@ -14834,7 +14834,7 @@
"rule": "jQuery-append(",
"path": "ts/logging/debuglogs.ts",
"line": " form.append('key', fields.key);",
"lineNumber": 55,
"lineNumber": 49,
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
@ -14842,7 +14842,7 @@
"rule": "jQuery-append(",
"path": "ts/logging/debuglogs.ts",
"line": " form.append(key, value);",
"lineNumber": 59,
"lineNumber": 53,
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
@ -14850,7 +14850,7 @@
"rule": "jQuery-append(",
"path": "ts/logging/debuglogs.ts",
"line": " form.append('Content-Type', contentType);",
"lineNumber": 64,
"lineNumber": 58,
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},
@ -14858,7 +14858,7 @@
"rule": "jQuery-append(",
"path": "ts/logging/debuglogs.ts",
"line": " form.append('file', contentBuffer, {",
"lineNumber": 65,
"lineNumber": 59,
"reasonCategory": "falseMatch",
"updated": "2020-12-17T18:08:07.752Z"
},

View File

@ -17620,3 +17620,8 @@ zip-stream@^1.2.0:
ffi-napi "2.4.5"
ref-array-napi "1.2.0"
ref-napi "1.4.2"
zod@1.11.13:
version "1.11.13"
resolved "https://registry.yarnpkg.com/zod/-/zod-1.11.13.tgz#6acb1e52b670afeb816ce2e2ddf6ab359f9ea506"
integrity sha512-10+KA7eWa8g1hbKIXkOnhjJ4RKEwX85ECz3VJzP+pWkJOFKn76bHy1kG0d1JHBwmdElLcCsaB0O9HqIfT1vZnw==