@fluidframework/tinylicious-driver 2.0.0-internal.3.0.2 → 2.0.0-internal.3.2.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.
- package/.eslintrc.js +8 -10
- package/dist/insecureTinyliciousTokenProvider.d.ts.map +1 -1
- package/dist/insecureTinyliciousTokenProvider.js +1 -5
- package/dist/insecureTinyliciousTokenProvider.js.map +1 -1
- package/dist/insecureTinyliciousUrlResolver.d.ts.map +1 -1
- package/dist/insecureTinyliciousUrlResolver.js.map +1 -1
- package/lib/insecureTinyliciousTokenProvider.d.ts.map +1 -1
- package/lib/insecureTinyliciousTokenProvider.js +1 -5
- package/lib/insecureTinyliciousTokenProvider.js.map +1 -1
- package/lib/insecureTinyliciousUrlResolver.d.ts.map +1 -1
- package/lib/insecureTinyliciousUrlResolver.js.map +1 -1
- package/package.json +33 -32
- package/prettier.config.cjs +1 -1
- package/src/insecureTinyliciousTokenProvider.ts +52 -65
- package/src/insecureTinyliciousUrlResolver.ts +75 -81
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
package/.eslintrc.js
CHANGED
|
@@ -4,13 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
module.exports = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
}
|
|
7
|
+
extends: [require.resolve("@fluidframework/eslint-config-fluid"), "prettier"],
|
|
8
|
+
parserOptions: {
|
|
9
|
+
project: ["./tsconfig.json", "./src/test/tsconfig.json"],
|
|
10
|
+
},
|
|
11
|
+
rules: {
|
|
12
|
+
"@typescript-eslint/strict-boolean-expressions": "off",
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insecureTinyliciousTokenProvider.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAgB,MAAM,sCAAsC,CAAC;AAC/E,OAAO,
|
|
1
|
+
{"version":3,"file":"insecureTinyliciousTokenProvider.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAgB,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAKtF;;;GAGG;AACH,qBAAa,gCAAiC,YAAW,cAAc;IAErE;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;;IARxB;;;;;;;OAOG;IACc,MAAM,CAAC,yBAAa;IAGzB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAOjF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAO7F,OAAO,CAAC,cAAc;CA8BtB"}
|
|
@@ -45,11 +45,7 @@ class InsecureTinyliciousTokenProvider {
|
|
|
45
45
|
const user = { id: (0, uuid_1.v4)(), name: (0, server_services_client_1.getRandomName)() };
|
|
46
46
|
const claims = {
|
|
47
47
|
documentId: documentId !== null && documentId !== void 0 ? documentId : "",
|
|
48
|
-
scopes: (_a = this.scopes) !== null && _a !== void 0 ? _a : [
|
|
49
|
-
protocol_definitions_1.ScopeType.DocRead,
|
|
50
|
-
protocol_definitions_1.ScopeType.DocWrite,
|
|
51
|
-
protocol_definitions_1.ScopeType.SummaryWrite,
|
|
52
|
-
],
|
|
48
|
+
scopes: (_a = this.scopes) !== null && _a !== void 0 ? _a : [protocol_definitions_1.ScopeType.DocRead, protocol_definitions_1.ScopeType.DocWrite, protocol_definitions_1.ScopeType.SummaryWrite],
|
|
53
49
|
tenantId,
|
|
54
50
|
user,
|
|
55
51
|
iat: now,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insecureTinyliciousTokenProvider.js","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+EAA+E;
|
|
1
|
+
{"version":3,"file":"insecureTinyliciousTokenProvider.js","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+EAA+E;AAE/E,mFAAuE;AACvE,yCAA8C;AAC9C,+BAAkC;AAElC;;;GAGG;AACH,MAAa,gCAAgC;IAC5C;IACC;;;;;;;OAOG;IACc,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;IACnC,CAAC;IAEG,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAmB;QACnE,OAAO;YACN,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SAC9C,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAClE,OAAO;YACN,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SAC9C,CAAC;IACH,CAAC;IAEO,cAAc,CACrB,QAAgB,EAChB,UAA8B,EAC9B,WAAmB,EAAE,GAAG,EAAE,EAC1B,MAAc,KAAK;;QAEnB,0BAA0B;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,IAAA,SAAI,GAAE,EAAE,IAAI,EAAE,IAAA,sCAAa,GAAE,EAAE,CAAC;QAEnD,MAAM,MAAM,GAAiB;YAC5B,UAAU,EAAE,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,EAAE;YAC5B,MAAM,EAAE,MAAA,IAAI,CAAC,MAAM,mCAAI,CAAC,gCAAS,CAAC,OAAO,EAAE,gCAAS,CAAC,QAAQ,EAAE,gCAAS,CAAC,YAAY,CAAC;YACtF,QAAQ;YACR,IAAI;YACJ,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG,GAAG,QAAQ;YACnB,GAAG;SACH,CAAC;QAEF,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAClC,OAAO,gBAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;QAC5B,2BAA2B;QAC3B,2CAA2C;QAC3C,IAAI,EACJ,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAC5C,MAAM,EACN,OAAO,CACP,CAAC;IACH,CAAC;CACD;AAzDD,4EAyDC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ScopeType, ITokenClaims } from \"@fluidframework/protocol-definitions\";\nimport { ITokenProvider, ITokenResponse } from \"@fluidframework/routerlicious-driver\";\nimport { getRandomName } from \"@fluidframework/server-services-client\";\nimport { KJUR as jsrsasign } from \"jsrsasign\";\nimport { v4 as uuid } from \"uuid\";\n\n/**\n * As the name implies this is not secure and should not be used in production. It simply makes the example easier\n * to get up and running.\n */\nexport class InsecureTinyliciousTokenProvider implements ITokenProvider {\n\tconstructor(\n\t\t/**\n\t\t * Optional. Override of scopes. If a param is not provided, InsecureTinyliciousTokenProvider\n\t\t * will use the default scopes which are document read, write and summarizer write.\n\t\t *\n\t\t * @param scopes - See {@link @fluidframework/protocol-definitions#ITokenClaims.scopes}\n\t\t *\n\t\t * @defaultValue - [ ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite ]\n\t\t */\n\t\tprivate readonly scopes?: ScopeType[],\n\t) {}\n\n\tpublic async fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse> {\n\t\treturn {\n\t\t\tfromCache: true,\n\t\t\tjwt: this.getSignedToken(tenantId, documentId),\n\t\t};\n\t}\n\n\tpublic async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n\t\treturn {\n\t\t\tfromCache: true,\n\t\t\tjwt: this.getSignedToken(tenantId, documentId),\n\t\t};\n\t}\n\n\tprivate getSignedToken(\n\t\ttenantId: string,\n\t\tdocumentId: string | undefined,\n\t\tlifetime: number = 60 * 60,\n\t\tver: string = \"1.0\",\n\t): string {\n\t\t// Current time in seconds\n\t\tconst now = Math.round(Date.now() / 1000);\n\t\tconst user = { id: uuid(), name: getRandomName() };\n\n\t\tconst claims: ITokenClaims = {\n\t\t\tdocumentId: documentId ?? \"\",\n\t\t\tscopes: this.scopes ?? [ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite],\n\t\t\ttenantId,\n\t\t\tuser,\n\t\t\tiat: now,\n\t\t\texp: now + lifetime,\n\t\t\tver,\n\t\t};\n\n\t\tconst utf8Key = { utf8: \"12345\" };\n\t\treturn jsrsasign.jws.JWS.sign(\n\t\t\t// External API uses `null`\n\t\t\t// eslint-disable-next-line unicorn/no-null\n\t\t\tnull,\n\t\t\tJSON.stringify({ alg: \"HS256\", typ: \"JWT\" }),\n\t\t\tclaims,\n\t\t\tutf8Key,\n\t\t);\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insecureTinyliciousUrlResolver.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,
|
|
1
|
+
{"version":3,"file":"insecureTinyliciousUrlResolver.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAEN,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,MAAM,oCAAoC,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,0BAA0B,qBAAqB,CAAC;AAE7D;;;;;GAKG;AACH,qBAAa,8BAA+B,YAAW,YAAY;IAClE,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;gBAC1B,IAAI,SAAyB,EAAE,QAAQ,SAA6B;IAK1E,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IA+CjD,cAAc,CAC1B,WAAW,EAAE,iBAAiB,EAC9B,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC;CAYlB;AAED,eAAO,MAAM,iCAAiC,uCAA0B,QAKtE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insecureTinyliciousUrlResolver.js","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,2EAK4C;AAE5C;;GAEG;AACU,QAAA,sBAAsB,GAAG,IAAI,CAAC;AAE3C;;GAEG;AACU,QAAA,0BAA0B,GAAG,kBAAkB,CAAC;AAE7D;;;;;GAKG;AACH,MAAa,8BAA8B;
|
|
1
|
+
{"version":3,"file":"insecureTinyliciousUrlResolver.js","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.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\nimport { IRequest } from \"@fluidframework/core-interfaces\";\nimport {\n\tDriverHeader,\n\tIFluidResolvedUrl,\n\tIResolvedUrl,\n\tIUrlResolver,\n} from \"@fluidframework/driver-definitions\";\n\n/**\n * Default endpoint port. Will be used by the service if the consumer does not specify a port.\n */\nexport const defaultTinyliciousPort = 7070;\n\n/**\n * Default endpoint URL base. Will be used by the service if the consumer does not specify an endpoint.\n */\nexport const defaultTinyliciousEndpoint = \"http://localhost\";\n\n/**\n * InsecureTinyliciousUrlResolver knows how to get the URLs to the service (in this case Tinylicious) to use\n * for a given request. This particular implementation has a goal to avoid imposing requirements on the app's\n * URL shape, so it expects the request url to have this format (as opposed to a more traditional URL):\n * documentId/containerRelativePathing\n */\nexport class InsecureTinyliciousUrlResolver implements IUrlResolver {\n\tprivate readonly fluidProtocolEndpoint: string;\n\tprivate readonly tinyliciousEndpoint: string;\n\tpublic constructor(port = defaultTinyliciousPort, endpoint = defaultTinyliciousEndpoint) {\n\t\tthis.tinyliciousEndpoint = `${endpoint}:${port}`;\n\t\tthis.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\\w+:|^)\\/\\//, \"fluid://\");\n\t}\n\n\tpublic async resolve(request: IRequest): Promise<IResolvedUrl> {\n\t\t// determine whether the request is for creating of a new container.\n\t\t// such request has the `createNew` header set to true and doesn't have a container ID.\n\t\tif (request.headers && request.headers[DriverHeader.createNew] === true) {\n\t\t\t// honor the document ID passed by the application via the create request\n\t\t\t// otherwise use the reserved keyword to let the driver generate the ID.\n\t\t\t// TODO: deprecate this capability for tinylicious as the r11s driver will stop using the document ID\n\t\t\t// in create requests.\n\t\t\tconst newDocumentId = request.url ?? \"new\";\n\t\t\treturn {\n\t\t\t\tendpoints: {\n\t\t\t\t\tdeltaStorageUrl: `${this.tinyliciousEndpoint}/deltas/tinylicious/${newDocumentId}`,\n\t\t\t\t\tordererUrl: this.tinyliciousEndpoint,\n\t\t\t\t\tstorageUrl: `${this.tinyliciousEndpoint}/repos/tinylicious`,\n\t\t\t\t},\n\t\t\t\t// id is a mandatory attribute, but it's ignored by the driver for new container requests.\n\t\t\t\tid: request.url,\n\t\t\t\t// tokens attribute is redundant as all tokens are generated via ITokenProvider\n\t\t\t\ttokens: {},\n\t\t\t\ttype: \"fluid\",\n\t\t\t\turl: `${this.fluidProtocolEndpoint}/tinylicious/${newDocumentId}`,\n\t\t\t};\n\t\t}\n\t\t// for an existing container we'll parse the request URL to determine the document ID.\n\t\tconst url = request.url.replace(`${this.tinyliciousEndpoint}/`, \"\");\n\t\tconst documentId = url.split(\"/\")[0];\n\t\tconst encodedDocId = encodeURIComponent(documentId);\n\t\tconst documentRelativePath = url.slice(documentId.length);\n\n\t\tconst documentUrl = `${this.fluidProtocolEndpoint}/tinylicious/${encodedDocId}${documentRelativePath}`;\n\t\tconst deltaStorageUrl = `${this.tinyliciousEndpoint}/deltas/tinylicious/${encodedDocId}`;\n\t\tconst storageUrl = `${this.tinyliciousEndpoint}/repos/tinylicious`;\n\n\t\tconst response: IFluidResolvedUrl = {\n\t\t\tendpoints: {\n\t\t\t\tdeltaStorageUrl,\n\t\t\t\tordererUrl: this.tinyliciousEndpoint,\n\t\t\t\tstorageUrl,\n\t\t\t},\n\t\t\tid: documentId,\n\t\t\ttokens: {},\n\t\t\ttype: \"fluid\",\n\t\t\turl: documentUrl,\n\t\t};\n\t\treturn response;\n\t}\n\n\tpublic async getAbsoluteUrl(\n\t\tresolvedUrl: IFluidResolvedUrl,\n\t\trelativeUrl: string,\n\t): Promise<string> {\n\t\tconst documentId = decodeURIComponent(\n\t\t\tresolvedUrl.url.replace(`${this.fluidProtocolEndpoint}/tinylicious/`, \"\"),\n\t\t);\n\t\t/*\n\t\t * The detached container flow will ultimately call getAbsoluteUrl() with the resolved.url produced by\n\t\t * resolve(). The container expects getAbsoluteUrl's return value to be a URL that can then be roundtripped\n\t\t * back through resolve() again, and get the same result again. So we'll return a \"URL\" with the same format\n\t\t * described above.\n\t\t */\n\t\treturn `${documentId}/${relativeUrl}`;\n\t}\n}\n\nexport const createTinyliciousCreateNewRequest = (documentId?: string): IRequest => ({\n\turl: documentId ?? \"\",\n\theaders: {\n\t\t[DriverHeader.createNew]: true,\n\t},\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insecureTinyliciousTokenProvider.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAgB,MAAM,sCAAsC,CAAC;AAC/E,OAAO,
|
|
1
|
+
{"version":3,"file":"insecureTinyliciousTokenProvider.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAgB,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAKtF;;;GAGG;AACH,qBAAa,gCAAiC,YAAW,cAAc;IAErE;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;;IARxB;;;;;;;OAOG;IACc,MAAM,CAAC,yBAAa;IAGzB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAOjF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAO7F,OAAO,CAAC,cAAc;CA8BtB"}
|
|
@@ -42,11 +42,7 @@ export class InsecureTinyliciousTokenProvider {
|
|
|
42
42
|
const user = { id: uuid(), name: getRandomName() };
|
|
43
43
|
const claims = {
|
|
44
44
|
documentId: documentId !== null && documentId !== void 0 ? documentId : "",
|
|
45
|
-
scopes: (_a = this.scopes) !== null && _a !== void 0 ? _a : [
|
|
46
|
-
ScopeType.DocRead,
|
|
47
|
-
ScopeType.DocWrite,
|
|
48
|
-
ScopeType.SummaryWrite,
|
|
49
|
-
],
|
|
45
|
+
scopes: (_a = this.scopes) !== null && _a !== void 0 ? _a : [ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite],
|
|
50
46
|
tenantId,
|
|
51
47
|
user,
|
|
52
48
|
iat: now,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insecureTinyliciousTokenProvider.js","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAgB,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"insecureTinyliciousTokenProvider.js","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAgB,MAAM,sCAAsC,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAElC;;;GAGG;AACH,MAAM,OAAO,gCAAgC;IAC5C;IACC;;;;;;;OAOG;IACc,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;IACnC,CAAC;IAEG,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAmB;QACnE,OAAO;YACN,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SAC9C,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAClE,OAAO;YACN,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SAC9C,CAAC;IACH,CAAC;IAEO,cAAc,CACrB,QAAgB,EAChB,UAA8B,EAC9B,WAAmB,EAAE,GAAG,EAAE,EAC1B,MAAc,KAAK;;QAEnB,0BAA0B;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC;QAEnD,MAAM,MAAM,GAAiB;YAC5B,UAAU,EAAE,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,EAAE;YAC5B,MAAM,EAAE,MAAA,IAAI,CAAC,MAAM,mCAAI,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,YAAY,CAAC;YACtF,QAAQ;YACR,IAAI;YACJ,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG,GAAG,QAAQ;YACnB,GAAG;SACH,CAAC;QAEF,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;QAC5B,2BAA2B;QAC3B,2CAA2C;QAC3C,IAAI,EACJ,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAC5C,MAAM,EACN,OAAO,CACP,CAAC;IACH,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ScopeType, ITokenClaims } from \"@fluidframework/protocol-definitions\";\nimport { ITokenProvider, ITokenResponse } from \"@fluidframework/routerlicious-driver\";\nimport { getRandomName } from \"@fluidframework/server-services-client\";\nimport { KJUR as jsrsasign } from \"jsrsasign\";\nimport { v4 as uuid } from \"uuid\";\n\n/**\n * As the name implies this is not secure and should not be used in production. It simply makes the example easier\n * to get up and running.\n */\nexport class InsecureTinyliciousTokenProvider implements ITokenProvider {\n\tconstructor(\n\t\t/**\n\t\t * Optional. Override of scopes. If a param is not provided, InsecureTinyliciousTokenProvider\n\t\t * will use the default scopes which are document read, write and summarizer write.\n\t\t *\n\t\t * @param scopes - See {@link @fluidframework/protocol-definitions#ITokenClaims.scopes}\n\t\t *\n\t\t * @defaultValue - [ ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite ]\n\t\t */\n\t\tprivate readonly scopes?: ScopeType[],\n\t) {}\n\n\tpublic async fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse> {\n\t\treturn {\n\t\t\tfromCache: true,\n\t\t\tjwt: this.getSignedToken(tenantId, documentId),\n\t\t};\n\t}\n\n\tpublic async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n\t\treturn {\n\t\t\tfromCache: true,\n\t\t\tjwt: this.getSignedToken(tenantId, documentId),\n\t\t};\n\t}\n\n\tprivate getSignedToken(\n\t\ttenantId: string,\n\t\tdocumentId: string | undefined,\n\t\tlifetime: number = 60 * 60,\n\t\tver: string = \"1.0\",\n\t): string {\n\t\t// Current time in seconds\n\t\tconst now = Math.round(Date.now() / 1000);\n\t\tconst user = { id: uuid(), name: getRandomName() };\n\n\t\tconst claims: ITokenClaims = {\n\t\t\tdocumentId: documentId ?? \"\",\n\t\t\tscopes: this.scopes ?? [ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite],\n\t\t\ttenantId,\n\t\t\tuser,\n\t\t\tiat: now,\n\t\t\texp: now + lifetime,\n\t\t\tver,\n\t\t};\n\n\t\tconst utf8Key = { utf8: \"12345\" };\n\t\treturn jsrsasign.jws.JWS.sign(\n\t\t\t// External API uses `null`\n\t\t\t// eslint-disable-next-line unicorn/no-null\n\t\t\tnull,\n\t\t\tJSON.stringify({ alg: \"HS256\", typ: \"JWT\" }),\n\t\t\tclaims,\n\t\t\tutf8Key,\n\t\t);\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insecureTinyliciousUrlResolver.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,
|
|
1
|
+
{"version":3,"file":"insecureTinyliciousUrlResolver.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAEN,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,MAAM,oCAAoC,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,0BAA0B,qBAAqB,CAAC;AAE7D;;;;;GAKG;AACH,qBAAa,8BAA+B,YAAW,YAAY;IAClE,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;gBAC1B,IAAI,SAAyB,EAAE,QAAQ,SAA6B;IAK1E,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IA+CjD,cAAc,CAC1B,WAAW,EAAE,iBAAiB,EAC9B,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC;CAYlB;AAED,eAAO,MAAM,iCAAiC,uCAA0B,QAKtE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insecureTinyliciousUrlResolver.js","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"insecureTinyliciousUrlResolver.js","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.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\nimport { IRequest } from \"@fluidframework/core-interfaces\";\nimport {\n\tDriverHeader,\n\tIFluidResolvedUrl,\n\tIResolvedUrl,\n\tIUrlResolver,\n} from \"@fluidframework/driver-definitions\";\n\n/**\n * Default endpoint port. Will be used by the service if the consumer does not specify a port.\n */\nexport const defaultTinyliciousPort = 7070;\n\n/**\n * Default endpoint URL base. Will be used by the service if the consumer does not specify an endpoint.\n */\nexport const defaultTinyliciousEndpoint = \"http://localhost\";\n\n/**\n * InsecureTinyliciousUrlResolver knows how to get the URLs to the service (in this case Tinylicious) to use\n * for a given request. This particular implementation has a goal to avoid imposing requirements on the app's\n * URL shape, so it expects the request url to have this format (as opposed to a more traditional URL):\n * documentId/containerRelativePathing\n */\nexport class InsecureTinyliciousUrlResolver implements IUrlResolver {\n\tprivate readonly fluidProtocolEndpoint: string;\n\tprivate readonly tinyliciousEndpoint: string;\n\tpublic constructor(port = defaultTinyliciousPort, endpoint = defaultTinyliciousEndpoint) {\n\t\tthis.tinyliciousEndpoint = `${endpoint}:${port}`;\n\t\tthis.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\\w+:|^)\\/\\//, \"fluid://\");\n\t}\n\n\tpublic async resolve(request: IRequest): Promise<IResolvedUrl> {\n\t\t// determine whether the request is for creating of a new container.\n\t\t// such request has the `createNew` header set to true and doesn't have a container ID.\n\t\tif (request.headers && request.headers[DriverHeader.createNew] === true) {\n\t\t\t// honor the document ID passed by the application via the create request\n\t\t\t// otherwise use the reserved keyword to let the driver generate the ID.\n\t\t\t// TODO: deprecate this capability for tinylicious as the r11s driver will stop using the document ID\n\t\t\t// in create requests.\n\t\t\tconst newDocumentId = request.url ?? \"new\";\n\t\t\treturn {\n\t\t\t\tendpoints: {\n\t\t\t\t\tdeltaStorageUrl: `${this.tinyliciousEndpoint}/deltas/tinylicious/${newDocumentId}`,\n\t\t\t\t\tordererUrl: this.tinyliciousEndpoint,\n\t\t\t\t\tstorageUrl: `${this.tinyliciousEndpoint}/repos/tinylicious`,\n\t\t\t\t},\n\t\t\t\t// id is a mandatory attribute, but it's ignored by the driver for new container requests.\n\t\t\t\tid: request.url,\n\t\t\t\t// tokens attribute is redundant as all tokens are generated via ITokenProvider\n\t\t\t\ttokens: {},\n\t\t\t\ttype: \"fluid\",\n\t\t\t\turl: `${this.fluidProtocolEndpoint}/tinylicious/${newDocumentId}`,\n\t\t\t};\n\t\t}\n\t\t// for an existing container we'll parse the request URL to determine the document ID.\n\t\tconst url = request.url.replace(`${this.tinyliciousEndpoint}/`, \"\");\n\t\tconst documentId = url.split(\"/\")[0];\n\t\tconst encodedDocId = encodeURIComponent(documentId);\n\t\tconst documentRelativePath = url.slice(documentId.length);\n\n\t\tconst documentUrl = `${this.fluidProtocolEndpoint}/tinylicious/${encodedDocId}${documentRelativePath}`;\n\t\tconst deltaStorageUrl = `${this.tinyliciousEndpoint}/deltas/tinylicious/${encodedDocId}`;\n\t\tconst storageUrl = `${this.tinyliciousEndpoint}/repos/tinylicious`;\n\n\t\tconst response: IFluidResolvedUrl = {\n\t\t\tendpoints: {\n\t\t\t\tdeltaStorageUrl,\n\t\t\t\tordererUrl: this.tinyliciousEndpoint,\n\t\t\t\tstorageUrl,\n\t\t\t},\n\t\t\tid: documentId,\n\t\t\ttokens: {},\n\t\t\ttype: \"fluid\",\n\t\t\turl: documentUrl,\n\t\t};\n\t\treturn response;\n\t}\n\n\tpublic async getAbsoluteUrl(\n\t\tresolvedUrl: IFluidResolvedUrl,\n\t\trelativeUrl: string,\n\t): Promise<string> {\n\t\tconst documentId = decodeURIComponent(\n\t\t\tresolvedUrl.url.replace(`${this.fluidProtocolEndpoint}/tinylicious/`, \"\"),\n\t\t);\n\t\t/*\n\t\t * The detached container flow will ultimately call getAbsoluteUrl() with the resolved.url produced by\n\t\t * resolve(). The container expects getAbsoluteUrl's return value to be a URL that can then be roundtripped\n\t\t * back through resolve() again, and get the same result again. So we'll return a \"URL\" with the same format\n\t\t * described above.\n\t\t */\n\t\treturn `${documentId}/${relativeUrl}`;\n\t}\n}\n\nexport const createTinyliciousCreateNewRequest = (documentId?: string): IRequest => ({\n\turl: documentId ?? \"\",\n\theaders: {\n\t\t[DriverHeader.createNew]: true,\n\t},\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/tinylicious-driver",
|
|
3
|
-
"version": "2.0.0-internal.3.0
|
|
3
|
+
"version": "2.0.0-internal.3.2.0",
|
|
4
4
|
"description": "Driver for tinylicious",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -13,43 +13,23 @@
|
|
|
13
13
|
"main": "dist/index.js",
|
|
14
14
|
"module": "lib/index.js",
|
|
15
15
|
"types": "dist/index.d.ts",
|
|
16
|
-
"scripts": {
|
|
17
|
-
"build": "concurrently npm:build:compile npm:lint",
|
|
18
|
-
"build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
|
|
19
|
-
"build:compile": "concurrently npm:build:commonjs npm:build:esnext",
|
|
20
|
-
"build:esnext": "tsc --project ./tsconfig.esnext.json",
|
|
21
|
-
"build:full": "npm run build",
|
|
22
|
-
"build:full:compile": "npm run build:compile",
|
|
23
|
-
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
24
|
-
"clean": "rimraf dist lib *.tsbuildinfo *.build.log",
|
|
25
|
-
"eslint": "eslint --format stylish src",
|
|
26
|
-
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
27
|
-
"format": "npm run prettier:fix",
|
|
28
|
-
"lint": "npm run eslint",
|
|
29
|
-
"lint:fix": "npm run eslint:fix",
|
|
30
|
-
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
|
|
31
|
-
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
|
|
32
|
-
"tsc": "tsc",
|
|
33
|
-
"typetests:gen": "flub generate typetests --generate --dir .",
|
|
34
|
-
"typetests:prepare": "flub generate typetests --prepare --dir . --pin"
|
|
35
|
-
},
|
|
36
16
|
"dependencies": {
|
|
37
|
-
"@fluidframework/core-interfaces": ">=2.0.0-internal.3.0
|
|
38
|
-
"@fluidframework/driver-definitions": ">=2.0.0-internal.3.0
|
|
39
|
-
"@fluidframework/driver-utils": ">=2.0.0-internal.3.0
|
|
17
|
+
"@fluidframework/core-interfaces": ">=2.0.0-internal.3.2.0 <2.0.0-internal.4.0.0",
|
|
18
|
+
"@fluidframework/driver-definitions": ">=2.0.0-internal.3.2.0 <2.0.0-internal.4.0.0",
|
|
19
|
+
"@fluidframework/driver-utils": ">=2.0.0-internal.3.2.0 <2.0.0-internal.4.0.0",
|
|
40
20
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
41
|
-
"@fluidframework/routerlicious-driver": ">=2.0.0-internal.3.0
|
|
21
|
+
"@fluidframework/routerlicious-driver": ">=2.0.0-internal.3.2.0 <2.0.0-internal.4.0.0",
|
|
42
22
|
"@fluidframework/server-services-client": "^0.1038.2000",
|
|
43
23
|
"jsrsasign": "^10.5.25",
|
|
44
24
|
"uuid": "^8.3.1"
|
|
45
25
|
},
|
|
46
26
|
"devDependencies": {
|
|
47
|
-
"@fluid-tools/build-cli": "^0.
|
|
27
|
+
"@fluid-tools/build-cli": "^0.10.0",
|
|
48
28
|
"@fluidframework/build-common": "^1.1.0",
|
|
49
|
-
"@fluidframework/build-tools": "^0.
|
|
29
|
+
"@fluidframework/build-tools": "^0.10.0",
|
|
50
30
|
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
51
31
|
"@fluidframework/test-tools": "^0.2.3074",
|
|
52
|
-
"@fluidframework/tinylicious-driver-previous": "npm:@fluidframework/tinylicious-driver@2.0.0-internal.3.
|
|
32
|
+
"@fluidframework/tinylicious-driver-previous": "npm:@fluidframework/tinylicious-driver@2.0.0-internal.3.1.0",
|
|
53
33
|
"@rushstack/eslint-config": "^2.5.1",
|
|
54
34
|
"@types/jsrsasign": "^8.0.8",
|
|
55
35
|
"@types/mocha": "^9.1.1",
|
|
@@ -63,9 +43,30 @@
|
|
|
63
43
|
"typescript": "~4.5.5"
|
|
64
44
|
},
|
|
65
45
|
"typeValidation": {
|
|
66
|
-
"version": "2.0.0-internal.3.0
|
|
67
|
-
"previousVersionStyle": "
|
|
68
|
-
"baselineRange": "2.0.0-internal.3.0.0",
|
|
46
|
+
"version": "2.0.0-internal.3.2.0",
|
|
47
|
+
"previousVersionStyle": "~previousMinor",
|
|
48
|
+
"baselineRange": ">=2.0.0-internal.3.1.0 <2.0.0-internal.3.2.0",
|
|
49
|
+
"baselineVersion": "2.0.0-internal.3.1.0",
|
|
69
50
|
"broken": {}
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "concurrently npm:build:compile npm:lint",
|
|
54
|
+
"build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
|
|
55
|
+
"build:compile": "concurrently npm:build:commonjs npm:build:esnext",
|
|
56
|
+
"build:esnext": "tsc --project ./tsconfig.esnext.json",
|
|
57
|
+
"build:full": "npm run build",
|
|
58
|
+
"build:full:compile": "npm run build:compile",
|
|
59
|
+
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
60
|
+
"clean": "rimraf dist lib *.tsbuildinfo *.build.log",
|
|
61
|
+
"eslint": "eslint --format stylish src",
|
|
62
|
+
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
63
|
+
"format": "npm run prettier:fix",
|
|
64
|
+
"lint": "npm run prettier && npm run eslint",
|
|
65
|
+
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
|
|
66
|
+
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
|
|
67
|
+
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
|
|
68
|
+
"tsc": "tsc",
|
|
69
|
+
"typetests:gen": "flub generate typetests --generate --dir .",
|
|
70
|
+
"typetests:prepare": "flub generate typetests --prepare --dir . --pin"
|
|
70
71
|
}
|
|
71
|
-
}
|
|
72
|
+
}
|
package/prettier.config.cjs
CHANGED
|
@@ -4,10 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ScopeType, ITokenClaims } from "@fluidframework/protocol-definitions";
|
|
7
|
-
import {
|
|
8
|
-
ITokenProvider,
|
|
9
|
-
ITokenResponse,
|
|
10
|
-
} from "@fluidframework/routerlicious-driver";
|
|
7
|
+
import { ITokenProvider, ITokenResponse } from "@fluidframework/routerlicious-driver";
|
|
11
8
|
import { getRandomName } from "@fluidframework/server-services-client";
|
|
12
9
|
import { KJUR as jsrsasign } from "jsrsasign";
|
|
13
10
|
import { v4 as uuid } from "uuid";
|
|
@@ -17,70 +14,60 @@ import { v4 as uuid } from "uuid";
|
|
|
17
14
|
* to get up and running.
|
|
18
15
|
*/
|
|
19
16
|
export class InsecureTinyliciousTokenProvider implements ITokenProvider {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
constructor(
|
|
18
|
+
/**
|
|
19
|
+
* Optional. Override of scopes. If a param is not provided, InsecureTinyliciousTokenProvider
|
|
20
|
+
* will use the default scopes which are document read, write and summarizer write.
|
|
21
|
+
*
|
|
22
|
+
* @param scopes - See {@link @fluidframework/protocol-definitions#ITokenClaims.scopes}
|
|
23
|
+
*
|
|
24
|
+
* @defaultValue - [ ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite ]
|
|
25
|
+
*/
|
|
26
|
+
private readonly scopes?: ScopeType[],
|
|
27
|
+
) {}
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
jwt: this.getSignedToken(tenantId, documentId),
|
|
39
|
-
};
|
|
40
|
-
}
|
|
29
|
+
public async fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse> {
|
|
30
|
+
return {
|
|
31
|
+
fromCache: true,
|
|
32
|
+
jwt: this.getSignedToken(tenantId, documentId),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
41
35
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
jwt: this.getSignedToken(tenantId, documentId),
|
|
49
|
-
};
|
|
50
|
-
}
|
|
36
|
+
public async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {
|
|
37
|
+
return {
|
|
38
|
+
fromCache: true,
|
|
39
|
+
jwt: this.getSignedToken(tenantId, documentId),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
51
42
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
43
|
+
private getSignedToken(
|
|
44
|
+
tenantId: string,
|
|
45
|
+
documentId: string | undefined,
|
|
46
|
+
lifetime: number = 60 * 60,
|
|
47
|
+
ver: string = "1.0",
|
|
48
|
+
): string {
|
|
49
|
+
// Current time in seconds
|
|
50
|
+
const now = Math.round(Date.now() / 1000);
|
|
51
|
+
const user = { id: uuid(), name: getRandomName() };
|
|
61
52
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
iat: now,
|
|
72
|
-
exp: now + lifetime,
|
|
73
|
-
ver,
|
|
74
|
-
};
|
|
53
|
+
const claims: ITokenClaims = {
|
|
54
|
+
documentId: documentId ?? "",
|
|
55
|
+
scopes: this.scopes ?? [ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite],
|
|
56
|
+
tenantId,
|
|
57
|
+
user,
|
|
58
|
+
iat: now,
|
|
59
|
+
exp: now + lifetime,
|
|
60
|
+
ver,
|
|
61
|
+
};
|
|
75
62
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
63
|
+
const utf8Key = { utf8: "12345" };
|
|
64
|
+
return jsrsasign.jws.JWS.sign(
|
|
65
|
+
// External API uses `null`
|
|
66
|
+
// eslint-disable-next-line unicorn/no-null
|
|
67
|
+
null,
|
|
68
|
+
JSON.stringify({ alg: "HS256", typ: "JWT" }),
|
|
69
|
+
claims,
|
|
70
|
+
utf8Key,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
86
73
|
}
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
import { IRequest } from "@fluidframework/core-interfaces";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
DriverHeader,
|
|
9
|
+
IFluidResolvedUrl,
|
|
10
|
+
IResolvedUrl,
|
|
11
|
+
IUrlResolver,
|
|
12
12
|
} from "@fluidframework/driver-definitions";
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -28,86 +28,80 @@ export const defaultTinyliciousEndpoint = "http://localhost";
|
|
|
28
28
|
* documentId/containerRelativePathing
|
|
29
29
|
*/
|
|
30
30
|
export class InsecureTinyliciousUrlResolver implements IUrlResolver {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.tinyliciousEndpoint = `${endpoint}:${port}`;
|
|
38
|
-
this.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\w+:|^)\/\//, "fluid://");
|
|
39
|
-
}
|
|
31
|
+
private readonly fluidProtocolEndpoint: string;
|
|
32
|
+
private readonly tinyliciousEndpoint: string;
|
|
33
|
+
public constructor(port = defaultTinyliciousPort, endpoint = defaultTinyliciousEndpoint) {
|
|
34
|
+
this.tinyliciousEndpoint = `${endpoint}:${port}`;
|
|
35
|
+
this.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\w+:|^)\/\//, "fluid://");
|
|
36
|
+
}
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
38
|
+
public async resolve(request: IRequest): Promise<IResolvedUrl> {
|
|
39
|
+
// determine whether the request is for creating of a new container.
|
|
40
|
+
// such request has the `createNew` header set to true and doesn't have a container ID.
|
|
41
|
+
if (request.headers && request.headers[DriverHeader.createNew] === true) {
|
|
42
|
+
// honor the document ID passed by the application via the create request
|
|
43
|
+
// otherwise use the reserved keyword to let the driver generate the ID.
|
|
44
|
+
// TODO: deprecate this capability for tinylicious as the r11s driver will stop using the document ID
|
|
45
|
+
// in create requests.
|
|
46
|
+
const newDocumentId = request.url ?? "new";
|
|
47
|
+
return {
|
|
48
|
+
endpoints: {
|
|
49
|
+
deltaStorageUrl: `${this.tinyliciousEndpoint}/deltas/tinylicious/${newDocumentId}`,
|
|
50
|
+
ordererUrl: this.tinyliciousEndpoint,
|
|
51
|
+
storageUrl: `${this.tinyliciousEndpoint}/repos/tinylicious`,
|
|
52
|
+
},
|
|
53
|
+
// id is a mandatory attribute, but it's ignored by the driver for new container requests.
|
|
54
|
+
id: request.url,
|
|
55
|
+
// tokens attribute is redundant as all tokens are generated via ITokenProvider
|
|
56
|
+
tokens: {},
|
|
57
|
+
type: "fluid",
|
|
58
|
+
url: `${this.fluidProtocolEndpoint}/tinylicious/${newDocumentId}`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// for an existing container we'll parse the request URL to determine the document ID.
|
|
62
|
+
const url = request.url.replace(`${this.tinyliciousEndpoint}/`, "");
|
|
63
|
+
const documentId = url.split("/")[0];
|
|
64
|
+
const encodedDocId = encodeURIComponent(documentId);
|
|
65
|
+
const documentRelativePath = url.slice(documentId.length);
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
`${this.tinyliciousEndpoint}/deltas/tinylicious/${encodedDocId}`;
|
|
74
|
-
const storageUrl =
|
|
75
|
-
`${this.tinyliciousEndpoint}/repos/tinylicious`;
|
|
67
|
+
const documentUrl = `${this.fluidProtocolEndpoint}/tinylicious/${encodedDocId}${documentRelativePath}`;
|
|
68
|
+
const deltaStorageUrl = `${this.tinyliciousEndpoint}/deltas/tinylicious/${encodedDocId}`;
|
|
69
|
+
const storageUrl = `${this.tinyliciousEndpoint}/repos/tinylicious`;
|
|
76
70
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
71
|
+
const response: IFluidResolvedUrl = {
|
|
72
|
+
endpoints: {
|
|
73
|
+
deltaStorageUrl,
|
|
74
|
+
ordererUrl: this.tinyliciousEndpoint,
|
|
75
|
+
storageUrl,
|
|
76
|
+
},
|
|
77
|
+
id: documentId,
|
|
78
|
+
tokens: {},
|
|
79
|
+
type: "fluid",
|
|
80
|
+
url: documentUrl,
|
|
81
|
+
};
|
|
82
|
+
return response;
|
|
83
|
+
}
|
|
90
84
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
85
|
+
public async getAbsoluteUrl(
|
|
86
|
+
resolvedUrl: IFluidResolvedUrl,
|
|
87
|
+
relativeUrl: string,
|
|
88
|
+
): Promise<string> {
|
|
89
|
+
const documentId = decodeURIComponent(
|
|
90
|
+
resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}/tinylicious/`, ""),
|
|
91
|
+
);
|
|
92
|
+
/*
|
|
93
|
+
* The detached container flow will ultimately call getAbsoluteUrl() with the resolved.url produced by
|
|
94
|
+
* resolve(). The container expects getAbsoluteUrl's return value to be a URL that can then be roundtripped
|
|
95
|
+
* back through resolve() again, and get the same result again. So we'll return a "URL" with the same format
|
|
96
|
+
* described above.
|
|
97
|
+
*/
|
|
98
|
+
return `${documentId}/${relativeUrl}`;
|
|
99
|
+
}
|
|
103
100
|
}
|
|
104
101
|
|
|
105
|
-
export const createTinyliciousCreateNewRequest =
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
},
|
|
112
|
-
}
|
|
113
|
-
);
|
|
102
|
+
export const createTinyliciousCreateNewRequest = (documentId?: string): IRequest => ({
|
|
103
|
+
url: documentId ?? "",
|
|
104
|
+
headers: {
|
|
105
|
+
[DriverHeader.createNew]: true,
|
|
106
|
+
},
|
|
107
|
+
});
|
package/tsconfig.esnext.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./lib",
|
|
5
|
+
"module": "esnext",
|
|
6
|
+
},
|
|
7
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"include": [
|
|
12
|
-
"src/**/*"
|
|
13
|
-
]
|
|
14
|
-
}
|
|
2
|
+
"extends": "@fluidframework/build-common/ts-common-config.json",
|
|
3
|
+
"exclude": ["src/test/**/*"],
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"composite": true,
|
|
8
|
+
},
|
|
9
|
+
"include": ["src/**/*"],
|
|
10
|
+
}
|