Skip to content

Commit

Permalink
feat(common): throw instead of truncating namespace (#2917)
Browse files Browse the repository at this point in the history
  • Loading branch information
holic authored Jul 2, 2024
1 parent 499b1f8 commit 8d0453e
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 40 deletions.
5 changes: 5 additions & 0 deletions .changeset/tender-badgers-ring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@latticexyz/common": patch
---

`resourceToHex` will now throw if provided namespace is >14 characters. Since namespaces are used to determine access control, it's not safe to automatically truncate to fit into `bytes14` as that may change the indended namespace for resource access.
25 changes: 10 additions & 15 deletions packages/common/src/resourceToHex.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,16 @@ describe("resourceToHex", () => {
`);
});

it("truncates namespaces >14 bytes", () => {
const hex = resourceToHex({
type: "table",
namespace: "AVeryLongNamespace",
name: "name",
});
expect(hex).toMatchInlineSnapshot('"0x746241566572794c6f6e674e616d65736e616d65000000000000000000000000"');
expect(hexToResource(hex)).toMatchInlineSnapshot(`
{
"name": "name",
"namespace": "AVeryLongNames",
"resourceId": "0x746241566572794c6f6e674e616d65736e616d65000000000000000000000000",
"type": "table",
}
`);
it("throws for namespaces >14 bytes", () => {
expect(() =>
resourceToHex({
type: "table",
namespace: "AVeryLongNamespace",
name: "name",
}),
).toThrowErrorMatchingInlineSnapshot(
'"Namespaces must fit into `bytes14`, but \\"AVeryLongNamespace\\" is too long."',
);
});

it("truncates names >16 bytes", () => {
Expand Down
6 changes: 5 additions & 1 deletion packages/common/src/resourceToHex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ export const resourceTypeIds = {

export function resourceToHex(resource: Omit<Resource, "resourceId">): Hex {
const typeId = resourceTypeIds[resource.type];
// Because namespaces are tied to access control, it's not safe to automatically truncate. Instead, we'll throw an error.
if (resource.namespace.length > 14) {
throw new Error(`Namespaces must fit into \`bytes14\`, but "${resource.namespace}" is too long.`);
}
return concatHex([
stringToHex(typeId, { size: 2 }),
stringToHex(resource.namespace.slice(0, 14), { size: 14 }),
stringToHex(resource.namespace, { size: 14 }),
stringToHex(resource.name.slice(0, 16), { size: 16 }),
]);
}
4 changes: 2 additions & 2 deletions packages/store/ts/config/v2/store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ describe("defineStore", () => {
it("should throw if name is overridden in the store context", () => {
attest(() =>
defineStore({
namespace: "CustomNamespace",
namespace: "CustomNS",
tables: {
Example: {
schema: { id: "address" },
Expand All @@ -500,7 +500,7 @@ describe("defineStore", () => {
it("should throw if namespace is overridden in the store context", () => {
attest(() =>
defineStore({
namespace: "CustomNamespace",
namespace: "CustomNS",
tables: {
Example: {
schema: { id: "address" },
Expand Down
24 changes: 12 additions & 12 deletions packages/world/ts/config/v2/world.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe("defineWorld", () => {
const config = defineWorld({
// @ts-expect-error TODO: remove once namespaces support ships
namespaces: {
ExampleNamespace: {
ExampleNS: {
tables: {
ExampleTable: {
schema: {
Expand All @@ -42,8 +42,8 @@ describe("defineWorld", () => {
...CONFIG_DEFAULTS,
codegen: CODEGEN_DEFAULTS,
tables: {
ExampleNamespace__ExampleTable: {
tableId: resourceToHex({ type: "table", namespace: "ExampleNamespace", name: "ExampleTable" }),
ExampleNS__ExampleTable: {
tableId: resourceToHex({ type: "table", namespace: "ExampleNS", name: "ExampleTable" }),
schema: {
id: {
type: "address",
Expand All @@ -60,7 +60,7 @@ describe("defineWorld", () => {
},
key: ["id"],
name: "ExampleTable",
namespace: "ExampleNamespace",
namespace: "ExampleNS",
codegen: { ...TABLE_CODEGEN_DEFAULTS, dataStruct: true as boolean },
type: "table",
deploy: TABLE_DEPLOY_DEFAULTS,
Expand All @@ -79,7 +79,7 @@ describe("defineWorld", () => {
const config = defineWorld({
// @ts-expect-error TODO: remove once namespaces support ships
namespaces: {
ExampleNamespace: {
ExampleNS: {
tables: {
ExampleTable: {
schema: {
Expand All @@ -105,8 +105,8 @@ describe("defineWorld", () => {
...CONFIG_DEFAULTS,
codegen: CODEGEN_DEFAULTS,
tables: {
ExampleNamespace__ExampleTable: {
tableId: resourceToHex({ type: "table", namespace: "ExampleNamespace", name: "ExampleTable" }),
ExampleNS__ExampleTable: {
tableId: resourceToHex({ type: "table", namespace: "ExampleNS", name: "ExampleTable" }),
schema: {
id: {
type: "address",
Expand All @@ -123,7 +123,7 @@ describe("defineWorld", () => {
},
key: ["id"],
name: "ExampleTable",
namespace: "ExampleNamespace",
namespace: "ExampleNS",
codegen: { ...TABLE_CODEGEN_DEFAULTS, dataStruct: true as boolean },
type: "table",
deploy: TABLE_DEPLOY_DEFAULTS,
Expand Down Expand Up @@ -152,7 +152,7 @@ describe("defineWorld", () => {
const config = defineWorld({
// @ts-expect-error TODO: remove once namespaces support ships
namespaces: {
ExampleNamespace: {
ExampleNS: {
tables: {
ExampleTable: {
schema: {
Expand Down Expand Up @@ -663,7 +663,7 @@ describe("defineWorld", () => {

it("should use the custom name and namespace as table index", () => {
const config = defineWorld({
namespace: "CustomNamespace",
namespace: "CustomNS",
tables: {
Example: {
schema: { id: "address" },
Expand All @@ -672,13 +672,13 @@ describe("defineWorld", () => {
},
});

attest<"CustomNamespace__Example", keyof typeof config.tables>();
attest<"CustomNS__Example", keyof typeof config.tables>();
});

it("should throw if namespace is overridden in top level tables", () => {
attest(() =>
defineWorld({
namespace: "CustomNamespace",
namespace: "CustomNS",
tables: {
Example: {
schema: { id: "address" },
Expand Down
20 changes: 10 additions & 10 deletions packages/world/ts/config/v2/worldWithShorthands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe("defineWorldWithShorthands", () => {
it("should resolve namespaced shorthand table config with user types and enums", () => {
const config = defineWorldWithShorthands({
namespaces: {
ExampleNamespace: {
ExampleNS: {
tables: {
ExampleTable: "Static",
},
Expand All @@ -36,8 +36,8 @@ describe("defineWorldWithShorthands", () => {
...CONFIG_DEFAULTS,
codegen: CODEGEN_DEFAULTS,
tables: {
ExampleNamespace__ExampleTable: {
tableId: resourceToHex({ type: "table", namespace: "ExampleNamespace", name: "ExampleTable" }),
ExampleNS__ExampleTable: {
tableId: resourceToHex({ type: "table", namespace: "ExampleNS", name: "ExampleTable" }),
schema: {
id: {
type: "bytes32",
Expand All @@ -50,7 +50,7 @@ describe("defineWorldWithShorthands", () => {
},
key: ["id"],
name: "ExampleTable",
namespace: "ExampleNamespace",
namespace: "ExampleNS",
codegen: { ...TABLE_CODEGEN_DEFAULTS, dataStruct: false as boolean },
type: "table",
deploy: TABLE_DEPLOY_DEFAULTS,
Expand Down Expand Up @@ -78,7 +78,7 @@ describe("defineWorldWithShorthands", () => {
it("should resolve namespaced shorthand schema table config with user types and enums", () => {
const config = defineWorldWithShorthands({
namespaces: {
ExampleNamespace: {
ExampleNS: {
tables: {
ExampleTable: {
id: "Static",
Expand All @@ -101,8 +101,8 @@ describe("defineWorldWithShorthands", () => {
...CONFIG_DEFAULTS,
codegen: CODEGEN_DEFAULTS,
tables: {
ExampleNamespace__ExampleTable: {
tableId: resourceToHex({ type: "table", namespace: "ExampleNamespace", name: "ExampleTable" }),
ExampleNS__ExampleTable: {
tableId: resourceToHex({ type: "table", namespace: "ExampleNS", name: "ExampleTable" }),
schema: {
id: {
type: "address",
Expand All @@ -119,7 +119,7 @@ describe("defineWorldWithShorthands", () => {
},
key: ["id"],
name: "ExampleTable",
namespace: "ExampleNamespace",
namespace: "ExampleNS",
codegen: { ...TABLE_CODEGEN_DEFAULTS, dataStruct: true as boolean },
type: "table",
deploy: TABLE_DEPLOY_DEFAULTS,
Expand Down Expand Up @@ -358,7 +358,7 @@ describe("defineWorldWithShorthands", () => {
attest(() =>
defineWorldWithShorthands({
namespaces: {
ExampleNamespace: {
ExampleNS: {
tables: {
// @ts-expect-error Type '"number"' is not assignable to type 'AbiType'.
ExampleTable: "number",
Expand All @@ -373,7 +373,7 @@ describe("defineWorldWithShorthands", () => {
attest(() =>
defineWorldWithShorthands({
namespaces: {
ExampleNamespace: {
ExampleNS: {
// @ts-expect-error Type 'true' is not assignable to type '"`invalidProperty` is not a valid namespace config option.
invalidProperty: true,
},
Expand Down

0 comments on commit 8d0453e

Please sign in to comment.