kstate fixes and code coverage

This commit is contained in:
Cadence Ember
2026-01-09 02:07:08 +13:00
parent 8661aa7cfa
commit 0d15865bcd
3 changed files with 192 additions and 11 deletions

View File

@@ -14,6 +14,8 @@ const {discord} = require("../../passthrough")
const ones = "₀₁₂₃₄₅₆₇₈₉"
const tens = "0123456789"
/* c8 ignore start */
module.exports = async function(db) {
/** @type {{name: string, channel_id: string, thread_parent: string | null}[]} */
const rows = db.prepare("SELECT name, channel_id, thread_parent FROM channel_room WHERE guild_id IS NULL").all()

View File

@@ -53,11 +53,11 @@ async function kstateToState(kstate) {
kstateStripConditionals(kstate)
await kstateUploadMxc(kstate)
for (const [k, content] of Object.entries(kstate)) {
if (k === "m.room.create/") continue
const slashIndex = k.indexOf("/")
assert(slashIndex > 0)
const type = k.slice(0, slashIndex)
const state_key = k.slice(slashIndex + 1)
if (type === "m.room.create") continue
events.push({type, state_key, content})
}
return events
@@ -94,15 +94,16 @@ function diffKState(actual, target) {
if (key === "m.room.power_levels/") {
// Special handling for power levels, we want to deep merge the actual and target into the final state.
if (!(key in actual)) throw new Error(`want to apply a power levels diff, but original power level data is missing\nstarted with: ${JSON.stringify(actual)}\nwant to apply: ${JSON.stringify(target)}`)
const mixedTarget = mixin({}, actual[key], target[key])
// if the diff includes users, it needs to be cleaned wrt room version 12
const cleanedTarget = mixin({}, target[key])
if (target[key].users && Object.keys(target[key].users).length > 0) {
assert("m.room.create/" in actual, `want to apply a power levels diff, but original m.room.create/ is missing\nstarted with: ${JSON.stringify(actual)}\nwant to apply: ${JSON.stringify(target)}`)
assert("m.room.create/outer" in actual, `want to apply a power levels diff, but original m.room.create/outer is missing\nstarted with: ${JSON.stringify(actual)}\nwant to apply: ${JSON.stringify(target)}`)
utils.removeCreatorsFromPowerLevels(actual["m.room.create/outer"], cleanedTarget)
}
const mixedTarget = mixin({}, actual[key], cleanedTarget)
if (!isDeepStrictEqual(actual[key], mixedTarget)) {
// they differ. use the newly prepared object as the diff.
// if the diff includes users, it needs to be cleaned wrt room version 12
if (target[key].users && Object.keys(target[key].users).length > 0) {
if (!("m.room.create/" in actual)) throw new Error(`want to apply a power levels diff, but original m.room.create/ is missing\nstarted with: ${JSON.stringify(actual)}\nwant to apply: ${JSON.stringify(target)}`)
if (!("m.room.create/outer" in actual)) throw new Error(`want to apply a power levels diff, but original m.room.create/outer is missing\nstarted with: ${JSON.stringify(actual)}\nwant to apply: ${JSON.stringify(target)}`)
utils.removeCreatorsFromPowerLevels(actual["m.room.create/outer"], mixedTarget)
}
diff[key] = mixedTarget
}

View File

@@ -1,5 +1,5 @@
const assert = require("assert")
const {kstateToState, stateToKState, diffKState, kstateStripConditionals, kstateUploadMxc} = require("./kstate")
const {kstateToState, stateToKState, diffKState, kstateStripConditionals, kstateUploadMxc, kstateToCreationContent} = require("./kstate")
const {test} = require("supertape")
test("kstate strip: strips false conditions", t => {
@@ -68,6 +68,8 @@ test("kstateUploadMxc and strip: work together", async t => {
test("kstate2state: general", async t => {
t.deepEqual(await kstateToState({
"m.room.create/": {bogus: true},
"m.room.create/outer": {bogus: true},
"m.room.name/": {name: "test name"},
"m.room.member/@cadence:cadence.moe": {membership: "join"},
"uk.half-shot.bridge/org.matrix.appservice-irc://irc/epicord.net/#general": {creator: "@cadence:cadence.moe"}
@@ -98,6 +100,14 @@ test("kstate2state: general", async t => {
test("state2kstate: general", t => {
t.deepEqual(stateToKState([
{
type: "m.room.create",
state_key: "",
sender: "@example:matrix.org",
content: {
room_version: "12"
}
},
{
type: "m.room.name",
state_key: "",
@@ -122,7 +132,9 @@ test("state2kstate: general", t => {
]), {
"m.room.name/": {name: "test name"},
"m.room.member/@cadence:cadence.moe": {membership: "join"},
"uk.half-shot.bridge/org.matrix.appservice-irc://irc/epicord.net/#general": {creator: "@cadence:cadence.moe"}
"uk.half-shot.bridge/org.matrix.appservice-irc://irc/epicord.net/#general": {creator: "@cadence:cadence.moe"},
"m.room.create/": {room_version: "12"},
"m.room.create/outer": {type: "m.room.create", state_key: "", sender: "@example:matrix.org", content: {room_version: "12"}}
})
})
@@ -157,6 +169,17 @@ test("diffKState: detects new properties", t => {
test("diffKState: power levels are mixed together", t => {
const original = {
"m.room.create/outer": {
type: "m.room.create",
state_key: "",
sender: "@example:matrix.org",
content: {
room_version: "11"
}
},
"m.room.create/": {
room_version: "11"
},
"m.room.power_levels/": {
"ban": 50,
"events": {
@@ -181,6 +204,9 @@ test("diffKState: power levels are mixed together", t => {
"m.room.power_levels/": {
"events": {
"m.room.avatar": 0
},
users: {
"@example:matrix.org": 100
}
}
})
@@ -201,7 +227,8 @@ test("diffKState: power levels are mixed together", t => {
"redact": 50,
"state_default": 50,
"users": {
"@example:localhost": 100
"@example:localhost": 100,
"@example:matrix.org": 100
},
"users_default": 0
}
@@ -270,3 +297,154 @@ test("diffKState: topic changes if the topic key has changed", t => {
}
})
})
test("diffKState: room v12 creators cannot be introduced into power levels", t => {
const original = {
"m.room.create/outer": {
type: "m.room.create",
state_key: "",
sender: "@example1:matrix.org",
content: {
additional_creators: ["@example2:matrix.org"],
room_version: "12"
}
},
"m.room.create/": {
room_version: "12"
},
"m.room.power_levels/": {
"ban": 50,
"events": {
"m.room.name": 100,
"m.room.power_levels": 100
},
"events_default": 0,
"invite": 50,
"kick": 50,
"notifications": {
"room": 20
},
"redact": 50,
"state_default": 50,
"users": {
"@example:localhost": 100
},
"users_default": 0
}
}
const result = diffKState(original, {
"m.room.create/": {
bogus: true
},
"m.room.power_levels/": {
events: {
"m.room.avatar": 0
},
users: {
"@example1:matrix.org": 100,
"@example2:matrix.org": 100,
"@example3:matrix.org": 100
}
}
})
t.deepEqual(result, {
"m.room.power_levels/": {
"ban": 50,
"events": {
"m.room.name": 100,
"m.room.power_levels": 100,
"m.room.avatar": 0
},
"events_default": 0,
"invite": 50,
"kick": 50,
"notifications": {
"room": 20
},
"redact": 50,
"state_default": 50,
"users": {
"@example:localhost": 100,
"@example3:matrix.org": 100
},
"users_default": 0
}
})
t.notDeepEqual(original, result)
})
test("diffKState: room v12 creators cannot be introduced into power levels - no diff if no changes", t => {
const original = {
"m.room.create/outer": {
type: "m.room.create",
state_key: "",
sender: "@example1:matrix.org",
content: {
additional_creators: ["@example2:matrix.org"],
room_version: "12"
}
},
"m.room.create/": {
additional_creators: ["@example2:matrix.org"],
room_version: "12"
},
"m.room.power_levels/": {
"ban": 50,
"events": {
"m.room.name": 100,
"m.room.power_levels": 100
},
"events_default": 0,
"invite": 50,
"kick": 50,
"notifications": {
"room": 20
},
"redact": 50,
"state_default": 50,
"users": {
"@example:localhost": 100
},
"users_default": 0
}
}
const result = diffKState(original, {
"m.room.power_levels/": {
users: {
"@example1:matrix.org": 100,
"@example2:matrix.org": 100
}
}
})
t.deepEqual(result, {})
t.notDeepEqual(original, result)
})
test("kstateToCreationContent: works", t => {
const original = {
"m.room.create/outer": {
type: "m.room.create",
state_key: "",
sender: "@example1:matrix.org",
content: {
additional_creators: ["@example2:matrix.org"],
room_version: "12",
type: "m.space"
}
},
"m.room.create/": {
additional_creators: ["@example2:matrix.org"],
room_version: "12",
type: "m.space"
}
}
t.deepEqual(kstateToCreationContent(original), {
additional_creators: ["@example2:matrix.org"],
room_version: "12",
type: "m.space"
})
})
test("kstateToCreationContent: works if empty", t => {
t.deepEqual(kstateToCreationContent({}), {})
})