KI-AGENT: Matrix-Räume in FEDEO provisionieren
This commit is contained in:
@@ -122,6 +122,20 @@ export function matrixService(server: FastifyInstance) {
|
||||
const tenantSpaceAlias = (tenant: { id: number, short?: string | null, name?: string | null }) =>
|
||||
`#${tenantSpaceAliasLocalpart(tenant)}:${serverName()}`
|
||||
|
||||
const tenantRoomAliasLocalpart = (
|
||||
tenant: { id: number, short?: string | null, name?: string | null },
|
||||
roomKey: string
|
||||
) => {
|
||||
const tenantSeed = normalizeMatrixAliasSeed(tenant.short || tenant.name || `tenant_${tenant.id}`)
|
||||
const roomSeed = normalizeMatrixAliasSeed(roomKey)
|
||||
return `fedeo_${tenantSeed}_${tenant.id}_${roomSeed}`
|
||||
}
|
||||
|
||||
const tenantRoomAlias = (
|
||||
tenant: { id: number, short?: string | null, name?: string | null },
|
||||
roomKey: string
|
||||
) => `#${tenantRoomAliasLocalpart(tenant, roomKey)}:${serverName()}`
|
||||
|
||||
const buildSharedSecretMac = (
|
||||
nonce: string,
|
||||
username: string,
|
||||
@@ -459,6 +473,140 @@ export function matrixService(server: FastifyInstance) {
|
||||
}
|
||||
}
|
||||
|
||||
const getTenantRoomStatus = async (
|
||||
tenantId: number | null,
|
||||
roomKey: string,
|
||||
roomName: string
|
||||
) => {
|
||||
const tenant = await getCurrentTenant(tenantId)
|
||||
const alias = tenantRoomAlias(tenant, roomKey)
|
||||
|
||||
try {
|
||||
const directoryEntry = await requestJson<{
|
||||
room_id: string
|
||||
servers: string[]
|
||||
}>(`${homeserverUrl()}/_matrix/client/v3/directory/room/${encodeURIComponent(alias)}`)
|
||||
|
||||
return {
|
||||
tenantId: tenant.id,
|
||||
tenantName: tenant.name,
|
||||
key: roomKey,
|
||||
name: roomName,
|
||||
alias,
|
||||
exists: true,
|
||||
roomId: directoryEntry.room_id,
|
||||
servers: directoryEntry.servers,
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (err.statusCode === 404 || err.errcode === "M_NOT_FOUND") {
|
||||
return {
|
||||
tenantId: tenant.id,
|
||||
tenantName: tenant.name,
|
||||
key: roomKey,
|
||||
name: roomName,
|
||||
alias,
|
||||
exists: false,
|
||||
roomId: null,
|
||||
servers: [],
|
||||
}
|
||||
}
|
||||
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
const provisionTenantRoom = async (
|
||||
userId: string,
|
||||
tenantId: number | null,
|
||||
options: {
|
||||
key?: string
|
||||
name?: string
|
||||
topic?: string
|
||||
} = {}
|
||||
) => {
|
||||
const tenant = await getCurrentTenant(tenantId)
|
||||
const key = normalizeMatrixAliasSeed(options.key || options.name || "allgemein")
|
||||
const name = (options.name || "Allgemeiner Chat").trim() || "Allgemeiner Chat"
|
||||
const topic = (options.topic || `Allgemeiner Kommunikationsraum für ${tenant.name}`).trim()
|
||||
const existing = await getTenantRoomStatus(tenant.id, key, name)
|
||||
const userAccount = await provisionCurrentUser(userId, tenant.id)
|
||||
const tenantSpace = await provisionCurrentTenantSpace(userId, tenant.id)
|
||||
|
||||
if (existing.exists) {
|
||||
return {
|
||||
...existing,
|
||||
created: false,
|
||||
alreadyExisted: true,
|
||||
parentSpaceRoomId: tenantSpace.roomId,
|
||||
invitedUserId: userAccount.matrixUserId,
|
||||
}
|
||||
}
|
||||
|
||||
const serviceLogin = await ensureServiceAccessToken()
|
||||
const createdRoom = await requestMatrixJson<{ room_id: string }>(
|
||||
"/_matrix/client/v3/createRoom",
|
||||
serviceLogin.access_token,
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
name,
|
||||
topic,
|
||||
preset: "private_chat",
|
||||
visibility: "private",
|
||||
room_alias_name: tenantRoomAliasLocalpart(tenant, key),
|
||||
invite: [userAccount.matrixUserId],
|
||||
initial_state: [
|
||||
{
|
||||
type: "m.room.history_visibility",
|
||||
state_key: "",
|
||||
content: {
|
||||
history_visibility: "invited",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "m.space.parent",
|
||||
state_key: tenantSpace.roomId,
|
||||
content: {
|
||||
via: [serverName()],
|
||||
canonical: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
await requestMatrixJson(
|
||||
`/_matrix/client/v3/rooms/${encodeURIComponent(tenantSpace.roomId)}/state/m.space.child/${encodeURIComponent(createdRoom.room_id)}`,
|
||||
serviceLogin.access_token,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
via: [serverName()],
|
||||
suggested: true,
|
||||
order: "10",
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
tenantId: tenant.id,
|
||||
tenantName: tenant.name,
|
||||
key,
|
||||
name,
|
||||
alias: tenantRoomAlias(tenant, key),
|
||||
exists: true,
|
||||
created: true,
|
||||
alreadyExisted: false,
|
||||
roomId: createdRoom.room_id,
|
||||
parentSpaceRoomId: tenantSpace.roomId,
|
||||
invitedUserId: userAccount.matrixUserId,
|
||||
serviceUserId: serviceLogin.user_id,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
getStatus,
|
||||
matrixUserIdForUser,
|
||||
@@ -466,5 +614,7 @@ export function matrixService(server: FastifyInstance) {
|
||||
provisionCurrentUser,
|
||||
getTenantSpaceStatus,
|
||||
provisionCurrentTenantSpace,
|
||||
getTenantRoomStatus,
|
||||
provisionTenantRoom,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,4 +49,29 @@ export default async function communicationRoutes(server: FastifyInstance) {
|
||||
.send({ error: err.message || "Matrix tenant space provisioning failed" })
|
||||
}
|
||||
})
|
||||
|
||||
server.get("/communication/matrix/rooms/general", async (req, reply) => {
|
||||
try {
|
||||
return await matrix.getTenantRoomStatus(req.user.tenant_id, "allgemein", "Allgemeiner Chat")
|
||||
} catch (err: any) {
|
||||
req.log.error(err)
|
||||
return reply
|
||||
.code(err.statusCode || 500)
|
||||
.send({ error: err.message || "Matrix room status failed" })
|
||||
}
|
||||
})
|
||||
|
||||
server.post("/communication/matrix/rooms/general/provision", async (req, reply) => {
|
||||
try {
|
||||
return await matrix.provisionTenantRoom(req.user.user_id, req.user.tenant_id, {
|
||||
key: "allgemein",
|
||||
name: "Allgemeiner Chat",
|
||||
})
|
||||
} catch (err: any) {
|
||||
req.log.error(err)
|
||||
return reply
|
||||
.code(err.statusCode || 500)
|
||||
.send({ error: err.message || "Matrix room provisioning failed" })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user