@fluidframework/debugger 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"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"}
package/dist/sanitizer.js CHANGED
@@ -564,33 +564,37 @@ class Sanitizer {
564
564
  msgContents = message.contents;
565
565
  }
566
566
  // handle container message types
567
- if (msgContents.type === "attach") {
568
- // this one is like a regular attach op, except its contents aren't nested as deep
569
- // run fixAttach directly and return
570
- this.fixAttach(msgContents);
571
- }
572
- else if (msgContents.type === "component") {
573
- // this one functionally nests its contents one layer deeper
574
- // bring up the contents object and continue as usual
575
- this.fixOpContentsObject(msgContents.contents);
576
- }
577
- else if (msgContents.type === "chunkedOp") {
578
- // this is a (regular?) op split into multiple parts due to size, e.g. because it
579
- // has an attached image, and where the chunkedOp is within the top-level op's contents
580
- // (as opposed to being at the top-level). The contents of the chunks need to be
581
- // concatenated to form the complete stringified json object
582
- // Early return here to skip re-stringify because no changes are made until the last
583
- // chunk, and the ChunkedOpProcessor will handle everything at that point
584
- return this.fixChunkedOp(message);
585
- }
586
- else if (msgContents.type === "blobAttach") {
587
- // TODO: handle this properly once blob api is used
588
- this.debugMsg("TODO: blobAttach ops are skipped/unhandled");
589
- return;
590
- }
591
- else {
592
- // A regular op
593
- this.fixOpContentsObject(msgContents);
567
+ switch (msgContents.type) {
568
+ case "attach": {
569
+ // this one is like a regular attach op, except its contents aren't nested as deep
570
+ // run fixAttach directly and return
571
+ this.fixAttach(msgContents);
572
+ break;
573
+ }
574
+ case "component": {
575
+ // this one functionally nests its contents one layer deeper
576
+ // bring up the contents object and continue as usual
577
+ this.fixOpContentsObject(msgContents.contents);
578
+ break;
579
+ }
580
+ case "chunkedOp": {
581
+ // this is a (regular?) op split into multiple parts due to size, e.g. because it
582
+ // has an attached image, and where the chunkedOp is within the top-level op's contents
583
+ // (as opposed to being at the top-level). The contents of the chunks need to be
584
+ // concatenated to form the complete stringified json object
585
+ // Early return here to skip re-stringify because no changes are made until the last
586
+ // chunk, and the ChunkedOpProcessor will handle everything at that point
587
+ return this.fixChunkedOp(message);
588
+ }
589
+ case "blobAttach": {
590
+ // TODO: handle this properly once blob api is used
591
+ this.debugMsg("TODO: blobAttach ops are skipped/unhandled");
592
+ return;
593
+ }
594
+ default: {
595
+ // A regular op
596
+ this.fixOpContentsObject(msgContents);
597
+ }
594
598
  }
595
599
  // re-stringify the json if needed
596
600
  if (typeof message.contents === "string") {
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * This tool cleans up a message.json file downloaded through fluid-fetch to remove\n * user content and user identifying information. Enough information can be retained\n * to allow loading through Fluid Preview, or everything can be scrubbed so that only\n * replay-tool can read the result. Anonymous identifying information such as client\n * IDs are always retained. Object keys are NOT scrubbed, including those that are\n * nested within values (only leaf values are scrubbed).\n *\n * Note: While user content/information is scrubbed, it should not be assumed to be\n * fully anonymized because certain meta-information (such as word lengths and\n * consistent replacement) are preserved.\n *\n * Messages must match known structures when scrubbing for Fluid Preview.\n */\n\nimport * as Validator from \"jsonschema\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport {\n ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n attachContentsSchema,\n chunkedOpContentsSchema,\n joinContentsSchema,\n joinDataSchema,\n opContentsMapSchema,\n opContentsSchema,\n opContentsMergeTreeDeltaOpSchema,\n opContentsMergeTreeGroupOpSchema,\n opContentsRegisterCollectionSchema,\n proposeContentsSchema,\n} from \"./messageSchema\";\n\nenum TextType {\n Generic,\n Email,\n Name,\n FluidObject,\n MapKey,\n}\n\n// Workaround to jsonschema package not supporting \"false\" as a schema\n// that matches nothing\nconst falseResult = {\n valid: false,\n toString: () => { return \"Unmatched format\"; },\n};\n\n/**\n * Class that takes chunkedOp messages and can provide their concatenated\n * contents along with re-write sanitized content in-place back into the\n * messages. Assumes sanitized messages are always less than or equal in\n * size to the original message.\n */\nclass ChunkedOpProcessor {\n /**\n * Message references so we can replace their contents in-place. These can\n * be top-level chunkedOp messages, or top-level op messages with a chunkedOp\n * within the contents\n */\n private messages = new Array<any>();\n /**\n * The messages' parsed contents for processing. Should parallel the\n * messages member\n */\n private parsedMessageContents = new Array<any>();\n private writtenBack = false;\n /**\n * keep track of the total starting length to make sure we don't somehow end\n * up with more content than we started with (meaning we may not be able to\n * write it back)\n */\n private concatenatedLength = 0;\n\n constructor(\n readonly validateSchemaFn: (object: any, schema: any) => boolean,\n readonly debug: boolean,\n ) { }\n\n debugMsg(msg: any) {\n if (this.debug) {\n console.error(msg);\n }\n }\n\n addMessage(message: any): void {\n this.messages.push(message);\n\n let parsed;\n try {\n parsed = JSON.parse(message.contents);\n if (message.type === \"op\") {\n // nested within a regular op\n // need to go deeper to get the desired contents\n parsed = parsed.contents;\n }\n } catch (e) {\n this.debugMsg(e);\n this.debugMsg(message.contents);\n }\n this.validateSchemaFn(parsed, chunkedOpContentsSchema);\n this.parsedMessageContents.push(parsed);\n }\n\n hasAllMessages(): boolean {\n const lastMsgContents = this.parsedMessageContents[this.parsedMessageContents.length - 1];\n return lastMsgContents.chunkId !== undefined && lastMsgContents.chunkId === lastMsgContents.totalChunks;\n }\n\n /**\n * @returns The concatenated contents of all the messages parsed as json\n */\n getConcatenatedContents(): any {\n const contentsString = this.parsedMessageContents.reduce((previousValue: string, currentValue: any) => {\n return previousValue + (currentValue.contents as string);\n }, \"\");\n\n this.concatenatedLength = contentsString.length;\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return JSON.parse(contentsString);\n } catch (e) {\n this.debugMsg(contentsString);\n this.debugMsg(e);\n return undefined;\n }\n }\n\n /**\n * Write back sanitized contents into the messages. The contents are\n * stringified, split up, and written in place to the messages that\n * were added earlier. The number of messages is preserved.\n * @param contents - Sanitized contents to write back\n */\n writeSanitizedContents(contents: any): void {\n // Write back a chunk size equal to the original\n const chunkSize = this.parsedMessageContents[0].contents.length;\n\n let stringified: string;\n try {\n stringified = JSON.stringify(contents);\n assert(stringified.length <= this.concatenatedLength,\n 0x089 /* \"Stringified length of chunk contents > total starting length\" */);\n } catch (e) {\n this.debugMsg(e);\n throw e;\n }\n\n for (let i = 0; i < this.messages.length; i++) {\n const substring = stringified.substring(i * chunkSize, (i + 1) * chunkSize);\n\n const parsedContents = this.parsedMessageContents[i];\n parsedContents.contents = substring;\n const message = this.messages[i];\n\n let stringifiedParsedContents;\n try {\n // for nested chunkedOps, we need to recreate the extra nesting layer\n // we removed earlier when adding the message\n if (message.type === \"op\") {\n const nestingLayer = {\n type: \"chunkedOp\",\n contents: parsedContents,\n };\n stringifiedParsedContents = JSON.stringify(nestingLayer);\n } else {\n stringifiedParsedContents = JSON.stringify(parsedContents);\n }\n } catch (e) {\n this.debugMsg(e);\n }\n\n message.contents = stringifiedParsedContents;\n }\n\n this.writtenBack = true;\n }\n\n reset(): void {\n assert(this.writtenBack, 0x08a /* \"resetting ChunkedOpProcessor that never wrote back its contents\" */);\n this.messages = new Array<any>();\n this.parsedMessageContents = new Array<any>();\n this.writtenBack = false;\n this.concatenatedLength = 0;\n }\n\n isPendingProcessing(): boolean {\n return this.messages.length !== 0;\n }\n}\n\nexport class Sanitizer {\n readonly validator = new Validator.Validator();\n // Represents the keys used to store Fluid object identifiers, snapshot info,\n // and other string fields that should not be replaced in contents blobs to\n // ensure the messages are still usable\n readonly defaultExcludedKeys = new Set<string>();\n // Represents the keys used by merge-tree ops their \"seg\" property, where other\n // keys represent user information\n readonly mergeTreeExcludedKeys = new Set<string>();\n // Map of user information to what it was replaced with. Used to ensure the same\n // data have the same replacements\n readonly replacementMap = new Map<string, string>();\n\n /**\n * Validate that the provided message matches the provided schema.\n * For a full scrub, warn and continue (scrubber should fully sanitize unexpected\n * fields for ops), otherwise throw an error because we cannot be sure user\n * information is being sufficiently sanitized.\n */\n objectMatchesSchema = (object: any, schema: any): boolean => {\n const result = schema === false ? falseResult : this.validator.validate(object, schema);\n if (!result.valid) {\n const errorMsg = `Bad msg fmt:\\n${result.toString()}\\n${JSON.stringify(object, undefined, 2)}`;\n\n if (this.fullScrub || this.noBail) {\n this.debugMsg(errorMsg);\n } else {\n throw new Error(errorMsg);\n }\n }\n return result.valid;\n };\n\n readonly chunkProcessor = new ChunkedOpProcessor(this.objectMatchesSchema, this.debug);\n\n constructor(\n readonly messages: ISequencedDocumentMessage[],\n readonly fullScrub: boolean,\n readonly noBail: boolean,\n readonly debug: boolean = false,\n ) {\n this.defaultExcludedKeys.add(\"type\");\n this.defaultExcludedKeys.add(\"id\");\n this.defaultExcludedKeys.add(\"pkg\");\n this.defaultExcludedKeys.add(\"snapshotFormatVersion\");\n this.defaultExcludedKeys.add(\"packageVersion\");\n this.mergeTreeExcludedKeys.add(\"nodeType\");\n }\n\n debugMsg(msg: any) {\n if (this.debug) {\n console.error(msg);\n }\n }\n\n isFluidObjectKey(key: string): boolean {\n return key === \"type\" || key === \"id\";\n }\n\n getRandomText(len: number): string {\n let str = \"\";\n while (str.length < len) {\n str = str + Math.random().toString(36).substring(2);\n }\n return str.substr(0, len);\n }\n\n readonly wordTokenRegex = /\\S+/g;\n\n readonly replaceRandomTextFn = (match: string): string => {\n if (this.replacementMap.has(match)) {\n return this.replacementMap.get(match)!;\n }\n\n const replacement = this.getRandomText(match.length);\n this.replacementMap.set(match, replacement);\n return replacement;\n };\n\n /**\n * Replace text with garbage. FluidObject types are not replaced when not under\n * full scrub mode. All other text is replaced consistently.\n */\n replaceText(input?: string, type: TextType = TextType.Generic): string | undefined {\n if (input === undefined) {\n return undefined;\n }\n\n if (type === TextType.FluidObject) {\n if (this.replacementMap.has(input)) {\n return this.replacementMap.get(input)!;\n }\n\n let replacement: string;\n if (this.fullScrub) {\n replacement = this.getRandomText(input.length);\n } else {\n replacement = input;\n }\n\n this.replacementMap.set(input, replacement);\n return replacement;\n }\n\n return input.replace(this.wordTokenRegex, this.replaceRandomTextFn);\n }\n\n replaceArray(input: any[]): any[] {\n for (let i = 0; i < input.length; i++) {\n const value = input[i];\n if (typeof value === \"string\") {\n input[i] = this.replaceText(value);\n } else if (Array.isArray(value)) {\n input[i] = this.replaceArray(value);\n } else if (typeof value === \"object\") {\n input[i] = this.replaceObject(value);\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n /**\n * (sort of) recurses down the values of a JSON object to sanitize all its strings\n * (only checks strings, arrays, and objects)\n * @param input - The object to sanitize\n * @param excludedKeys - object keys for which to skip replacement when not in fullScrub\n */\n // eslint-disable-next-line @typescript-eslint/ban-types\n replaceObject(input: object | null, excludedKeys: Set<string> = this.defaultExcludedKeys): object | null {\n // File might contain actual nulls\n if (input === null || input === undefined) {\n return input;\n }\n\n const keys = Object.keys(input);\n keys.forEach((key) => {\n if (this.fullScrub || !excludedKeys.has(key)) {\n const value = input[key];\n if (typeof value === \"string\") {\n input[key] = this.replaceText(\n value,\n this.isFluidObjectKey(key) ? TextType.FluidObject : TextType.Generic,\n );\n } else if (Array.isArray(value)) {\n input[key] = this.replaceArray(value);\n } else if (typeof value === \"object\") {\n input[key] = this.replaceObject(value, excludedKeys);\n }\n }\n });\n return input;\n }\n\n /**\n * Replacement on an unknown type or a parsed root level object\n * without a key\n * @param input - The object to sanitize\n * @param excludedKeys - object keys for which to skip replacement when not in fullScrub\n */\n replaceAny(input: any, excludedKeys: Set<string> = this.defaultExcludedKeys): any {\n if (input === null || input === undefined) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n if (typeof input === \"string\") {\n return this.replaceText(input);\n } else if (Array.isArray(input)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return this.replaceArray(input);\n } else if (typeof input === \"object\") {\n return this.replaceObject(input, excludedKeys);\n }\n\n // Don't run replacement on any other types\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n fixJoin(message: any) {\n if (!this.objectMatchesSchema(message.contents, joinContentsSchema)) {\n message.contents = this.replaceAny(message.contents);\n }\n\n try {\n let data = JSON.parse(message.data);\n if (!this.objectMatchesSchema(data, joinDataSchema)) {\n data = this.replaceAny(data);\n } else {\n const user = data.detail.user;\n user.id = this.replaceText(user.id, TextType.Email);\n user.email = this.replaceText(user.email, TextType.Email);\n user.name = this.replaceText(user.name, TextType.Name);\n }\n\n message.data = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n }\n }\n\n fixPropose(message: any) {\n if (!this.objectMatchesSchema(message.contents, proposeContentsSchema)) {\n message.contents = this.replaceAny(message.contents);\n } else {\n if (typeof message.contents === \"string\") {\n try {\n const data = JSON.parse(message.contents);\n if (this.fullScrub) {\n const pkg = data.value?.package;\n if (pkg?.name) {\n pkg.name = this.replaceText(pkg.name, TextType.FluidObject);\n }\n if (Array.isArray(pkg?.fluid?.browser?.umd?.files)) {\n pkg.fluid.browser.umd.files = this.replaceArray(pkg.fluid.browser.umd.files);\n }\n }\n } catch (e) {\n this.debugMsg(e);\n }\n } else {\n if (this.fullScrub) {\n message.contents.value = this.replaceText(message.contents.value, TextType.FluidObject);\n }\n }\n }\n }\n\n fixAttachEntries(entries: any[]) {\n entries.forEach((element) => {\n // Tree type\n if (element.value.entries) {\n this.fixAttachEntries(element.value.entries);\n } else {\n // Blob (leaf) type\n try {\n if (typeof element.value.contents === \"string\") {\n let data = JSON.parse(element.value.contents);\n data = this.replaceObject(data);\n element.value.contents = JSON.stringify(data);\n }\n } catch (e) {\n this.debugMsg(e);\n }\n }\n });\n }\n\n /**\n * Fix the content of an attach in place\n * @param contents - contents object to fix\n */\n fixAttachContents(contents: any): any {\n assert(typeof contents === \"object\", 0x08b /* \"Unexpected type on contents for fix of an attach!\" */);\n if (!this.objectMatchesSchema(contents, attachContentsSchema)) {\n this.replaceObject(contents);\n } else {\n if (this.fullScrub) {\n contents.id = this.replaceText(contents.id, TextType.FluidObject);\n contents.type = this.replaceText(contents.type, TextType.FluidObject);\n }\n\n this.fixAttachEntries(contents.snapshot.entries);\n }\n }\n\n /**\n * Fix an attach message at the root level or a ContainerMessageType attach. Attach\n * messages found within an op message should instead have their contents parsed out\n * and sent to fixAttachContents.\n * @param message - The attach message to fix\n * @param withinOp - If the message is from within an op message (as opposed to being\n * an attach message at the root level). Root level attach messages have \"snapshot\"\n * under a \"contents\" key, whereas attach messages from within an op message have it\n * under a \"content\" key\n */\n fixAttach(message: any) {\n // Handle case where contents is stringified json\n if (typeof message.contents === \"string\") {\n try {\n const data = JSON.parse(message.contents);\n this.fixAttachContents(data);\n message.contents = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n } else {\n this.fixAttachContents(message.contents);\n }\n }\n\n fixDeltaOp(deltaOp: any) {\n if (typeof deltaOp.seg === \"string\") {\n deltaOp.seg = this.replaceText(deltaOp.seg);\n } else {\n deltaOp.seg = this.replaceObject(deltaOp.seg, this.mergeTreeExcludedKeys);\n }\n }\n\n /**\n * Fix the contents object for an op message. Does not do extra type handling. Does\n * not handle special container message types like \"attach\", \"component\", and\n * \"chunkedOp\" (these should be handled by the caller)\n * @param contents - The contents object for an op message. If it was a string in the\n * message, it must have been converted to an object first\n */\n fixOpContentsObject(contents: any) {\n // do replacement\n if (!this.objectMatchesSchema(contents, opContentsSchema)) {\n this.replaceAny(contents);\n } else {\n if (this.fullScrub) {\n contents.address = this.replaceText(contents.address, TextType.FluidObject);\n }\n\n const innerContent = contents.contents.content;\n assert(innerContent !== undefined, 0x08c /* \"innerContent for fixing op contents is undefined!\" */);\n if (contents.contents.type === \"attach\") {\n // attach op\n // handle case where inner content is stringified json\n if (typeof contents.contents.content === \"string\") {\n try {\n const data = JSON.parse(contents.contents.content);\n this.fixAttachContents(data);\n contents.contents.content = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n }\n } else {\n this.fixAttachContents(contents.contents.content);\n }\n } else if (this.validator.validate(innerContent, opContentsMapSchema).valid) {\n // map op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n innerContent.contents.key = this.replaceText(innerContent.contents.key, TextType.MapKey);\n }\n if (innerContent.contents.value !== undefined) {\n innerContent.contents.value.value = this.replaceAny(innerContent.contents.value.value);\n }\n } else if (this.validator.validate(innerContent, opContentsMergeTreeGroupOpSchema).valid) {\n // merge tree group op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n }\n innerContent.contents.ops.forEach((deltaOp) => {\n this.fixDeltaOp(deltaOp);\n });\n } else if (this.validator.validate(innerContent, opContentsMergeTreeDeltaOpSchema).valid) {\n // merge tree delta op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n }\n this.fixDeltaOp(innerContent.contents);\n } else if (this.validator.validate(innerContent, opContentsRegisterCollectionSchema).valid) {\n // register collection op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n innerContent.contents.key = this.replaceText(innerContent.contents.key, TextType.MapKey);\n }\n if (innerContent.contents.value !== undefined) {\n innerContent.contents.value.value = this.replaceAny(innerContent.contents.value.value);\n }\n } else {\n // message contents don't match any known op format\n this.objectMatchesSchema(contents, false);\n }\n }\n }\n\n fixOp(message: any) {\n // handle case where contents is stringified json\n let msgContents;\n if (typeof message.contents === \"string\") {\n try {\n msgContents = JSON.parse(message.contents);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n } else {\n msgContents = message.contents;\n }\n\n // handle container message types\n if (msgContents.type === \"attach\") {\n // this one is like a regular attach op, except its contents aren't nested as deep\n // run fixAttach directly and return\n this.fixAttach(msgContents);\n } else if (msgContents.type === \"component\") {\n // this one functionally nests its contents one layer deeper\n // bring up the contents object and continue as usual\n this.fixOpContentsObject(msgContents.contents);\n } else if (msgContents.type === \"chunkedOp\") {\n // this is a (regular?) op split into multiple parts due to size, e.g. because it\n // has an attached image, and where the chunkedOp is within the top-level op's contents\n // (as opposed to being at the top-level). The contents of the chunks need to be\n // concatenated to form the complete stringified json object\n // Early return here to skip re-stringify because no changes are made until the last\n // chunk, and the ChunkedOpProcessor will handle everything at that point\n return this.fixChunkedOp(message);\n } else if (msgContents.type === \"blobAttach\") {\n // TODO: handle this properly once blob api is used\n this.debugMsg(\"TODO: blobAttach ops are skipped/unhandled\");\n return;\n } else {\n // A regular op\n this.fixOpContentsObject(msgContents);\n }\n\n // re-stringify the json if needed\n if (typeof message.contents === \"string\") {\n try {\n message.contents = JSON.stringify(msgContents);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n }\n }\n\n /**\n * @param message - The top-level chunkedOp message or a top-level op message\n * with a chunkedOp inside its contents\n */\n fixChunkedOp(message: any) {\n this.chunkProcessor.addMessage(message);\n if (!this.chunkProcessor.hasAllMessages()) {\n return;\n }\n\n const contents = this.chunkProcessor.getConcatenatedContents();\n this.fixOpContentsObject(contents);\n\n this.chunkProcessor.writeSanitizedContents(contents);\n this.chunkProcessor.reset();\n }\n\n sanitize(): ISequencedDocumentMessage[] {\n let seq = 0;\n\n try {\n this.messages.map((message) => {\n seq = message.sequenceNumber;\n // message types from protocol-definitions' protocol.ts\n switch (message.type) {\n case \"join\": {\n this.fixJoin(message);\n break;\n }\n case \"propose\": {\n this.fixPropose(message);\n break;\n }\n case \"attach\": {\n this.fixAttach(message);\n break;\n }\n case \"op\": {\n this.fixOp(message);\n break;\n }\n case \"chunkedOp\": {\n this.fixChunkedOp(message);\n break;\n }\n case \"noop\":\n case \"leave\":\n case \"noClient\":\n case \"summarize\":\n case \"summaryAck\":\n case \"summaryNack\":\n break;\n default:\n this.debugMsg(`Unexpected op type ${message.type}`);\n }\n });\n\n // make sure we don't miss an incomplete chunked op at the end\n assert(!this.chunkProcessor.isPendingProcessing(), 0x08d /* \"After sanitize, pending incomplete ops!\" */);\n } catch (error) {\n this.debugMsg(`Error while processing sequenceNumber ${seq}`);\n throw error;\n }\n\n return this.messages;\n }\n}\n"]}
1
+ {"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * This tool cleans up a message.json file downloaded through fluid-fetch to remove\n * user content and user identifying information. Enough information can be retained\n * to allow loading through Fluid Preview, or everything can be scrubbed so that only\n * replay-tool can read the result. Anonymous identifying information such as client\n * IDs are always retained. Object keys are NOT scrubbed, including those that are\n * nested within values (only leaf values are scrubbed).\n *\n * Note: While user content/information is scrubbed, it should not be assumed to be\n * fully anonymized because certain meta-information (such as word lengths and\n * consistent replacement) are preserved.\n *\n * Messages must match known structures when scrubbing for Fluid Preview.\n */\n\nimport * as Validator from \"jsonschema\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport {\n ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n attachContentsSchema,\n chunkedOpContentsSchema,\n joinContentsSchema,\n joinDataSchema,\n opContentsMapSchema,\n opContentsSchema,\n opContentsMergeTreeDeltaOpSchema,\n opContentsMergeTreeGroupOpSchema,\n opContentsRegisterCollectionSchema,\n proposeContentsSchema,\n} from \"./messageSchema\";\n\nenum TextType {\n Generic,\n Email,\n Name,\n FluidObject,\n MapKey,\n}\n\n// Workaround to jsonschema package not supporting \"false\" as a schema\n// that matches nothing\nconst falseResult = {\n valid: false,\n toString: () => { return \"Unmatched format\"; },\n};\n\n/**\n * Class that takes chunkedOp messages and can provide their concatenated\n * contents along with re-write sanitized content in-place back into the\n * messages. Assumes sanitized messages are always less than or equal in\n * size to the original message.\n */\nclass ChunkedOpProcessor {\n /**\n * Message references so we can replace their contents in-place. These can\n * be top-level chunkedOp messages, or top-level op messages with a chunkedOp\n * within the contents\n */\n private messages = new Array<any>();\n /**\n * The messages' parsed contents for processing. Should parallel the\n * messages member\n */\n private parsedMessageContents = new Array<any>();\n private writtenBack = false;\n /**\n * keep track of the total starting length to make sure we don't somehow end\n * up with more content than we started with (meaning we may not be able to\n * write it back)\n */\n private concatenatedLength = 0;\n\n constructor(\n readonly validateSchemaFn: (object: any, schema: any) => boolean,\n readonly debug: boolean,\n ) { }\n\n debugMsg(msg: any) {\n if (this.debug) {\n console.error(msg);\n }\n }\n\n addMessage(message: any): void {\n this.messages.push(message);\n\n let parsed;\n try {\n parsed = JSON.parse(message.contents);\n if (message.type === \"op\") {\n // nested within a regular op\n // need to go deeper to get the desired contents\n parsed = parsed.contents;\n }\n } catch (e) {\n this.debugMsg(e);\n this.debugMsg(message.contents);\n }\n this.validateSchemaFn(parsed, chunkedOpContentsSchema);\n this.parsedMessageContents.push(parsed);\n }\n\n hasAllMessages(): boolean {\n const lastMsgContents = this.parsedMessageContents[this.parsedMessageContents.length - 1];\n return lastMsgContents.chunkId !== undefined && lastMsgContents.chunkId === lastMsgContents.totalChunks;\n }\n\n /**\n * @returns The concatenated contents of all the messages parsed as json\n */\n getConcatenatedContents(): any {\n const contentsString = this.parsedMessageContents.reduce((previousValue: string, currentValue: any) => {\n return previousValue + (currentValue.contents as string);\n }, \"\");\n\n this.concatenatedLength = contentsString.length;\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return JSON.parse(contentsString);\n } catch (e) {\n this.debugMsg(contentsString);\n this.debugMsg(e);\n return undefined;\n }\n }\n\n /**\n * Write back sanitized contents into the messages. The contents are\n * stringified, split up, and written in place to the messages that\n * were added earlier. The number of messages is preserved.\n * @param contents - Sanitized contents to write back\n */\n writeSanitizedContents(contents: any): void {\n // Write back a chunk size equal to the original\n const chunkSize = this.parsedMessageContents[0].contents.length;\n\n let stringified: string;\n try {\n stringified = JSON.stringify(contents);\n assert(stringified.length <= this.concatenatedLength,\n 0x089 /* \"Stringified length of chunk contents > total starting length\" */);\n } catch (e) {\n this.debugMsg(e);\n throw e;\n }\n\n for (let i = 0; i < this.messages.length; i++) {\n const substring = stringified.substring(i * chunkSize, (i + 1) * chunkSize);\n\n const parsedContents = this.parsedMessageContents[i];\n parsedContents.contents = substring;\n const message = this.messages[i];\n\n let stringifiedParsedContents;\n try {\n // for nested chunkedOps, we need to recreate the extra nesting layer\n // we removed earlier when adding the message\n if (message.type === \"op\") {\n const nestingLayer = {\n type: \"chunkedOp\",\n contents: parsedContents,\n };\n stringifiedParsedContents = JSON.stringify(nestingLayer);\n } else {\n stringifiedParsedContents = JSON.stringify(parsedContents);\n }\n } catch (e) {\n this.debugMsg(e);\n }\n\n message.contents = stringifiedParsedContents;\n }\n\n this.writtenBack = true;\n }\n\n reset(): void {\n assert(this.writtenBack, 0x08a /* \"resetting ChunkedOpProcessor that never wrote back its contents\" */);\n this.messages = new Array<any>();\n this.parsedMessageContents = new Array<any>();\n this.writtenBack = false;\n this.concatenatedLength = 0;\n }\n\n isPendingProcessing(): boolean {\n return this.messages.length !== 0;\n }\n}\n\nexport class Sanitizer {\n readonly validator = new Validator.Validator();\n // Represents the keys used to store Fluid object identifiers, snapshot info,\n // and other string fields that should not be replaced in contents blobs to\n // ensure the messages are still usable\n readonly defaultExcludedKeys = new Set<string>();\n // Represents the keys used by merge-tree ops their \"seg\" property, where other\n // keys represent user information\n readonly mergeTreeExcludedKeys = new Set<string>();\n // Map of user information to what it was replaced with. Used to ensure the same\n // data have the same replacements\n readonly replacementMap = new Map<string, string>();\n\n /**\n * Validate that the provided message matches the provided schema.\n * For a full scrub, warn and continue (scrubber should fully sanitize unexpected\n * fields for ops), otherwise throw an error because we cannot be sure user\n * information is being sufficiently sanitized.\n */\n objectMatchesSchema = (object: any, schema: any): boolean => {\n const result = schema === false ? falseResult : this.validator.validate(object, schema);\n if (!result.valid) {\n const errorMsg = `Bad msg fmt:\\n${result.toString()}\\n${JSON.stringify(object, undefined, 2)}`;\n\n if (this.fullScrub || this.noBail) {\n this.debugMsg(errorMsg);\n } else {\n throw new Error(errorMsg);\n }\n }\n return result.valid;\n };\n\n readonly chunkProcessor = new ChunkedOpProcessor(this.objectMatchesSchema, this.debug);\n\n constructor(\n readonly messages: ISequencedDocumentMessage[],\n readonly fullScrub: boolean,\n readonly noBail: boolean,\n readonly debug: boolean = false,\n ) {\n this.defaultExcludedKeys.add(\"type\");\n this.defaultExcludedKeys.add(\"id\");\n this.defaultExcludedKeys.add(\"pkg\");\n this.defaultExcludedKeys.add(\"snapshotFormatVersion\");\n this.defaultExcludedKeys.add(\"packageVersion\");\n this.mergeTreeExcludedKeys.add(\"nodeType\");\n }\n\n debugMsg(msg: any) {\n if (this.debug) {\n console.error(msg);\n }\n }\n\n isFluidObjectKey(key: string): boolean {\n return key === \"type\" || key === \"id\";\n }\n\n getRandomText(len: number): string {\n let str = \"\";\n while (str.length < len) {\n str = str + Math.random().toString(36).substring(2);\n }\n return str.substr(0, len);\n }\n\n readonly wordTokenRegex = /\\S+/g;\n\n readonly replaceRandomTextFn = (match: string): string => {\n if (this.replacementMap.has(match)) {\n return this.replacementMap.get(match)!;\n }\n\n const replacement = this.getRandomText(match.length);\n this.replacementMap.set(match, replacement);\n return replacement;\n };\n\n /**\n * Replace text with garbage. FluidObject types are not replaced when not under\n * full scrub mode. All other text is replaced consistently.\n */\n replaceText(input?: string, type: TextType = TextType.Generic): string | undefined {\n if (input === undefined) {\n return undefined;\n }\n\n if (type === TextType.FluidObject) {\n if (this.replacementMap.has(input)) {\n return this.replacementMap.get(input)!;\n }\n\n let replacement: string;\n if (this.fullScrub) {\n replacement = this.getRandomText(input.length);\n } else {\n replacement = input;\n }\n\n this.replacementMap.set(input, replacement);\n return replacement;\n }\n\n return input.replace(this.wordTokenRegex, this.replaceRandomTextFn);\n }\n\n replaceArray(input: any[]): any[] {\n for (let i = 0; i < input.length; i++) {\n const value = input[i];\n if (typeof value === \"string\") {\n input[i] = this.replaceText(value);\n } else if (Array.isArray(value)) {\n input[i] = this.replaceArray(value);\n } else if (typeof value === \"object\") {\n input[i] = this.replaceObject(value);\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n /**\n * (sort of) recurses down the values of a JSON object to sanitize all its strings\n * (only checks strings, arrays, and objects)\n * @param input - The object to sanitize\n * @param excludedKeys - object keys for which to skip replacement when not in fullScrub\n */\n // eslint-disable-next-line @typescript-eslint/ban-types\n replaceObject(input: object | null, excludedKeys: Set<string> = this.defaultExcludedKeys): object | null {\n // File might contain actual nulls\n if (input === null || input === undefined) {\n return input;\n }\n\n const keys = Object.keys(input);\n keys.forEach((key) => {\n if (this.fullScrub || !excludedKeys.has(key)) {\n const value = input[key];\n if (typeof value === \"string\") {\n input[key] = this.replaceText(\n value,\n this.isFluidObjectKey(key) ? TextType.FluidObject : TextType.Generic,\n );\n } else if (Array.isArray(value)) {\n input[key] = this.replaceArray(value);\n } else if (typeof value === \"object\") {\n input[key] = this.replaceObject(value, excludedKeys);\n }\n }\n });\n return input;\n }\n\n /**\n * Replacement on an unknown type or a parsed root level object\n * without a key\n * @param input - The object to sanitize\n * @param excludedKeys - object keys for which to skip replacement when not in fullScrub\n */\n replaceAny(input: any, excludedKeys: Set<string> = this.defaultExcludedKeys): any {\n if (input === null || input === undefined) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n if (typeof input === \"string\") {\n return this.replaceText(input);\n } else if (Array.isArray(input)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return this.replaceArray(input);\n } else if (typeof input === \"object\") {\n return this.replaceObject(input, excludedKeys);\n }\n\n // Don't run replacement on any other types\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n fixJoin(message: any) {\n if (!this.objectMatchesSchema(message.contents, joinContentsSchema)) {\n message.contents = this.replaceAny(message.contents);\n }\n\n try {\n let data = JSON.parse(message.data);\n if (!this.objectMatchesSchema(data, joinDataSchema)) {\n data = this.replaceAny(data);\n } else {\n const user = data.detail.user;\n user.id = this.replaceText(user.id, TextType.Email);\n user.email = this.replaceText(user.email, TextType.Email);\n user.name = this.replaceText(user.name, TextType.Name);\n }\n\n message.data = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n }\n }\n\n fixPropose(message: any) {\n if (!this.objectMatchesSchema(message.contents, proposeContentsSchema)) {\n message.contents = this.replaceAny(message.contents);\n } else {\n if (typeof message.contents === \"string\") {\n try {\n const data = JSON.parse(message.contents);\n if (this.fullScrub) {\n const pkg = data.value?.package;\n if (pkg?.name) {\n pkg.name = this.replaceText(pkg.name, TextType.FluidObject);\n }\n if (Array.isArray(pkg?.fluid?.browser?.umd?.files)) {\n pkg.fluid.browser.umd.files = this.replaceArray(pkg.fluid.browser.umd.files);\n }\n }\n } catch (e) {\n this.debugMsg(e);\n }\n } else {\n if (this.fullScrub) {\n message.contents.value = this.replaceText(message.contents.value, TextType.FluidObject);\n }\n }\n }\n }\n\n fixAttachEntries(entries: any[]) {\n entries.forEach((element) => {\n // Tree type\n if (element.value.entries) {\n this.fixAttachEntries(element.value.entries);\n } else {\n // Blob (leaf) type\n try {\n if (typeof element.value.contents === \"string\") {\n let data = JSON.parse(element.value.contents);\n data = this.replaceObject(data);\n element.value.contents = JSON.stringify(data);\n }\n } catch (e) {\n this.debugMsg(e);\n }\n }\n });\n }\n\n /**\n * Fix the content of an attach in place\n * @param contents - contents object to fix\n */\n fixAttachContents(contents: any): any {\n assert(typeof contents === \"object\", 0x08b /* \"Unexpected type on contents for fix of an attach!\" */);\n if (!this.objectMatchesSchema(contents, attachContentsSchema)) {\n this.replaceObject(contents);\n } else {\n if (this.fullScrub) {\n contents.id = this.replaceText(contents.id, TextType.FluidObject);\n contents.type = this.replaceText(contents.type, TextType.FluidObject);\n }\n\n this.fixAttachEntries(contents.snapshot.entries);\n }\n }\n\n /**\n * Fix an attach message at the root level or a ContainerMessageType attach. Attach\n * messages found within an op message should instead have their contents parsed out\n * and sent to fixAttachContents.\n * @param message - The attach message to fix\n * @param withinOp - If the message is from within an op message (as opposed to being\n * an attach message at the root level). Root level attach messages have \"snapshot\"\n * under a \"contents\" key, whereas attach messages from within an op message have it\n * under a \"content\" key\n */\n fixAttach(message: any) {\n // Handle case where contents is stringified json\n if (typeof message.contents === \"string\") {\n try {\n const data = JSON.parse(message.contents);\n this.fixAttachContents(data);\n message.contents = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n } else {\n this.fixAttachContents(message.contents);\n }\n }\n\n fixDeltaOp(deltaOp: any) {\n if (typeof deltaOp.seg === \"string\") {\n deltaOp.seg = this.replaceText(deltaOp.seg);\n } else {\n deltaOp.seg = this.replaceObject(deltaOp.seg, this.mergeTreeExcludedKeys);\n }\n }\n\n /**\n * Fix the contents object for an op message. Does not do extra type handling. Does\n * not handle special container message types like \"attach\", \"component\", and\n * \"chunkedOp\" (these should be handled by the caller)\n * @param contents - The contents object for an op message. If it was a string in the\n * message, it must have been converted to an object first\n */\n fixOpContentsObject(contents: any) {\n // do replacement\n if (!this.objectMatchesSchema(contents, opContentsSchema)) {\n this.replaceAny(contents);\n } else {\n if (this.fullScrub) {\n contents.address = this.replaceText(contents.address, TextType.FluidObject);\n }\n\n const innerContent = contents.contents.content;\n assert(innerContent !== undefined, 0x08c /* \"innerContent for fixing op contents is undefined!\" */);\n if (contents.contents.type === \"attach\") {\n // attach op\n // handle case where inner content is stringified json\n if (typeof contents.contents.content === \"string\") {\n try {\n const data = JSON.parse(contents.contents.content);\n this.fixAttachContents(data);\n contents.contents.content = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n }\n } else {\n this.fixAttachContents(contents.contents.content);\n }\n } else if (this.validator.validate(innerContent, opContentsMapSchema).valid) {\n // map op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n innerContent.contents.key = this.replaceText(innerContent.contents.key, TextType.MapKey);\n }\n if (innerContent.contents.value !== undefined) {\n innerContent.contents.value.value = this.replaceAny(innerContent.contents.value.value);\n }\n } else if (this.validator.validate(innerContent, opContentsMergeTreeGroupOpSchema).valid) {\n // merge tree group op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n }\n innerContent.contents.ops.forEach((deltaOp) => {\n this.fixDeltaOp(deltaOp);\n });\n } else if (this.validator.validate(innerContent, opContentsMergeTreeDeltaOpSchema).valid) {\n // merge tree delta op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n }\n this.fixDeltaOp(innerContent.contents);\n } else if (this.validator.validate(innerContent, opContentsRegisterCollectionSchema).valid) {\n // register collection op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n innerContent.contents.key = this.replaceText(innerContent.contents.key, TextType.MapKey);\n }\n if (innerContent.contents.value !== undefined) {\n innerContent.contents.value.value = this.replaceAny(innerContent.contents.value.value);\n }\n } else {\n // message contents don't match any known op format\n this.objectMatchesSchema(contents, false);\n }\n }\n }\n\n fixOp(message: any) {\n // handle case where contents is stringified json\n let msgContents;\n if (typeof message.contents === \"string\") {\n try {\n msgContents = JSON.parse(message.contents);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n } else {\n msgContents = message.contents;\n }\n\n // handle container message types\n switch (msgContents.type) {\n case \"attach\": {\n // this one is like a regular attach op, except its contents aren't nested as deep\n // run fixAttach directly and return\n this.fixAttach(msgContents);\n break;\n }\n case \"component\": {\n // this one functionally nests its contents one layer deeper\n // bring up the contents object and continue as usual\n this.fixOpContentsObject(msgContents.contents);\n break;\n }\n case \"chunkedOp\": {\n // this is a (regular?) op split into multiple parts due to size, e.g. because it\n // has an attached image, and where the chunkedOp is within the top-level op's contents\n // (as opposed to being at the top-level). The contents of the chunks need to be\n // concatenated to form the complete stringified json object\n // Early return here to skip re-stringify because no changes are made until the last\n // chunk, and the ChunkedOpProcessor will handle everything at that point\n return this.fixChunkedOp(message);\n }\n case \"blobAttach\": {\n // TODO: handle this properly once blob api is used\n this.debugMsg(\"TODO: blobAttach ops are skipped/unhandled\");\n return;\n }\n default: {\n // A regular op\n this.fixOpContentsObject(msgContents);\n }\n }\n\n // re-stringify the json if needed\n if (typeof message.contents === \"string\") {\n try {\n message.contents = JSON.stringify(msgContents);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n }\n }\n\n /**\n * @param message - The top-level chunkedOp message or a top-level op message\n * with a chunkedOp inside its contents\n */\n fixChunkedOp(message: any) {\n this.chunkProcessor.addMessage(message);\n if (!this.chunkProcessor.hasAllMessages()) {\n return;\n }\n\n const contents = this.chunkProcessor.getConcatenatedContents();\n this.fixOpContentsObject(contents);\n\n this.chunkProcessor.writeSanitizedContents(contents);\n this.chunkProcessor.reset();\n }\n\n sanitize(): ISequencedDocumentMessage[] {\n let seq = 0;\n\n try {\n this.messages.map((message) => {\n seq = message.sequenceNumber;\n // message types from protocol-definitions' protocol.ts\n switch (message.type) {\n case \"join\": {\n this.fixJoin(message);\n break;\n }\n case \"propose\": {\n this.fixPropose(message);\n break;\n }\n case \"attach\": {\n this.fixAttach(message);\n break;\n }\n case \"op\": {\n this.fixOp(message);\n break;\n }\n case \"chunkedOp\": {\n this.fixChunkedOp(message);\n break;\n }\n case \"noop\":\n case \"leave\":\n case \"noClient\":\n case \"summarize\":\n case \"summaryAck\":\n case \"summaryNack\":\n break;\n default:\n this.debugMsg(`Unexpected op type ${message.type}`);\n }\n });\n\n // make sure we don't miss an incomplete chunked op at the end\n assert(!this.chunkProcessor.isPendingProcessing(), 0x08d /* \"After sanitize, pending incomplete ops!\" */);\n } catch (error) {\n this.debugMsg(`Error while processing sequenceNumber ${seq}`);\n throw error;\n }\n\n return this.messages;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"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"}
package/lib/sanitizer.js CHANGED
@@ -542,33 +542,37 @@ export class Sanitizer {
542
542
  msgContents = message.contents;
543
543
  }
544
544
  // handle container message types
545
- if (msgContents.type === "attach") {
546
- // this one is like a regular attach op, except its contents aren't nested as deep
547
- // run fixAttach directly and return
548
- this.fixAttach(msgContents);
549
- }
550
- else if (msgContents.type === "component") {
551
- // this one functionally nests its contents one layer deeper
552
- // bring up the contents object and continue as usual
553
- this.fixOpContentsObject(msgContents.contents);
554
- }
555
- else if (msgContents.type === "chunkedOp") {
556
- // this is a (regular?) op split into multiple parts due to size, e.g. because it
557
- // has an attached image, and where the chunkedOp is within the top-level op's contents
558
- // (as opposed to being at the top-level). The contents of the chunks need to be
559
- // concatenated to form the complete stringified json object
560
- // Early return here to skip re-stringify because no changes are made until the last
561
- // chunk, and the ChunkedOpProcessor will handle everything at that point
562
- return this.fixChunkedOp(message);
563
- }
564
- else if (msgContents.type === "blobAttach") {
565
- // TODO: handle this properly once blob api is used
566
- this.debugMsg("TODO: blobAttach ops are skipped/unhandled");
567
- return;
568
- }
569
- else {
570
- // A regular op
571
- this.fixOpContentsObject(msgContents);
545
+ switch (msgContents.type) {
546
+ case "attach": {
547
+ // this one is like a regular attach op, except its contents aren't nested as deep
548
+ // run fixAttach directly and return
549
+ this.fixAttach(msgContents);
550
+ break;
551
+ }
552
+ case "component": {
553
+ // this one functionally nests its contents one layer deeper
554
+ // bring up the contents object and continue as usual
555
+ this.fixOpContentsObject(msgContents.contents);
556
+ break;
557
+ }
558
+ case "chunkedOp": {
559
+ // this is a (regular?) op split into multiple parts due to size, e.g. because it
560
+ // has an attached image, and where the chunkedOp is within the top-level op's contents
561
+ // (as opposed to being at the top-level). The contents of the chunks need to be
562
+ // concatenated to form the complete stringified json object
563
+ // Early return here to skip re-stringify because no changes are made until the last
564
+ // chunk, and the ChunkedOpProcessor will handle everything at that point
565
+ return this.fixChunkedOp(message);
566
+ }
567
+ case "blobAttach": {
568
+ // TODO: handle this properly once blob api is used
569
+ this.debugMsg("TODO: blobAttach ops are skipped/unhandled");
570
+ return;
571
+ }
572
+ default: {
573
+ // A regular op
574
+ this.fixOpContentsObject(msgContents);
575
+ }
572
576
  }
573
577
  // re-stringify the json if needed
574
578
  if (typeof message.contents === "string") {
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * This tool cleans up a message.json file downloaded through fluid-fetch to remove\n * user content and user identifying information. Enough information can be retained\n * to allow loading through Fluid Preview, or everything can be scrubbed so that only\n * replay-tool can read the result. Anonymous identifying information such as client\n * IDs are always retained. Object keys are NOT scrubbed, including those that are\n * nested within values (only leaf values are scrubbed).\n *\n * Note: While user content/information is scrubbed, it should not be assumed to be\n * fully anonymized because certain meta-information (such as word lengths and\n * consistent replacement) are preserved.\n *\n * Messages must match known structures when scrubbing for Fluid Preview.\n */\n\nimport * as Validator from \"jsonschema\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport {\n ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n attachContentsSchema,\n chunkedOpContentsSchema,\n joinContentsSchema,\n joinDataSchema,\n opContentsMapSchema,\n opContentsSchema,\n opContentsMergeTreeDeltaOpSchema,\n opContentsMergeTreeGroupOpSchema,\n opContentsRegisterCollectionSchema,\n proposeContentsSchema,\n} from \"./messageSchema\";\n\nenum TextType {\n Generic,\n Email,\n Name,\n FluidObject,\n MapKey,\n}\n\n// Workaround to jsonschema package not supporting \"false\" as a schema\n// that matches nothing\nconst falseResult = {\n valid: false,\n toString: () => { return \"Unmatched format\"; },\n};\n\n/**\n * Class that takes chunkedOp messages and can provide their concatenated\n * contents along with re-write sanitized content in-place back into the\n * messages. Assumes sanitized messages are always less than or equal in\n * size to the original message.\n */\nclass ChunkedOpProcessor {\n /**\n * Message references so we can replace their contents in-place. These can\n * be top-level chunkedOp messages, or top-level op messages with a chunkedOp\n * within the contents\n */\n private messages = new Array<any>();\n /**\n * The messages' parsed contents for processing. Should parallel the\n * messages member\n */\n private parsedMessageContents = new Array<any>();\n private writtenBack = false;\n /**\n * keep track of the total starting length to make sure we don't somehow end\n * up with more content than we started with (meaning we may not be able to\n * write it back)\n */\n private concatenatedLength = 0;\n\n constructor(\n readonly validateSchemaFn: (object: any, schema: any) => boolean,\n readonly debug: boolean,\n ) { }\n\n debugMsg(msg: any) {\n if (this.debug) {\n console.error(msg);\n }\n }\n\n addMessage(message: any): void {\n this.messages.push(message);\n\n let parsed;\n try {\n parsed = JSON.parse(message.contents);\n if (message.type === \"op\") {\n // nested within a regular op\n // need to go deeper to get the desired contents\n parsed = parsed.contents;\n }\n } catch (e) {\n this.debugMsg(e);\n this.debugMsg(message.contents);\n }\n this.validateSchemaFn(parsed, chunkedOpContentsSchema);\n this.parsedMessageContents.push(parsed);\n }\n\n hasAllMessages(): boolean {\n const lastMsgContents = this.parsedMessageContents[this.parsedMessageContents.length - 1];\n return lastMsgContents.chunkId !== undefined && lastMsgContents.chunkId === lastMsgContents.totalChunks;\n }\n\n /**\n * @returns The concatenated contents of all the messages parsed as json\n */\n getConcatenatedContents(): any {\n const contentsString = this.parsedMessageContents.reduce((previousValue: string, currentValue: any) => {\n return previousValue + (currentValue.contents as string);\n }, \"\");\n\n this.concatenatedLength = contentsString.length;\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return JSON.parse(contentsString);\n } catch (e) {\n this.debugMsg(contentsString);\n this.debugMsg(e);\n return undefined;\n }\n }\n\n /**\n * Write back sanitized contents into the messages. The contents are\n * stringified, split up, and written in place to the messages that\n * were added earlier. The number of messages is preserved.\n * @param contents - Sanitized contents to write back\n */\n writeSanitizedContents(contents: any): void {\n // Write back a chunk size equal to the original\n const chunkSize = this.parsedMessageContents[0].contents.length;\n\n let stringified: string;\n try {\n stringified = JSON.stringify(contents);\n assert(stringified.length <= this.concatenatedLength,\n 0x089 /* \"Stringified length of chunk contents > total starting length\" */);\n } catch (e) {\n this.debugMsg(e);\n throw e;\n }\n\n for (let i = 0; i < this.messages.length; i++) {\n const substring = stringified.substring(i * chunkSize, (i + 1) * chunkSize);\n\n const parsedContents = this.parsedMessageContents[i];\n parsedContents.contents = substring;\n const message = this.messages[i];\n\n let stringifiedParsedContents;\n try {\n // for nested chunkedOps, we need to recreate the extra nesting layer\n // we removed earlier when adding the message\n if (message.type === \"op\") {\n const nestingLayer = {\n type: \"chunkedOp\",\n contents: parsedContents,\n };\n stringifiedParsedContents = JSON.stringify(nestingLayer);\n } else {\n stringifiedParsedContents = JSON.stringify(parsedContents);\n }\n } catch (e) {\n this.debugMsg(e);\n }\n\n message.contents = stringifiedParsedContents;\n }\n\n this.writtenBack = true;\n }\n\n reset(): void {\n assert(this.writtenBack, 0x08a /* \"resetting ChunkedOpProcessor that never wrote back its contents\" */);\n this.messages = new Array<any>();\n this.parsedMessageContents = new Array<any>();\n this.writtenBack = false;\n this.concatenatedLength = 0;\n }\n\n isPendingProcessing(): boolean {\n return this.messages.length !== 0;\n }\n}\n\nexport class Sanitizer {\n readonly validator = new Validator.Validator();\n // Represents the keys used to store Fluid object identifiers, snapshot info,\n // and other string fields that should not be replaced in contents blobs to\n // ensure the messages are still usable\n readonly defaultExcludedKeys = new Set<string>();\n // Represents the keys used by merge-tree ops their \"seg\" property, where other\n // keys represent user information\n readonly mergeTreeExcludedKeys = new Set<string>();\n // Map of user information to what it was replaced with. Used to ensure the same\n // data have the same replacements\n readonly replacementMap = new Map<string, string>();\n\n /**\n * Validate that the provided message matches the provided schema.\n * For a full scrub, warn and continue (scrubber should fully sanitize unexpected\n * fields for ops), otherwise throw an error because we cannot be sure user\n * information is being sufficiently sanitized.\n */\n objectMatchesSchema = (object: any, schema: any): boolean => {\n const result = schema === false ? falseResult : this.validator.validate(object, schema);\n if (!result.valid) {\n const errorMsg = `Bad msg fmt:\\n${result.toString()}\\n${JSON.stringify(object, undefined, 2)}`;\n\n if (this.fullScrub || this.noBail) {\n this.debugMsg(errorMsg);\n } else {\n throw new Error(errorMsg);\n }\n }\n return result.valid;\n };\n\n readonly chunkProcessor = new ChunkedOpProcessor(this.objectMatchesSchema, this.debug);\n\n constructor(\n readonly messages: ISequencedDocumentMessage[],\n readonly fullScrub: boolean,\n readonly noBail: boolean,\n readonly debug: boolean = false,\n ) {\n this.defaultExcludedKeys.add(\"type\");\n this.defaultExcludedKeys.add(\"id\");\n this.defaultExcludedKeys.add(\"pkg\");\n this.defaultExcludedKeys.add(\"snapshotFormatVersion\");\n this.defaultExcludedKeys.add(\"packageVersion\");\n this.mergeTreeExcludedKeys.add(\"nodeType\");\n }\n\n debugMsg(msg: any) {\n if (this.debug) {\n console.error(msg);\n }\n }\n\n isFluidObjectKey(key: string): boolean {\n return key === \"type\" || key === \"id\";\n }\n\n getRandomText(len: number): string {\n let str = \"\";\n while (str.length < len) {\n str = str + Math.random().toString(36).substring(2);\n }\n return str.substr(0, len);\n }\n\n readonly wordTokenRegex = /\\S+/g;\n\n readonly replaceRandomTextFn = (match: string): string => {\n if (this.replacementMap.has(match)) {\n return this.replacementMap.get(match)!;\n }\n\n const replacement = this.getRandomText(match.length);\n this.replacementMap.set(match, replacement);\n return replacement;\n };\n\n /**\n * Replace text with garbage. FluidObject types are not replaced when not under\n * full scrub mode. All other text is replaced consistently.\n */\n replaceText(input?: string, type: TextType = TextType.Generic): string | undefined {\n if (input === undefined) {\n return undefined;\n }\n\n if (type === TextType.FluidObject) {\n if (this.replacementMap.has(input)) {\n return this.replacementMap.get(input)!;\n }\n\n let replacement: string;\n if (this.fullScrub) {\n replacement = this.getRandomText(input.length);\n } else {\n replacement = input;\n }\n\n this.replacementMap.set(input, replacement);\n return replacement;\n }\n\n return input.replace(this.wordTokenRegex, this.replaceRandomTextFn);\n }\n\n replaceArray(input: any[]): any[] {\n for (let i = 0; i < input.length; i++) {\n const value = input[i];\n if (typeof value === \"string\") {\n input[i] = this.replaceText(value);\n } else if (Array.isArray(value)) {\n input[i] = this.replaceArray(value);\n } else if (typeof value === \"object\") {\n input[i] = this.replaceObject(value);\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n /**\n * (sort of) recurses down the values of a JSON object to sanitize all its strings\n * (only checks strings, arrays, and objects)\n * @param input - The object to sanitize\n * @param excludedKeys - object keys for which to skip replacement when not in fullScrub\n */\n // eslint-disable-next-line @typescript-eslint/ban-types\n replaceObject(input: object | null, excludedKeys: Set<string> = this.defaultExcludedKeys): object | null {\n // File might contain actual nulls\n if (input === null || input === undefined) {\n return input;\n }\n\n const keys = Object.keys(input);\n keys.forEach((key) => {\n if (this.fullScrub || !excludedKeys.has(key)) {\n const value = input[key];\n if (typeof value === \"string\") {\n input[key] = this.replaceText(\n value,\n this.isFluidObjectKey(key) ? TextType.FluidObject : TextType.Generic,\n );\n } else if (Array.isArray(value)) {\n input[key] = this.replaceArray(value);\n } else if (typeof value === \"object\") {\n input[key] = this.replaceObject(value, excludedKeys);\n }\n }\n });\n return input;\n }\n\n /**\n * Replacement on an unknown type or a parsed root level object\n * without a key\n * @param input - The object to sanitize\n * @param excludedKeys - object keys for which to skip replacement when not in fullScrub\n */\n replaceAny(input: any, excludedKeys: Set<string> = this.defaultExcludedKeys): any {\n if (input === null || input === undefined) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n if (typeof input === \"string\") {\n return this.replaceText(input);\n } else if (Array.isArray(input)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return this.replaceArray(input);\n } else if (typeof input === \"object\") {\n return this.replaceObject(input, excludedKeys);\n }\n\n // Don't run replacement on any other types\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n fixJoin(message: any) {\n if (!this.objectMatchesSchema(message.contents, joinContentsSchema)) {\n message.contents = this.replaceAny(message.contents);\n }\n\n try {\n let data = JSON.parse(message.data);\n if (!this.objectMatchesSchema(data, joinDataSchema)) {\n data = this.replaceAny(data);\n } else {\n const user = data.detail.user;\n user.id = this.replaceText(user.id, TextType.Email);\n user.email = this.replaceText(user.email, TextType.Email);\n user.name = this.replaceText(user.name, TextType.Name);\n }\n\n message.data = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n }\n }\n\n fixPropose(message: any) {\n if (!this.objectMatchesSchema(message.contents, proposeContentsSchema)) {\n message.contents = this.replaceAny(message.contents);\n } else {\n if (typeof message.contents === \"string\") {\n try {\n const data = JSON.parse(message.contents);\n if (this.fullScrub) {\n const pkg = data.value?.package;\n if (pkg?.name) {\n pkg.name = this.replaceText(pkg.name, TextType.FluidObject);\n }\n if (Array.isArray(pkg?.fluid?.browser?.umd?.files)) {\n pkg.fluid.browser.umd.files = this.replaceArray(pkg.fluid.browser.umd.files);\n }\n }\n } catch (e) {\n this.debugMsg(e);\n }\n } else {\n if (this.fullScrub) {\n message.contents.value = this.replaceText(message.contents.value, TextType.FluidObject);\n }\n }\n }\n }\n\n fixAttachEntries(entries: any[]) {\n entries.forEach((element) => {\n // Tree type\n if (element.value.entries) {\n this.fixAttachEntries(element.value.entries);\n } else {\n // Blob (leaf) type\n try {\n if (typeof element.value.contents === \"string\") {\n let data = JSON.parse(element.value.contents);\n data = this.replaceObject(data);\n element.value.contents = JSON.stringify(data);\n }\n } catch (e) {\n this.debugMsg(e);\n }\n }\n });\n }\n\n /**\n * Fix the content of an attach in place\n * @param contents - contents object to fix\n */\n fixAttachContents(contents: any): any {\n assert(typeof contents === \"object\", 0x08b /* \"Unexpected type on contents for fix of an attach!\" */);\n if (!this.objectMatchesSchema(contents, attachContentsSchema)) {\n this.replaceObject(contents);\n } else {\n if (this.fullScrub) {\n contents.id = this.replaceText(contents.id, TextType.FluidObject);\n contents.type = this.replaceText(contents.type, TextType.FluidObject);\n }\n\n this.fixAttachEntries(contents.snapshot.entries);\n }\n }\n\n /**\n * Fix an attach message at the root level or a ContainerMessageType attach. Attach\n * messages found within an op message should instead have their contents parsed out\n * and sent to fixAttachContents.\n * @param message - The attach message to fix\n * @param withinOp - If the message is from within an op message (as opposed to being\n * an attach message at the root level). Root level attach messages have \"snapshot\"\n * under a \"contents\" key, whereas attach messages from within an op message have it\n * under a \"content\" key\n */\n fixAttach(message: any) {\n // Handle case where contents is stringified json\n if (typeof message.contents === \"string\") {\n try {\n const data = JSON.parse(message.contents);\n this.fixAttachContents(data);\n message.contents = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n } else {\n this.fixAttachContents(message.contents);\n }\n }\n\n fixDeltaOp(deltaOp: any) {\n if (typeof deltaOp.seg === \"string\") {\n deltaOp.seg = this.replaceText(deltaOp.seg);\n } else {\n deltaOp.seg = this.replaceObject(deltaOp.seg, this.mergeTreeExcludedKeys);\n }\n }\n\n /**\n * Fix the contents object for an op message. Does not do extra type handling. Does\n * not handle special container message types like \"attach\", \"component\", and\n * \"chunkedOp\" (these should be handled by the caller)\n * @param contents - The contents object for an op message. If it was a string in the\n * message, it must have been converted to an object first\n */\n fixOpContentsObject(contents: any) {\n // do replacement\n if (!this.objectMatchesSchema(contents, opContentsSchema)) {\n this.replaceAny(contents);\n } else {\n if (this.fullScrub) {\n contents.address = this.replaceText(contents.address, TextType.FluidObject);\n }\n\n const innerContent = contents.contents.content;\n assert(innerContent !== undefined, 0x08c /* \"innerContent for fixing op contents is undefined!\" */);\n if (contents.contents.type === \"attach\") {\n // attach op\n // handle case where inner content is stringified json\n if (typeof contents.contents.content === \"string\") {\n try {\n const data = JSON.parse(contents.contents.content);\n this.fixAttachContents(data);\n contents.contents.content = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n }\n } else {\n this.fixAttachContents(contents.contents.content);\n }\n } else if (this.validator.validate(innerContent, opContentsMapSchema).valid) {\n // map op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n innerContent.contents.key = this.replaceText(innerContent.contents.key, TextType.MapKey);\n }\n if (innerContent.contents.value !== undefined) {\n innerContent.contents.value.value = this.replaceAny(innerContent.contents.value.value);\n }\n } else if (this.validator.validate(innerContent, opContentsMergeTreeGroupOpSchema).valid) {\n // merge tree group op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n }\n innerContent.contents.ops.forEach((deltaOp) => {\n this.fixDeltaOp(deltaOp);\n });\n } else if (this.validator.validate(innerContent, opContentsMergeTreeDeltaOpSchema).valid) {\n // merge tree delta op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n }\n this.fixDeltaOp(innerContent.contents);\n } else if (this.validator.validate(innerContent, opContentsRegisterCollectionSchema).valid) {\n // register collection op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n innerContent.contents.key = this.replaceText(innerContent.contents.key, TextType.MapKey);\n }\n if (innerContent.contents.value !== undefined) {\n innerContent.contents.value.value = this.replaceAny(innerContent.contents.value.value);\n }\n } else {\n // message contents don't match any known op format\n this.objectMatchesSchema(contents, false);\n }\n }\n }\n\n fixOp(message: any) {\n // handle case where contents is stringified json\n let msgContents;\n if (typeof message.contents === \"string\") {\n try {\n msgContents = JSON.parse(message.contents);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n } else {\n msgContents = message.contents;\n }\n\n // handle container message types\n if (msgContents.type === \"attach\") {\n // this one is like a regular attach op, except its contents aren't nested as deep\n // run fixAttach directly and return\n this.fixAttach(msgContents);\n } else if (msgContents.type === \"component\") {\n // this one functionally nests its contents one layer deeper\n // bring up the contents object and continue as usual\n this.fixOpContentsObject(msgContents.contents);\n } else if (msgContents.type === \"chunkedOp\") {\n // this is a (regular?) op split into multiple parts due to size, e.g. because it\n // has an attached image, and where the chunkedOp is within the top-level op's contents\n // (as opposed to being at the top-level). The contents of the chunks need to be\n // concatenated to form the complete stringified json object\n // Early return here to skip re-stringify because no changes are made until the last\n // chunk, and the ChunkedOpProcessor will handle everything at that point\n return this.fixChunkedOp(message);\n } else if (msgContents.type === \"blobAttach\") {\n // TODO: handle this properly once blob api is used\n this.debugMsg(\"TODO: blobAttach ops are skipped/unhandled\");\n return;\n } else {\n // A regular op\n this.fixOpContentsObject(msgContents);\n }\n\n // re-stringify the json if needed\n if (typeof message.contents === \"string\") {\n try {\n message.contents = JSON.stringify(msgContents);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n }\n }\n\n /**\n * @param message - The top-level chunkedOp message or a top-level op message\n * with a chunkedOp inside its contents\n */\n fixChunkedOp(message: any) {\n this.chunkProcessor.addMessage(message);\n if (!this.chunkProcessor.hasAllMessages()) {\n return;\n }\n\n const contents = this.chunkProcessor.getConcatenatedContents();\n this.fixOpContentsObject(contents);\n\n this.chunkProcessor.writeSanitizedContents(contents);\n this.chunkProcessor.reset();\n }\n\n sanitize(): ISequencedDocumentMessage[] {\n let seq = 0;\n\n try {\n this.messages.map((message) => {\n seq = message.sequenceNumber;\n // message types from protocol-definitions' protocol.ts\n switch (message.type) {\n case \"join\": {\n this.fixJoin(message);\n break;\n }\n case \"propose\": {\n this.fixPropose(message);\n break;\n }\n case \"attach\": {\n this.fixAttach(message);\n break;\n }\n case \"op\": {\n this.fixOp(message);\n break;\n }\n case \"chunkedOp\": {\n this.fixChunkedOp(message);\n break;\n }\n case \"noop\":\n case \"leave\":\n case \"noClient\":\n case \"summarize\":\n case \"summaryAck\":\n case \"summaryNack\":\n break;\n default:\n this.debugMsg(`Unexpected op type ${message.type}`);\n }\n });\n\n // make sure we don't miss an incomplete chunked op at the end\n assert(!this.chunkProcessor.isPendingProcessing(), 0x08d /* \"After sanitize, pending incomplete ops!\" */);\n } catch (error) {\n this.debugMsg(`Error while processing sequenceNumber ${seq}`);\n throw error;\n }\n\n return this.messages;\n }\n}\n"]}
1
+ {"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * This tool cleans up a message.json file downloaded through fluid-fetch to remove\n * user content and user identifying information. Enough information can be retained\n * to allow loading through Fluid Preview, or everything can be scrubbed so that only\n * replay-tool can read the result. Anonymous identifying information such as client\n * IDs are always retained. Object keys are NOT scrubbed, including those that are\n * nested within values (only leaf values are scrubbed).\n *\n * Note: While user content/information is scrubbed, it should not be assumed to be\n * fully anonymized because certain meta-information (such as word lengths and\n * consistent replacement) are preserved.\n *\n * Messages must match known structures when scrubbing for Fluid Preview.\n */\n\nimport * as Validator from \"jsonschema\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport {\n ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n attachContentsSchema,\n chunkedOpContentsSchema,\n joinContentsSchema,\n joinDataSchema,\n opContentsMapSchema,\n opContentsSchema,\n opContentsMergeTreeDeltaOpSchema,\n opContentsMergeTreeGroupOpSchema,\n opContentsRegisterCollectionSchema,\n proposeContentsSchema,\n} from \"./messageSchema\";\n\nenum TextType {\n Generic,\n Email,\n Name,\n FluidObject,\n MapKey,\n}\n\n// Workaround to jsonschema package not supporting \"false\" as a schema\n// that matches nothing\nconst falseResult = {\n valid: false,\n toString: () => { return \"Unmatched format\"; },\n};\n\n/**\n * Class that takes chunkedOp messages and can provide their concatenated\n * contents along with re-write sanitized content in-place back into the\n * messages. Assumes sanitized messages are always less than or equal in\n * size to the original message.\n */\nclass ChunkedOpProcessor {\n /**\n * Message references so we can replace their contents in-place. These can\n * be top-level chunkedOp messages, or top-level op messages with a chunkedOp\n * within the contents\n */\n private messages = new Array<any>();\n /**\n * The messages' parsed contents for processing. Should parallel the\n * messages member\n */\n private parsedMessageContents = new Array<any>();\n private writtenBack = false;\n /**\n * keep track of the total starting length to make sure we don't somehow end\n * up with more content than we started with (meaning we may not be able to\n * write it back)\n */\n private concatenatedLength = 0;\n\n constructor(\n readonly validateSchemaFn: (object: any, schema: any) => boolean,\n readonly debug: boolean,\n ) { }\n\n debugMsg(msg: any) {\n if (this.debug) {\n console.error(msg);\n }\n }\n\n addMessage(message: any): void {\n this.messages.push(message);\n\n let parsed;\n try {\n parsed = JSON.parse(message.contents);\n if (message.type === \"op\") {\n // nested within a regular op\n // need to go deeper to get the desired contents\n parsed = parsed.contents;\n }\n } catch (e) {\n this.debugMsg(e);\n this.debugMsg(message.contents);\n }\n this.validateSchemaFn(parsed, chunkedOpContentsSchema);\n this.parsedMessageContents.push(parsed);\n }\n\n hasAllMessages(): boolean {\n const lastMsgContents = this.parsedMessageContents[this.parsedMessageContents.length - 1];\n return lastMsgContents.chunkId !== undefined && lastMsgContents.chunkId === lastMsgContents.totalChunks;\n }\n\n /**\n * @returns The concatenated contents of all the messages parsed as json\n */\n getConcatenatedContents(): any {\n const contentsString = this.parsedMessageContents.reduce((previousValue: string, currentValue: any) => {\n return previousValue + (currentValue.contents as string);\n }, \"\");\n\n this.concatenatedLength = contentsString.length;\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return JSON.parse(contentsString);\n } catch (e) {\n this.debugMsg(contentsString);\n this.debugMsg(e);\n return undefined;\n }\n }\n\n /**\n * Write back sanitized contents into the messages. The contents are\n * stringified, split up, and written in place to the messages that\n * were added earlier. The number of messages is preserved.\n * @param contents - Sanitized contents to write back\n */\n writeSanitizedContents(contents: any): void {\n // Write back a chunk size equal to the original\n const chunkSize = this.parsedMessageContents[0].contents.length;\n\n let stringified: string;\n try {\n stringified = JSON.stringify(contents);\n assert(stringified.length <= this.concatenatedLength,\n 0x089 /* \"Stringified length of chunk contents > total starting length\" */);\n } catch (e) {\n this.debugMsg(e);\n throw e;\n }\n\n for (let i = 0; i < this.messages.length; i++) {\n const substring = stringified.substring(i * chunkSize, (i + 1) * chunkSize);\n\n const parsedContents = this.parsedMessageContents[i];\n parsedContents.contents = substring;\n const message = this.messages[i];\n\n let stringifiedParsedContents;\n try {\n // for nested chunkedOps, we need to recreate the extra nesting layer\n // we removed earlier when adding the message\n if (message.type === \"op\") {\n const nestingLayer = {\n type: \"chunkedOp\",\n contents: parsedContents,\n };\n stringifiedParsedContents = JSON.stringify(nestingLayer);\n } else {\n stringifiedParsedContents = JSON.stringify(parsedContents);\n }\n } catch (e) {\n this.debugMsg(e);\n }\n\n message.contents = stringifiedParsedContents;\n }\n\n this.writtenBack = true;\n }\n\n reset(): void {\n assert(this.writtenBack, 0x08a /* \"resetting ChunkedOpProcessor that never wrote back its contents\" */);\n this.messages = new Array<any>();\n this.parsedMessageContents = new Array<any>();\n this.writtenBack = false;\n this.concatenatedLength = 0;\n }\n\n isPendingProcessing(): boolean {\n return this.messages.length !== 0;\n }\n}\n\nexport class Sanitizer {\n readonly validator = new Validator.Validator();\n // Represents the keys used to store Fluid object identifiers, snapshot info,\n // and other string fields that should not be replaced in contents blobs to\n // ensure the messages are still usable\n readonly defaultExcludedKeys = new Set<string>();\n // Represents the keys used by merge-tree ops their \"seg\" property, where other\n // keys represent user information\n readonly mergeTreeExcludedKeys = new Set<string>();\n // Map of user information to what it was replaced with. Used to ensure the same\n // data have the same replacements\n readonly replacementMap = new Map<string, string>();\n\n /**\n * Validate that the provided message matches the provided schema.\n * For a full scrub, warn and continue (scrubber should fully sanitize unexpected\n * fields for ops), otherwise throw an error because we cannot be sure user\n * information is being sufficiently sanitized.\n */\n objectMatchesSchema = (object: any, schema: any): boolean => {\n const result = schema === false ? falseResult : this.validator.validate(object, schema);\n if (!result.valid) {\n const errorMsg = `Bad msg fmt:\\n${result.toString()}\\n${JSON.stringify(object, undefined, 2)}`;\n\n if (this.fullScrub || this.noBail) {\n this.debugMsg(errorMsg);\n } else {\n throw new Error(errorMsg);\n }\n }\n return result.valid;\n };\n\n readonly chunkProcessor = new ChunkedOpProcessor(this.objectMatchesSchema, this.debug);\n\n constructor(\n readonly messages: ISequencedDocumentMessage[],\n readonly fullScrub: boolean,\n readonly noBail: boolean,\n readonly debug: boolean = false,\n ) {\n this.defaultExcludedKeys.add(\"type\");\n this.defaultExcludedKeys.add(\"id\");\n this.defaultExcludedKeys.add(\"pkg\");\n this.defaultExcludedKeys.add(\"snapshotFormatVersion\");\n this.defaultExcludedKeys.add(\"packageVersion\");\n this.mergeTreeExcludedKeys.add(\"nodeType\");\n }\n\n debugMsg(msg: any) {\n if (this.debug) {\n console.error(msg);\n }\n }\n\n isFluidObjectKey(key: string): boolean {\n return key === \"type\" || key === \"id\";\n }\n\n getRandomText(len: number): string {\n let str = \"\";\n while (str.length < len) {\n str = str + Math.random().toString(36).substring(2);\n }\n return str.substr(0, len);\n }\n\n readonly wordTokenRegex = /\\S+/g;\n\n readonly replaceRandomTextFn = (match: string): string => {\n if (this.replacementMap.has(match)) {\n return this.replacementMap.get(match)!;\n }\n\n const replacement = this.getRandomText(match.length);\n this.replacementMap.set(match, replacement);\n return replacement;\n };\n\n /**\n * Replace text with garbage. FluidObject types are not replaced when not under\n * full scrub mode. All other text is replaced consistently.\n */\n replaceText(input?: string, type: TextType = TextType.Generic): string | undefined {\n if (input === undefined) {\n return undefined;\n }\n\n if (type === TextType.FluidObject) {\n if (this.replacementMap.has(input)) {\n return this.replacementMap.get(input)!;\n }\n\n let replacement: string;\n if (this.fullScrub) {\n replacement = this.getRandomText(input.length);\n } else {\n replacement = input;\n }\n\n this.replacementMap.set(input, replacement);\n return replacement;\n }\n\n return input.replace(this.wordTokenRegex, this.replaceRandomTextFn);\n }\n\n replaceArray(input: any[]): any[] {\n for (let i = 0; i < input.length; i++) {\n const value = input[i];\n if (typeof value === \"string\") {\n input[i] = this.replaceText(value);\n } else if (Array.isArray(value)) {\n input[i] = this.replaceArray(value);\n } else if (typeof value === \"object\") {\n input[i] = this.replaceObject(value);\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n /**\n * (sort of) recurses down the values of a JSON object to sanitize all its strings\n * (only checks strings, arrays, and objects)\n * @param input - The object to sanitize\n * @param excludedKeys - object keys for which to skip replacement when not in fullScrub\n */\n // eslint-disable-next-line @typescript-eslint/ban-types\n replaceObject(input: object | null, excludedKeys: Set<string> = this.defaultExcludedKeys): object | null {\n // File might contain actual nulls\n if (input === null || input === undefined) {\n return input;\n }\n\n const keys = Object.keys(input);\n keys.forEach((key) => {\n if (this.fullScrub || !excludedKeys.has(key)) {\n const value = input[key];\n if (typeof value === \"string\") {\n input[key] = this.replaceText(\n value,\n this.isFluidObjectKey(key) ? TextType.FluidObject : TextType.Generic,\n );\n } else if (Array.isArray(value)) {\n input[key] = this.replaceArray(value);\n } else if (typeof value === \"object\") {\n input[key] = this.replaceObject(value, excludedKeys);\n }\n }\n });\n return input;\n }\n\n /**\n * Replacement on an unknown type or a parsed root level object\n * without a key\n * @param input - The object to sanitize\n * @param excludedKeys - object keys for which to skip replacement when not in fullScrub\n */\n replaceAny(input: any, excludedKeys: Set<string> = this.defaultExcludedKeys): any {\n if (input === null || input === undefined) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n if (typeof input === \"string\") {\n return this.replaceText(input);\n } else if (Array.isArray(input)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return this.replaceArray(input);\n } else if (typeof input === \"object\") {\n return this.replaceObject(input, excludedKeys);\n }\n\n // Don't run replacement on any other types\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return input;\n }\n\n fixJoin(message: any) {\n if (!this.objectMatchesSchema(message.contents, joinContentsSchema)) {\n message.contents = this.replaceAny(message.contents);\n }\n\n try {\n let data = JSON.parse(message.data);\n if (!this.objectMatchesSchema(data, joinDataSchema)) {\n data = this.replaceAny(data);\n } else {\n const user = data.detail.user;\n user.id = this.replaceText(user.id, TextType.Email);\n user.email = this.replaceText(user.email, TextType.Email);\n user.name = this.replaceText(user.name, TextType.Name);\n }\n\n message.data = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n }\n }\n\n fixPropose(message: any) {\n if (!this.objectMatchesSchema(message.contents, proposeContentsSchema)) {\n message.contents = this.replaceAny(message.contents);\n } else {\n if (typeof message.contents === \"string\") {\n try {\n const data = JSON.parse(message.contents);\n if (this.fullScrub) {\n const pkg = data.value?.package;\n if (pkg?.name) {\n pkg.name = this.replaceText(pkg.name, TextType.FluidObject);\n }\n if (Array.isArray(pkg?.fluid?.browser?.umd?.files)) {\n pkg.fluid.browser.umd.files = this.replaceArray(pkg.fluid.browser.umd.files);\n }\n }\n } catch (e) {\n this.debugMsg(e);\n }\n } else {\n if (this.fullScrub) {\n message.contents.value = this.replaceText(message.contents.value, TextType.FluidObject);\n }\n }\n }\n }\n\n fixAttachEntries(entries: any[]) {\n entries.forEach((element) => {\n // Tree type\n if (element.value.entries) {\n this.fixAttachEntries(element.value.entries);\n } else {\n // Blob (leaf) type\n try {\n if (typeof element.value.contents === \"string\") {\n let data = JSON.parse(element.value.contents);\n data = this.replaceObject(data);\n element.value.contents = JSON.stringify(data);\n }\n } catch (e) {\n this.debugMsg(e);\n }\n }\n });\n }\n\n /**\n * Fix the content of an attach in place\n * @param contents - contents object to fix\n */\n fixAttachContents(contents: any): any {\n assert(typeof contents === \"object\", 0x08b /* \"Unexpected type on contents for fix of an attach!\" */);\n if (!this.objectMatchesSchema(contents, attachContentsSchema)) {\n this.replaceObject(contents);\n } else {\n if (this.fullScrub) {\n contents.id = this.replaceText(contents.id, TextType.FluidObject);\n contents.type = this.replaceText(contents.type, TextType.FluidObject);\n }\n\n this.fixAttachEntries(contents.snapshot.entries);\n }\n }\n\n /**\n * Fix an attach message at the root level or a ContainerMessageType attach. Attach\n * messages found within an op message should instead have their contents parsed out\n * and sent to fixAttachContents.\n * @param message - The attach message to fix\n * @param withinOp - If the message is from within an op message (as opposed to being\n * an attach message at the root level). Root level attach messages have \"snapshot\"\n * under a \"contents\" key, whereas attach messages from within an op message have it\n * under a \"content\" key\n */\n fixAttach(message: any) {\n // Handle case where contents is stringified json\n if (typeof message.contents === \"string\") {\n try {\n const data = JSON.parse(message.contents);\n this.fixAttachContents(data);\n message.contents = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n } else {\n this.fixAttachContents(message.contents);\n }\n }\n\n fixDeltaOp(deltaOp: any) {\n if (typeof deltaOp.seg === \"string\") {\n deltaOp.seg = this.replaceText(deltaOp.seg);\n } else {\n deltaOp.seg = this.replaceObject(deltaOp.seg, this.mergeTreeExcludedKeys);\n }\n }\n\n /**\n * Fix the contents object for an op message. Does not do extra type handling. Does\n * not handle special container message types like \"attach\", \"component\", and\n * \"chunkedOp\" (these should be handled by the caller)\n * @param contents - The contents object for an op message. If it was a string in the\n * message, it must have been converted to an object first\n */\n fixOpContentsObject(contents: any) {\n // do replacement\n if (!this.objectMatchesSchema(contents, opContentsSchema)) {\n this.replaceAny(contents);\n } else {\n if (this.fullScrub) {\n contents.address = this.replaceText(contents.address, TextType.FluidObject);\n }\n\n const innerContent = contents.contents.content;\n assert(innerContent !== undefined, 0x08c /* \"innerContent for fixing op contents is undefined!\" */);\n if (contents.contents.type === \"attach\") {\n // attach op\n // handle case where inner content is stringified json\n if (typeof contents.contents.content === \"string\") {\n try {\n const data = JSON.parse(contents.contents.content);\n this.fixAttachContents(data);\n contents.contents.content = JSON.stringify(data);\n } catch (e) {\n this.debugMsg(e);\n }\n } else {\n this.fixAttachContents(contents.contents.content);\n }\n } else if (this.validator.validate(innerContent, opContentsMapSchema).valid) {\n // map op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n innerContent.contents.key = this.replaceText(innerContent.contents.key, TextType.MapKey);\n }\n if (innerContent.contents.value !== undefined) {\n innerContent.contents.value.value = this.replaceAny(innerContent.contents.value.value);\n }\n } else if (this.validator.validate(innerContent, opContentsMergeTreeGroupOpSchema).valid) {\n // merge tree group op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n }\n innerContent.contents.ops.forEach((deltaOp) => {\n this.fixDeltaOp(deltaOp);\n });\n } else if (this.validator.validate(innerContent, opContentsMergeTreeDeltaOpSchema).valid) {\n // merge tree delta op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n }\n this.fixDeltaOp(innerContent.contents);\n } else if (this.validator.validate(innerContent, opContentsRegisterCollectionSchema).valid) {\n // register collection op\n if (this.fullScrub) {\n innerContent.address = this.replaceText(innerContent.address, TextType.FluidObject);\n innerContent.contents.key = this.replaceText(innerContent.contents.key, TextType.MapKey);\n }\n if (innerContent.contents.value !== undefined) {\n innerContent.contents.value.value = this.replaceAny(innerContent.contents.value.value);\n }\n } else {\n // message contents don't match any known op format\n this.objectMatchesSchema(contents, false);\n }\n }\n }\n\n fixOp(message: any) {\n // handle case where contents is stringified json\n let msgContents;\n if (typeof message.contents === \"string\") {\n try {\n msgContents = JSON.parse(message.contents);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n } else {\n msgContents = message.contents;\n }\n\n // handle container message types\n switch (msgContents.type) {\n case \"attach\": {\n // this one is like a regular attach op, except its contents aren't nested as deep\n // run fixAttach directly and return\n this.fixAttach(msgContents);\n break;\n }\n case \"component\": {\n // this one functionally nests its contents one layer deeper\n // bring up the contents object and continue as usual\n this.fixOpContentsObject(msgContents.contents);\n break;\n }\n case \"chunkedOp\": {\n // this is a (regular?) op split into multiple parts due to size, e.g. because it\n // has an attached image, and where the chunkedOp is within the top-level op's contents\n // (as opposed to being at the top-level). The contents of the chunks need to be\n // concatenated to form the complete stringified json object\n // Early return here to skip re-stringify because no changes are made until the last\n // chunk, and the ChunkedOpProcessor will handle everything at that point\n return this.fixChunkedOp(message);\n }\n case \"blobAttach\": {\n // TODO: handle this properly once blob api is used\n this.debugMsg(\"TODO: blobAttach ops are skipped/unhandled\");\n return;\n }\n default: {\n // A regular op\n this.fixOpContentsObject(msgContents);\n }\n }\n\n // re-stringify the json if needed\n if (typeof message.contents === \"string\") {\n try {\n message.contents = JSON.stringify(msgContents);\n } catch (e) {\n this.debugMsg(e);\n return;\n }\n }\n }\n\n /**\n * @param message - The top-level chunkedOp message or a top-level op message\n * with a chunkedOp inside its contents\n */\n fixChunkedOp(message: any) {\n this.chunkProcessor.addMessage(message);\n if (!this.chunkProcessor.hasAllMessages()) {\n return;\n }\n\n const contents = this.chunkProcessor.getConcatenatedContents();\n this.fixOpContentsObject(contents);\n\n this.chunkProcessor.writeSanitizedContents(contents);\n this.chunkProcessor.reset();\n }\n\n sanitize(): ISequencedDocumentMessage[] {\n let seq = 0;\n\n try {\n this.messages.map((message) => {\n seq = message.sequenceNumber;\n // message types from protocol-definitions' protocol.ts\n switch (message.type) {\n case \"join\": {\n this.fixJoin(message);\n break;\n }\n case \"propose\": {\n this.fixPropose(message);\n break;\n }\n case \"attach\": {\n this.fixAttach(message);\n break;\n }\n case \"op\": {\n this.fixOp(message);\n break;\n }\n case \"chunkedOp\": {\n this.fixChunkedOp(message);\n break;\n }\n case \"noop\":\n case \"leave\":\n case \"noClient\":\n case \"summarize\":\n case \"summaryAck\":\n case \"summaryNack\":\n break;\n default:\n this.debugMsg(`Unexpected op type ${message.type}`);\n }\n });\n\n // make sure we don't miss an incomplete chunked op at the end\n assert(!this.chunkProcessor.isPendingProcessing(), 0x08d /* \"After sanitize, pending incomplete ops!\" */);\n } catch (error) {\n this.debugMsg(`Error while processing sequenceNumber ${seq}`);\n throw error;\n }\n\n return this.messages;\n }\n}\n"]}
@@ -3,9 +3,7 @@ use_old_ClassDeclaration_DebuggerUI(get_current_ClassDeclaration_DebuggerUI());
3
3
  use_current_TypeAliasDeclaration_debuggerUIFactory(get_old_TypeAliasDeclaration_debuggerUIFactory());
4
4
  use_old_TypeAliasDeclaration_debuggerUIFactory(get_current_TypeAliasDeclaration_debuggerUIFactory());
5
5
  use_current_ClassDeclaration_DebugReplayController(get_old_ClassDeclaration_DebugReplayController());
6
- use_old_ClassDeclaration_DebugReplayController(
7
- // @ts-expect-error compatibility expected to be broken
8
- get_current_ClassDeclaration_DebugReplayController());
6
+ use_old_ClassDeclaration_DebugReplayController(get_current_ClassDeclaration_DebugReplayController());
9
7
  use_current_FunctionDeclaration_FluidDebugger_createFromService(get_old_FunctionDeclaration_FluidDebugger_createFromService());
10
8
  use_old_FunctionDeclaration_FluidDebugger_createFromService(get_current_FunctionDeclaration_FluidDebugger_createFromService());
11
9
  use_current_FunctionDeclaration_FluidDebugger_createFromServiceFactory(get_old_FunctionDeclaration_FluidDebugger_createFromServiceFactory());
@@ -1 +1 @@
1
- {"version":3,"file":"validateDebuggerPrevious.js","sourceRoot":"","sources":["../../../src/test/types/validateDebuggerPrevious.ts"],"names":[],"mappings":"AAwBA,uCAAuC,CACnC,mCAAmC,EAAE,CAAC,CAAC;AAW3C,mCAAmC,CAC/B,uCAAuC,EAAE,CAAC,CAAC;AAW/C,kDAAkD,CAC9C,8CAA8C,EAAE,CAAC,CAAC;AAWtD,8CAA8C,CAC1C,kDAAkD,EAAE,CAAC,CAAC;AAW1D,kDAAkD,CAC9C,8CAA8C,EAAE,CAAC,CAAC;AAWtD,8CAA8C;AAC1C,uDAAuD;AACvD,kDAAkD,EAAE,CAAC,CAAC;AAW1D,+DAA+D,CAC3D,2DAA2D,EAAE,CAAC,CAAC;AAWnE,2DAA2D,CACvD,+DAA+D,EAAE,CAAC,CAAC;AAWvE,sEAAsE,CAClE,kEAAkE,EAAE,CAAC,CAAC;AAW1E,kEAAkE,CAC9D,sEAAsE,EAAE,CAAC,CAAC;AAW9E,oDAAoD,CAChD,gDAAgD,EAAE,CAAC,CAAC;AAWxD,gDAAgD,CAC5C,oDAAoD,EAAE,CAAC,CAAC;AAW5D,4CAA4C,CACxC,wCAAwC,EAAE,CAAC,CAAC;AAWhD,wCAAwC,CACpC,4CAA4C,EAAE,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n/*\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n * Generated by fluid-type-validator in @fluidframework/build-tools.\n */\nimport * as old from \"@fluidframework/debugger-previous\";\nimport * as current from \"../../index\";\n\ntype TypeOnly<T> = {\n [P in keyof T]: TypeOnly<T[P]>;\n};\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DebuggerUI\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_ClassDeclaration_DebuggerUI():\n TypeOnly<old.DebuggerUI>;\ndeclare function use_current_ClassDeclaration_DebuggerUI(\n use: TypeOnly<current.DebuggerUI>);\nuse_current_ClassDeclaration_DebuggerUI(\n get_old_ClassDeclaration_DebuggerUI());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DebuggerUI\": {\"backCompat\": false}\n*/\ndeclare function get_current_ClassDeclaration_DebuggerUI():\n TypeOnly<current.DebuggerUI>;\ndeclare function use_old_ClassDeclaration_DebuggerUI(\n use: TypeOnly<old.DebuggerUI>);\nuse_old_ClassDeclaration_DebuggerUI(\n get_current_ClassDeclaration_DebuggerUI());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"TypeAliasDeclaration_debuggerUIFactory\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_TypeAliasDeclaration_debuggerUIFactory():\n TypeOnly<old.debuggerUIFactory>;\ndeclare function use_current_TypeAliasDeclaration_debuggerUIFactory(\n use: TypeOnly<current.debuggerUIFactory>);\nuse_current_TypeAliasDeclaration_debuggerUIFactory(\n get_old_TypeAliasDeclaration_debuggerUIFactory());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"TypeAliasDeclaration_debuggerUIFactory\": {\"backCompat\": false}\n*/\ndeclare function get_current_TypeAliasDeclaration_debuggerUIFactory():\n TypeOnly<current.debuggerUIFactory>;\ndeclare function use_old_TypeAliasDeclaration_debuggerUIFactory(\n use: TypeOnly<old.debuggerUIFactory>);\nuse_old_TypeAliasDeclaration_debuggerUIFactory(\n get_current_TypeAliasDeclaration_debuggerUIFactory());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DebugReplayController\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_ClassDeclaration_DebugReplayController():\n TypeOnly<old.DebugReplayController>;\ndeclare function use_current_ClassDeclaration_DebugReplayController(\n use: TypeOnly<current.DebugReplayController>);\nuse_current_ClassDeclaration_DebugReplayController(\n get_old_ClassDeclaration_DebugReplayController());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DebugReplayController\": {\"backCompat\": false}\n*/\ndeclare function get_current_ClassDeclaration_DebugReplayController():\n TypeOnly<current.DebugReplayController>;\ndeclare function use_old_ClassDeclaration_DebugReplayController(\n use: TypeOnly<old.DebugReplayController>);\nuse_old_ClassDeclaration_DebugReplayController(\n // @ts-expect-error compatibility expected to be broken\n get_current_ClassDeclaration_DebugReplayController());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"FunctionDeclaration_FluidDebugger.createFromService\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_FunctionDeclaration_FluidDebugger_createFromService():\n TypeOnly<typeof old.FluidDebugger.createFromService>;\ndeclare function use_current_FunctionDeclaration_FluidDebugger_createFromService(\n use: TypeOnly<typeof current.FluidDebugger.createFromService>);\nuse_current_FunctionDeclaration_FluidDebugger_createFromService(\n get_old_FunctionDeclaration_FluidDebugger_createFromService());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"FunctionDeclaration_FluidDebugger.createFromService\": {\"backCompat\": false}\n*/\ndeclare function get_current_FunctionDeclaration_FluidDebugger_createFromService():\n TypeOnly<typeof current.FluidDebugger.createFromService>;\ndeclare function use_old_FunctionDeclaration_FluidDebugger_createFromService(\n use: TypeOnly<typeof old.FluidDebugger.createFromService>);\nuse_old_FunctionDeclaration_FluidDebugger_createFromService(\n get_current_FunctionDeclaration_FluidDebugger_createFromService());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"FunctionDeclaration_FluidDebugger.createFromServiceFactory\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_FunctionDeclaration_FluidDebugger_createFromServiceFactory():\n TypeOnly<typeof old.FluidDebugger.createFromServiceFactory>;\ndeclare function use_current_FunctionDeclaration_FluidDebugger_createFromServiceFactory(\n use: TypeOnly<typeof current.FluidDebugger.createFromServiceFactory>);\nuse_current_FunctionDeclaration_FluidDebugger_createFromServiceFactory(\n get_old_FunctionDeclaration_FluidDebugger_createFromServiceFactory());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"FunctionDeclaration_FluidDebugger.createFromServiceFactory\": {\"backCompat\": false}\n*/\ndeclare function get_current_FunctionDeclaration_FluidDebugger_createFromServiceFactory():\n TypeOnly<typeof current.FluidDebugger.createFromServiceFactory>;\ndeclare function use_old_FunctionDeclaration_FluidDebugger_createFromServiceFactory(\n use: TypeOnly<typeof old.FluidDebugger.createFromServiceFactory>);\nuse_old_FunctionDeclaration_FluidDebugger_createFromServiceFactory(\n get_current_FunctionDeclaration_FluidDebugger_createFromServiceFactory());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"InterfaceDeclaration_IDebuggerController\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_InterfaceDeclaration_IDebuggerController():\n TypeOnly<old.IDebuggerController>;\ndeclare function use_current_InterfaceDeclaration_IDebuggerController(\n use: TypeOnly<current.IDebuggerController>);\nuse_current_InterfaceDeclaration_IDebuggerController(\n get_old_InterfaceDeclaration_IDebuggerController());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"InterfaceDeclaration_IDebuggerController\": {\"backCompat\": false}\n*/\ndeclare function get_current_InterfaceDeclaration_IDebuggerController():\n TypeOnly<current.IDebuggerController>;\ndeclare function use_old_InterfaceDeclaration_IDebuggerController(\n use: TypeOnly<old.IDebuggerController>);\nuse_old_InterfaceDeclaration_IDebuggerController(\n get_current_InterfaceDeclaration_IDebuggerController());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"InterfaceDeclaration_IDebuggerUI\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_InterfaceDeclaration_IDebuggerUI():\n TypeOnly<old.IDebuggerUI>;\ndeclare function use_current_InterfaceDeclaration_IDebuggerUI(\n use: TypeOnly<current.IDebuggerUI>);\nuse_current_InterfaceDeclaration_IDebuggerUI(\n get_old_InterfaceDeclaration_IDebuggerUI());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"InterfaceDeclaration_IDebuggerUI\": {\"backCompat\": false}\n*/\ndeclare function get_current_InterfaceDeclaration_IDebuggerUI():\n TypeOnly<current.IDebuggerUI>;\ndeclare function use_old_InterfaceDeclaration_IDebuggerUI(\n use: TypeOnly<old.IDebuggerUI>);\nuse_old_InterfaceDeclaration_IDebuggerUI(\n get_current_InterfaceDeclaration_IDebuggerUI());\n"]}
1
+ {"version":3,"file":"validateDebuggerPrevious.js","sourceRoot":"","sources":["../../../src/test/types/validateDebuggerPrevious.ts"],"names":[],"mappings":"AAwBA,uCAAuC,CACnC,mCAAmC,EAAE,CAAC,CAAC;AAW3C,mCAAmC,CAC/B,uCAAuC,EAAE,CAAC,CAAC;AAW/C,kDAAkD,CAC9C,8CAA8C,EAAE,CAAC,CAAC;AAWtD,8CAA8C,CAC1C,kDAAkD,EAAE,CAAC,CAAC;AAW1D,kDAAkD,CAC9C,8CAA8C,EAAE,CAAC,CAAC;AAWtD,8CAA8C,CAC1C,kDAAkD,EAAE,CAAC,CAAC;AAW1D,+DAA+D,CAC3D,2DAA2D,EAAE,CAAC,CAAC;AAWnE,2DAA2D,CACvD,+DAA+D,EAAE,CAAC,CAAC;AAWvE,sEAAsE,CAClE,kEAAkE,EAAE,CAAC,CAAC;AAW1E,kEAAkE,CAC9D,sEAAsE,EAAE,CAAC,CAAC;AAW9E,oDAAoD,CAChD,gDAAgD,EAAE,CAAC,CAAC;AAWxD,gDAAgD,CAC5C,oDAAoD,EAAE,CAAC,CAAC;AAW5D,4CAA4C,CACxC,wCAAwC,EAAE,CAAC,CAAC;AAWhD,wCAAwC,CACpC,4CAA4C,EAAE,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n/*\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n * Generated by fluid-type-validator in @fluidframework/build-tools.\n */\nimport * as old from \"@fluidframework/debugger-previous\";\nimport * as current from \"../../index\";\n\ntype TypeOnly<T> = {\n [P in keyof T]: TypeOnly<T[P]>;\n};\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DebuggerUI\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_ClassDeclaration_DebuggerUI():\n TypeOnly<old.DebuggerUI>;\ndeclare function use_current_ClassDeclaration_DebuggerUI(\n use: TypeOnly<current.DebuggerUI>);\nuse_current_ClassDeclaration_DebuggerUI(\n get_old_ClassDeclaration_DebuggerUI());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DebuggerUI\": {\"backCompat\": false}\n*/\ndeclare function get_current_ClassDeclaration_DebuggerUI():\n TypeOnly<current.DebuggerUI>;\ndeclare function use_old_ClassDeclaration_DebuggerUI(\n use: TypeOnly<old.DebuggerUI>);\nuse_old_ClassDeclaration_DebuggerUI(\n get_current_ClassDeclaration_DebuggerUI());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"TypeAliasDeclaration_debuggerUIFactory\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_TypeAliasDeclaration_debuggerUIFactory():\n TypeOnly<old.debuggerUIFactory>;\ndeclare function use_current_TypeAliasDeclaration_debuggerUIFactory(\n use: TypeOnly<current.debuggerUIFactory>);\nuse_current_TypeAliasDeclaration_debuggerUIFactory(\n get_old_TypeAliasDeclaration_debuggerUIFactory());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"TypeAliasDeclaration_debuggerUIFactory\": {\"backCompat\": false}\n*/\ndeclare function get_current_TypeAliasDeclaration_debuggerUIFactory():\n TypeOnly<current.debuggerUIFactory>;\ndeclare function use_old_TypeAliasDeclaration_debuggerUIFactory(\n use: TypeOnly<old.debuggerUIFactory>);\nuse_old_TypeAliasDeclaration_debuggerUIFactory(\n get_current_TypeAliasDeclaration_debuggerUIFactory());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DebugReplayController\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_ClassDeclaration_DebugReplayController():\n TypeOnly<old.DebugReplayController>;\ndeclare function use_current_ClassDeclaration_DebugReplayController(\n use: TypeOnly<current.DebugReplayController>);\nuse_current_ClassDeclaration_DebugReplayController(\n get_old_ClassDeclaration_DebugReplayController());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DebugReplayController\": {\"backCompat\": false}\n*/\ndeclare function get_current_ClassDeclaration_DebugReplayController():\n TypeOnly<current.DebugReplayController>;\ndeclare function use_old_ClassDeclaration_DebugReplayController(\n use: TypeOnly<old.DebugReplayController>);\nuse_old_ClassDeclaration_DebugReplayController(\n get_current_ClassDeclaration_DebugReplayController());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"FunctionDeclaration_FluidDebugger.createFromService\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_FunctionDeclaration_FluidDebugger_createFromService():\n TypeOnly<typeof old.FluidDebugger.createFromService>;\ndeclare function use_current_FunctionDeclaration_FluidDebugger_createFromService(\n use: TypeOnly<typeof current.FluidDebugger.createFromService>);\nuse_current_FunctionDeclaration_FluidDebugger_createFromService(\n get_old_FunctionDeclaration_FluidDebugger_createFromService());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"FunctionDeclaration_FluidDebugger.createFromService\": {\"backCompat\": false}\n*/\ndeclare function get_current_FunctionDeclaration_FluidDebugger_createFromService():\n TypeOnly<typeof current.FluidDebugger.createFromService>;\ndeclare function use_old_FunctionDeclaration_FluidDebugger_createFromService(\n use: TypeOnly<typeof old.FluidDebugger.createFromService>);\nuse_old_FunctionDeclaration_FluidDebugger_createFromService(\n get_current_FunctionDeclaration_FluidDebugger_createFromService());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"FunctionDeclaration_FluidDebugger.createFromServiceFactory\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_FunctionDeclaration_FluidDebugger_createFromServiceFactory():\n TypeOnly<typeof old.FluidDebugger.createFromServiceFactory>;\ndeclare function use_current_FunctionDeclaration_FluidDebugger_createFromServiceFactory(\n use: TypeOnly<typeof current.FluidDebugger.createFromServiceFactory>);\nuse_current_FunctionDeclaration_FluidDebugger_createFromServiceFactory(\n get_old_FunctionDeclaration_FluidDebugger_createFromServiceFactory());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"FunctionDeclaration_FluidDebugger.createFromServiceFactory\": {\"backCompat\": false}\n*/\ndeclare function get_current_FunctionDeclaration_FluidDebugger_createFromServiceFactory():\n TypeOnly<typeof current.FluidDebugger.createFromServiceFactory>;\ndeclare function use_old_FunctionDeclaration_FluidDebugger_createFromServiceFactory(\n use: TypeOnly<typeof old.FluidDebugger.createFromServiceFactory>);\nuse_old_FunctionDeclaration_FluidDebugger_createFromServiceFactory(\n get_current_FunctionDeclaration_FluidDebugger_createFromServiceFactory());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"InterfaceDeclaration_IDebuggerController\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_InterfaceDeclaration_IDebuggerController():\n TypeOnly<old.IDebuggerController>;\ndeclare function use_current_InterfaceDeclaration_IDebuggerController(\n use: TypeOnly<current.IDebuggerController>);\nuse_current_InterfaceDeclaration_IDebuggerController(\n get_old_InterfaceDeclaration_IDebuggerController());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"InterfaceDeclaration_IDebuggerController\": {\"backCompat\": false}\n*/\ndeclare function get_current_InterfaceDeclaration_IDebuggerController():\n TypeOnly<current.IDebuggerController>;\ndeclare function use_old_InterfaceDeclaration_IDebuggerController(\n use: TypeOnly<old.IDebuggerController>);\nuse_old_InterfaceDeclaration_IDebuggerController(\n get_current_InterfaceDeclaration_IDebuggerController());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"InterfaceDeclaration_IDebuggerUI\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_InterfaceDeclaration_IDebuggerUI():\n TypeOnly<old.IDebuggerUI>;\ndeclare function use_current_InterfaceDeclaration_IDebuggerUI(\n use: TypeOnly<current.IDebuggerUI>);\nuse_current_InterfaceDeclaration_IDebuggerUI(\n get_old_InterfaceDeclaration_IDebuggerUI());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"InterfaceDeclaration_IDebuggerUI\": {\"backCompat\": false}\n*/\ndeclare function get_current_InterfaceDeclaration_IDebuggerUI():\n TypeOnly<current.IDebuggerUI>;\ndeclare function use_old_InterfaceDeclaration_IDebuggerUI(\n use: TypeOnly<old.IDebuggerUI>);\nuse_old_InterfaceDeclaration_IDebuggerUI(\n get_current_InterfaceDeclaration_IDebuggerUI());\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/debugger",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Fluid Debugger - a tool to play through history of a file",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -16,7 +16,7 @@
16
16
  "types": "dist/index.d.ts",
17
17
  "scripts": {
18
18
  "build": "concurrently npm:build:compile npm:lint && npm run build:docs",
19
- "build:compile": "concurrently npm:tsc npm:build:esnext",
19
+ "build:compile": "concurrently npm:typetests:gen npm:tsc npm:build:esnext",
20
20
  "build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
21
21
  "build:esnext": "tsc --project ./tsconfig.esnext.json",
22
22
  "build:full": "npm run build",
@@ -29,20 +29,21 @@
29
29
  "lint:fix": "npm run eslint:fix",
30
30
  "tsc": "tsc",
31
31
  "tsfmt": "tsfmt --verify",
32
- "tsfmt:fix": "tsfmt --replace"
32
+ "tsfmt:fix": "tsfmt --replace",
33
+ "typetests:gen": "fluid-type-validator -g -d ."
33
34
  },
34
35
  "dependencies": {
35
36
  "@fluidframework/common-utils": "^0.32.1",
36
- "@fluidframework/driver-definitions": "^1.0.1",
37
- "@fluidframework/driver-utils": "^1.0.1",
37
+ "@fluidframework/driver-definitions": "^1.1.0",
38
+ "@fluidframework/driver-utils": "^1.1.0",
38
39
  "@fluidframework/protocol-definitions": "^0.1028.2000",
39
- "@fluidframework/replay-driver": "^1.0.1",
40
+ "@fluidframework/replay-driver": "^1.1.0",
40
41
  "jsonschema": "^1.2.6"
41
42
  },
42
43
  "devDependencies": {
43
- "@fluidframework/build-common": "^0.23.0",
44
- "@fluidframework/build-tools": "^0.2.71273",
45
- "@fluidframework/debugger-previous": "npm:@fluidframework/debugger@0.59.3000",
44
+ "@fluidframework/build-common": "^0.24.0",
45
+ "@fluidframework/build-tools": "^0.2.74327",
46
+ "@fluidframework/debugger-previous": "npm:@fluidframework/debugger@^1.0.0",
46
47
  "@fluidframework/eslint-config-fluid": "^0.28.2000",
47
48
  "@microsoft/api-extractor": "^7.22.2",
48
49
  "@rushstack/eslint-config": "^2.5.1",
@@ -57,11 +58,7 @@
57
58
  "typescript-formatter": "7.1.0"
58
59
  },
59
60
  "typeValidation": {
60
- "version": "1.0.0",
61
- "broken": {
62
- "ClassDeclaration_DebugReplayController": {
63
- "backCompat": false
64
- }
65
- }
61
+ "version": "1.1.0",
62
+ "broken": {}
66
63
  }
67
64
  }
package/src/sanitizer.ts CHANGED
@@ -581,29 +581,37 @@ export class Sanitizer {
581
581
  }
582
582
 
583
583
  // handle container message types
584
- if (msgContents.type === "attach") {
585
- // this one is like a regular attach op, except its contents aren't nested as deep
586
- // run fixAttach directly and return
587
- this.fixAttach(msgContents);
588
- } else if (msgContents.type === "component") {
589
- // this one functionally nests its contents one layer deeper
590
- // bring up the contents object and continue as usual
591
- this.fixOpContentsObject(msgContents.contents);
592
- } else if (msgContents.type === "chunkedOp") {
593
- // this is a (regular?) op split into multiple parts due to size, e.g. because it
594
- // has an attached image, and where the chunkedOp is within the top-level op's contents
595
- // (as opposed to being at the top-level). The contents of the chunks need to be
596
- // concatenated to form the complete stringified json object
597
- // Early return here to skip re-stringify because no changes are made until the last
598
- // chunk, and the ChunkedOpProcessor will handle everything at that point
599
- return this.fixChunkedOp(message);
600
- } else if (msgContents.type === "blobAttach") {
601
- // TODO: handle this properly once blob api is used
602
- this.debugMsg("TODO: blobAttach ops are skipped/unhandled");
603
- return;
604
- } else {
605
- // A regular op
606
- this.fixOpContentsObject(msgContents);
584
+ switch (msgContents.type) {
585
+ case "attach": {
586
+ // this one is like a regular attach op, except its contents aren't nested as deep
587
+ // run fixAttach directly and return
588
+ this.fixAttach(msgContents);
589
+ break;
590
+ }
591
+ case "component": {
592
+ // this one functionally nests its contents one layer deeper
593
+ // bring up the contents object and continue as usual
594
+ this.fixOpContentsObject(msgContents.contents);
595
+ break;
596
+ }
597
+ case "chunkedOp": {
598
+ // this is a (regular?) op split into multiple parts due to size, e.g. because it
599
+ // has an attached image, and where the chunkedOp is within the top-level op's contents
600
+ // (as opposed to being at the top-level). The contents of the chunks need to be
601
+ // concatenated to form the complete stringified json object
602
+ // Early return here to skip re-stringify because no changes are made until the last
603
+ // chunk, and the ChunkedOpProcessor will handle everything at that point
604
+ return this.fixChunkedOp(message);
605
+ }
606
+ case "blobAttach": {
607
+ // TODO: handle this properly once blob api is used
608
+ this.debugMsg("TODO: blobAttach ops are skipped/unhandled");
609
+ return;
610
+ }
611
+ default: {
612
+ // A regular op
613
+ this.fixOpContentsObject(msgContents);
614
+ }
607
615
  }
608
616
 
609
617
  // re-stringify the json if needed