forked from mystiq/hydrogen-web
Merge pull request #601 from vector-im/filter-token
Ensure unwanted data do not end up in logs
This commit is contained in:
commit
19827a0b5b
3 changed files with 55 additions and 12 deletions
|
@ -17,15 +17,17 @@ limitations under the License.
|
||||||
|
|
||||||
import {LogItem} from "./LogItem";
|
import {LogItem} from "./LogItem";
|
||||||
import {LogLevel, LogFilter} from "./LogFilter";
|
import {LogLevel, LogFilter} from "./LogFilter";
|
||||||
import type {ILogger, ILogExport, FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./types";
|
import type {ILogger, ILogExport, FilterCreator, LabelOrValues, LogCallback, ILogItem, ISerializedItem} from "./types";
|
||||||
import type {Platform} from "../platform/web/Platform.js";
|
import type {Platform} from "../platform/web/Platform.js";
|
||||||
|
|
||||||
export abstract class BaseLogger implements ILogger {
|
export abstract class BaseLogger implements ILogger {
|
||||||
protected _openItems: Set<LogItem> = new Set();
|
protected _openItems: Set<LogItem> = new Set();
|
||||||
protected _platform: Platform;
|
protected _platform: Platform;
|
||||||
|
protected _serializedTransformer: (item: ISerializedItem) => ISerializedItem;
|
||||||
|
|
||||||
constructor({platform}) {
|
constructor({platform, serializedTransformer = (item: ISerializedItem) => item}) {
|
||||||
this._platform = platform;
|
this._platform = platform;
|
||||||
|
this._serializedTransformer = serializedTransformer;
|
||||||
}
|
}
|
||||||
|
|
||||||
log(labelOrValues: LabelOrValues, logLevel: LogLevel = LogLevel.Info): void {
|
log(labelOrValues: LabelOrValues, logLevel: LogLevel = LogLevel.Info): void {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import {BaseLogger} from "./BaseLogger";
|
||||||
import type {Interval} from "../platform/web/dom/Clock";
|
import type {Interval} from "../platform/web/dom/Clock";
|
||||||
import type {Platform} from "../platform/web/Platform.js";
|
import type {Platform} from "../platform/web/Platform.js";
|
||||||
import type {BlobHandle} from "../platform/web/dom/BlobHandle.js";
|
import type {BlobHandle} from "../platform/web/dom/BlobHandle.js";
|
||||||
import type {ILogItem, ILogExport} from "./types";
|
import type {ILogItem, ILogExport, ISerializedItem} from "./types";
|
||||||
import type {LogFilter} from "./LogFilter";
|
import type {LogFilter} from "./LogFilter";
|
||||||
|
|
||||||
type QueuedItem = {
|
type QueuedItem = {
|
||||||
|
@ -40,7 +40,7 @@ export class IDBLogger extends BaseLogger {
|
||||||
private readonly _flushInterval: Interval;
|
private readonly _flushInterval: Interval;
|
||||||
private _queuedItems: QueuedItem[];
|
private _queuedItems: QueuedItem[];
|
||||||
|
|
||||||
constructor(options: {name: string, flushInterval?: number, limit?: number, platform: Platform}) {
|
constructor(options: {name: string, flushInterval?: number, limit?: number, platform: Platform, serializedTransformer?: (item: ISerializedItem) => ISerializedItem}) {
|
||||||
super(options);
|
super(options);
|
||||||
const {name, flushInterval = 60 * 1000, limit = 3000} = options;
|
const {name, flushInterval = 60 * 1000, limit = 3000} = options;
|
||||||
this._name = name;
|
this._name = name;
|
||||||
|
@ -119,10 +119,13 @@ export class IDBLogger extends BaseLogger {
|
||||||
|
|
||||||
_persistItem(logItem: ILogItem, filter: LogFilter, forced: boolean): void {
|
_persistItem(logItem: ILogItem, filter: LogFilter, forced: boolean): void {
|
||||||
const serializedItem = logItem.serialize(filter, undefined, forced);
|
const serializedItem = logItem.serialize(filter, undefined, forced);
|
||||||
|
if (serializedItem) {
|
||||||
|
const transformedSerializedItem = this._serializedTransformer(serializedItem);
|
||||||
this._queuedItems.push({
|
this._queuedItems.push({
|
||||||
json: JSON.stringify(serializedItem)
|
json: JSON.stringify(transformedSerializedItem)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_persistQueuedItems(items: QueuedItem[]): void {
|
_persistQueuedItems(items: QueuedItem[]): void {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -132,11 +132,7 @@ export class Platform {
|
||||||
this.clock = new Clock();
|
this.clock = new Clock();
|
||||||
this.encoding = new Encoding();
|
this.encoding = new Encoding();
|
||||||
this.random = Math.random;
|
this.random = Math.random;
|
||||||
if (options?.development) {
|
this._createLogger(options?.development);
|
||||||
this.logger = new ConsoleLogger({platform: this});
|
|
||||||
} else {
|
|
||||||
this.logger = new IDBLogger({name: "hydrogen_logs", platform: this});
|
|
||||||
}
|
|
||||||
this.history = new History();
|
this.history = new History();
|
||||||
this.onlineStatus = new OnlineStatus();
|
this.onlineStatus = new OnlineStatus();
|
||||||
this._serviceWorkerHandler = null;
|
this._serviceWorkerHandler = null;
|
||||||
|
@ -162,6 +158,21 @@ export class Platform {
|
||||||
this._disposables = new Disposables();
|
this._disposables = new Disposables();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_createLogger(isDevelopment) {
|
||||||
|
// Make sure that loginToken does not end up in the logs
|
||||||
|
const transformer = (item) => {
|
||||||
|
if (item.e?.stack) {
|
||||||
|
item.e.stack = item.e.stack.replace(/(?<=\/\?loginToken=).+/, "<snip>");
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
if (isDevelopment) {
|
||||||
|
this.logger = new ConsoleLogger({platform: this});
|
||||||
|
} else {
|
||||||
|
this.logger = new IDBLogger({name: "hydrogen_logs", platform: this, serializedTransformer: transformer});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get updateService() {
|
get updateService() {
|
||||||
return this._serviceWorkerHandler;
|
return this._serviceWorkerHandler;
|
||||||
}
|
}
|
||||||
|
@ -272,3 +283,30 @@ export class Platform {
|
||||||
this._disposables.dispose();
|
this._disposables.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import {LogItem} from "../../logging/LogItem";
|
||||||
|
export function tests() {
|
||||||
|
return {
|
||||||
|
"loginToken should not be in logs": (assert) => {
|
||||||
|
const transformer = (item) => {
|
||||||
|
if (item.e?.stack) {
|
||||||
|
item.e.stack = item.e.stack.replace(/(?<=\/\?loginToken=).+/, "<snip>");
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
const logger = {
|
||||||
|
_queuedItems: [],
|
||||||
|
_serializedTransformer: transformer,
|
||||||
|
_now: () => {}
|
||||||
|
};
|
||||||
|
logger.persist = IDBLogger.prototype._persistItem.bind(logger);
|
||||||
|
const logItem = new LogItem("test", 1, logger);
|
||||||
|
logItem.error = new Error();
|
||||||
|
logItem.error.stack = "main http://localhost:3000/src/main.js:55\n<anonymous> http://localhost:3000/?loginToken=secret:26"
|
||||||
|
logger.persist(logItem, null, false);
|
||||||
|
const item = logger._queuedItems.pop();
|
||||||
|
console.log(item);
|
||||||
|
assert.strictEqual(item.json.search("secret"), -1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue