package role import ( "encoding/json" "errors" "github.com/google/uuid" "github.com/justamessenger/server/internal/database" "github.com/justamessenger/server/internal/models" ) type Manager struct { db *database.DB } func NewManager(db *database.DB) *Manager { return &Manager{db: db} } var DefaultPermissions = []string{ "view_channels", "send_messages", "add_reactions", "read_message_history", "connect_voice", "speak", } var AdminPermissions = []string{ "administrator", "manage_guild", "manage_channels", "manage_roles", "manage_messages", "kick_members", "ban_members", "view_channels", "send_messages", "add_reactions", "read_message_history", "connect_voice", "speak", "mute_members", "deafen_members", "move_members", "stream", } func (m *Manager) CreateDefaultRoles(guildID string) error { _, err := m.db.Exec( `INSERT OR IGNORE INTO roles (id, guild_id, name, color, position, permissions, is_default) VALUES (?, ?, 'everyone', 0, 0, ?, 1)`, uuid.New().String(), guildID, mustJSON(DefaultPermissions), ) return err } func mustJSON(v interface{}) string { b, _ := json.Marshal(v) return string(b) } func (m *Manager) Create(guildID, name string, color, position int, permissions []string) (*models.Role, error) { id := uuid.New().String() permJSON, _ := json.Marshal(permissions) _, err := m.db.Exec( `INSERT INTO roles (id, guild_id, name, color, position, permissions) VALUES (?, ?, ?, ?, ?, ?)`, id, guildID, name, color, position, string(permJSON), ) if err != nil { return nil, err } return m.Get(id) } func (m *Manager) Get(id string) (*models.Role, error) { row := m.db.QueryRow( `SELECT id, guild_id, name, color, position, permissions, is_default FROM roles WHERE id = ?`, id, ) r := &models.Role{} var permJSON string err := row.Scan(&r.ID, &r.GuildID, &r.Name, &r.Color, &r.Position, &permJSON, &r.IsDefault) if err != nil { return nil, err } json.Unmarshal([]byte(permJSON), &r.Permissions) return r, nil } func (m *Manager) ListByGuild(guildID string) ([]*models.Role, error) { rows, err := m.db.Query( `SELECT id, guild_id, name, color, position, permissions, is_default FROM roles WHERE guild_id = ? ORDER BY position DESC`, guildID, ) if err != nil { return nil, err } defer rows.Close() var roles []*models.Role for rows.Next() { r := &models.Role{} var permJSON string if err := rows.Scan(&r.ID, &r.GuildID, &r.Name, &r.Color, &r.Position, &permJSON, &r.IsDefault); err != nil { return nil, err } json.Unmarshal([]byte(permJSON), &r.Permissions) roles = append(roles, r) } return roles, nil } func (m *Manager) AssignRole(roleID, userID string) error { _, err := m.db.Exec( `INSERT OR IGNORE INTO role_members (role_id, user_id) VALUES (?, ?)`, roleID, userID, ) return err } func (m *Manager) RemoveRole(roleID, userID string) error { result, err := m.db.Exec( `DELETE FROM role_members WHERE role_id = ? AND user_id = ?`, roleID, userID, ) if err != nil { return err } affected, _ := result.RowsAffected() if affected == 0 { return errors.New("role assignment not found") } return nil } func (m *Manager) GetUserRoles(guildID, userID string) ([]*models.Role, error) { rows, err := m.db.Query( `SELECT r.id, r.guild_id, r.name, r.color, r.position, r.permissions, r.is_default FROM roles r INNER JOIN role_members rm ON r.id = rm.role_id WHERE r.guild_id = ? AND rm.user_id = ? UNION SELECT id, guild_id, name, color, position, permissions, is_default FROM roles WHERE guild_id = ? AND is_default = 1 ORDER BY position DESC`, guildID, userID, guildID, ) if err != nil { return nil, err } defer rows.Close() var roles []*models.Role for rows.Next() { r := &models.Role{} var permJSON string if err := rows.Scan(&r.ID, &r.GuildID, &r.Name, &r.Color, &r.Position, &permJSON, &r.IsDefault); err != nil { return nil, err } json.Unmarshal([]byte(permJSON), &r.Permissions) roles = append(roles, r) } return roles, nil } func (m *Manager) HasPermission(guildID, userID, permission string) (bool, error) { roles, err := m.GetUserRoles(guildID, userID) if err != nil { return false, err } for _, r := range roles { for _, p := range r.Permissions { if p == "administrator" || p == permission { return true, nil } } } return false, nil }