mattermost-plugin-bridge-xmpp/server/config/config.go
Felipe Martin b80e8ebd8f
feat: refactor bridge user detection and fix linting issues
- Extract bridge user detection logic into separate isBridgeUserMessage() function
- Fix gocritic ifElseChain issues by converting if-else to switch statements
- Fix gofmt formatting issues in client.go
- Fix revive naming issues by renaming XMPPUser to User and XMPPUserManager to UserManager
- Improve code organization and maintainability

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-12 12:01:42 +02:00

137 lines
4.6 KiB
Go

package config
import (
"fmt"
"strings"
)
// Configuration captures the plugin's external configuration as exposed in the Mattermost server
// configuration, as well as values computed from the configuration. Any public fields will be
// deserialized from the Mattermost server configuration in OnConfigurationChange.
//
// As plugins are inherently concurrent (hooks being called asynchronously), and the plugin
// configuration can change at any time, access to the configuration must be synchronized. The
// strategy used in this plugin is to guard a pointer to the configuration, and clone the entire
// struct whenever it changes. You may replace this with whatever strategy you choose.
//
// If you add non-reference types to your configuration struct, be sure to rewrite Clone as a deep
// copy appropriate for your types.
type Configuration struct {
XMPPServerURL string `json:"XMPPServerURL"`
XMPPUsername string `json:"XMPPUsername"`
XMPPPassword string `json:"XMPPPassword"`
EnableSync bool `json:"EnableSync"`
XMPPResource string `json:"XMPPResource"`
XMPPInsecureSkipVerify bool `json:"XMPPInsecureSkipVerify"`
// Ghost User Settings (XEP-0077 In-Band Registration)
EnableXMPPGhostUsers bool `json:"EnableXMPPGhostUsers"`
XMPPGhostUserPrefix string `json:"XMPPGhostUserPrefix"`
XMPPGhostUserDomain string `json:"XMPPGhostUserDomain"`
XMPPGhostUserCleanup bool `json:"XMPPGhostUserCleanup"`
}
// Equals compares two configuration structs
func (c *Configuration) Equals(other *Configuration) bool {
if c == nil && other == nil {
return true
}
if c == nil || other == nil {
return false
}
return c.XMPPServerURL == other.XMPPServerURL &&
c.XMPPUsername == other.XMPPUsername &&
c.XMPPPassword == other.XMPPPassword &&
c.EnableSync == other.EnableSync &&
c.XMPPResource == other.XMPPResource &&
c.XMPPInsecureSkipVerify == other.XMPPInsecureSkipVerify &&
c.EnableXMPPGhostUsers == other.EnableXMPPGhostUsers &&
c.XMPPGhostUserPrefix == other.XMPPGhostUserPrefix &&
c.XMPPGhostUserDomain == other.XMPPGhostUserDomain &&
c.XMPPGhostUserCleanup == other.XMPPGhostUserCleanup
}
// Clone shallow copies the configuration. Your implementation may require a deep copy if
// your configuration has reference types.
func (c *Configuration) Clone() *Configuration {
var clone = *c
return &clone
}
// GetXMPPResource returns the configured XMPP resource, or a default if not set
func (c *Configuration) GetXMPPResource() string {
if c.XMPPResource == "" {
return "mattermost-bridge"
}
return c.XMPPResource
}
// GetXMPPGhostUserDomain returns the configured ghost user domain, or derives it from server URL
func (c *Configuration) GetXMPPGhostUserDomain() string {
if c.XMPPGhostUserDomain != "" {
return c.XMPPGhostUserDomain
}
// Extract domain from bridge username as fallback
if c.XMPPUsername != "" && strings.Contains(c.XMPPUsername, "@") {
parts := strings.Split(c.XMPPUsername, "@")
if len(parts) > 1 {
return parts[1]
}
}
// Last resort: try to extract from server URL
if c.XMPPServerURL != "" {
parts := strings.Split(c.XMPPServerURL, ":")
if len(parts) > 0 {
return parts[0]
}
}
return "localhost"
}
// IsGhostUserEnabled returns true if ghost users should be created
func (c *Configuration) IsGhostUserEnabled() bool {
return c.EnableXMPPGhostUsers && c.EnableSync
}
// IsGhostUserCleanupEnabled returns true if ghost users should be cleaned up on removal
func (c *Configuration) IsGhostUserCleanupEnabled() bool {
return c.XMPPGhostUserCleanup
}
// IsValid validates the configuration and returns an error if invalid
func (c *Configuration) IsValid() error {
if c.EnableSync {
if c.XMPPServerURL == "" {
return fmt.Errorf("XMPP Server URL is required when sync is enabled")
}
if c.XMPPUsername == "" {
return fmt.Errorf("XMPP Username is required when sync is enabled")
}
if c.XMPPPassword == "" {
return fmt.Errorf("XMPP Password is required when sync is enabled")
}
// Validate server URL format
if !strings.Contains(c.XMPPServerURL, ":") {
return fmt.Errorf("XMPP Server URL must include port (e.g., server.com:5222)")
}
// Validate ghost user configuration if enabled
if c.EnableXMPPGhostUsers {
if c.XMPPGhostUserPrefix == "" {
return fmt.Errorf("XMPP Ghost User Prefix is required when ghost users are enabled")
}
// Validate ghost user prefix doesn't contain invalid characters
if strings.ContainsAny(c.XMPPGhostUserPrefix, ":@/\\") {
return fmt.Errorf("XMPP Ghost User Prefix cannot contain special characters (:, @, /, \\)")
}
}
}
return nil
}