feat: implement comprehensive room validation and admin-only command access

- Add RoomExists and GetRoomMapping methods to Bridge interface
- Implement XMPP room existence checking using disco#info queries (XEP-0030)
- Add room validation in BridgeManager to prevent duplicate mappings and invalid rooms
- Enhance XMPP client with CheckRoomExists method and comprehensive logging
- Implement admin-only access control for all bridge commands
- Add user-friendly error messages with actionable troubleshooting steps
- Update doctor command with room existence testing and pre-join validation
- Add SimpleLogger implementation for standalone command usage

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Felipe M 2025-08-04 11:29:35 +02:00
parent 1f45197aa8
commit a95ca8fb76
No known key found for this signature in database
GPG key ID: 52E5D65FCF99808A
8 changed files with 454 additions and 17 deletions

View file

@ -73,6 +73,7 @@ func (b *xmppBridge) createXMPPClient(cfg *config.Configuration) *xmppClient.Cli
cfg.GetXMPPResource(),
"", // remoteID not needed for bridge user
tlsConfig,
b.logger,
)
}
@ -471,3 +472,48 @@ func (b *xmppBridge) DeleteChannelMapping(channelID string) error {
b.logger.LogInfo("Deleted channel room mapping", "channel_id", channelID, "room_jid", roomJID)
return nil
}
// RoomExists checks if an XMPP room exists on the remote service
func (b *xmppBridge) RoomExists(roomID string) (bool, error) {
if !b.connected.Load() {
return false, fmt.Errorf("not connected to XMPP server")
}
if b.xmppClient == nil {
return false, fmt.Errorf("XMPP client not initialized")
}
b.logger.LogDebug("Checking if XMPP room exists", "room_jid", roomID)
// Use the XMPP client to check room existence
exists, err := b.xmppClient.CheckRoomExists(roomID)
if err != nil {
b.logger.LogError("Failed to check room existence", "room_jid", roomID, "error", err)
return false, fmt.Errorf("failed to check room existence: %w", err)
}
b.logger.LogDebug("Room existence check completed", "room_jid", roomID, "exists", exists)
return exists, nil
}
// GetRoomMapping retrieves the Mattermost channel ID for a given XMPP room JID (reverse lookup)
func (b *xmppBridge) GetRoomMapping(roomID string) (string, error) {
if b.kvstore == nil {
return "", fmt.Errorf("KV store not initialized")
}
b.logger.LogDebug("Getting channel mapping for XMPP room", "room_jid", roomID)
// Look up the channel ID using the room JID as the key
channelIDBytes, err := b.kvstore.Get(kvstore.BuildChannelMapKey("xmpp", roomID))
if err != nil {
// No mapping found is not an error, just return empty string
b.logger.LogDebug("No channel mapping found for room", "room_jid", roomID)
return "", nil
}
channelID := string(channelIDBytes)
b.logger.LogDebug("Found channel mapping for room", "room_jid", roomID, "channel_id", channelID)
return channelID, nil
}