Added all of the existing code
This commit is contained in:
339
oper_config.go
Normal file
339
oper_config.go
Normal file
@@ -0,0 +1,339 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// OperClass defines an operator class with specific permissions
|
||||
type OperClass struct {
|
||||
Name string `json:"name"`
|
||||
Rank int `json:"rank"` // Higher number = higher rank
|
||||
Description string `json:"description"`
|
||||
Permissions []string `json:"permissions"`
|
||||
Inherits string `json:"inherits"` // Inherit permissions from another class
|
||||
Color string `json:"color"` // Color for display purposes
|
||||
Symbol string `json:"symbol"` // Symbol to display (*, @, &, etc.)
|
||||
}
|
||||
|
||||
// Oper defines an individual operator
|
||||
type Oper struct {
|
||||
Name string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
Host string `json:"host"`
|
||||
Class string `json:"class"`
|
||||
Flags []string `json:"flags"` // Additional per-user flags
|
||||
MaxClients int `json:"max_clients"` // Max clients this oper can handle
|
||||
Expires string `json:"expires"` // Expiration date (optional)
|
||||
Contact string `json:"contact"` // Contact information
|
||||
LastSeen string `json:"last_seen"` // Last time this oper was online
|
||||
}
|
||||
|
||||
// RankNames defines custom names for rank levels
|
||||
type RankNames struct {
|
||||
Rank1 string `json:"rank_1"` // Default: Helper
|
||||
Rank2 string `json:"rank_2"` // Default: Moderator
|
||||
Rank3 string `json:"rank_3"` // Default: Operator
|
||||
Rank4 string `json:"rank_4"` // Default: Administrator
|
||||
Rank5 string `json:"rank_5"` // Default: Owner
|
||||
// Support for custom ranks beyond 5
|
||||
CustomRanks map[string]int `json:"custom_ranks"` // "CustomName": 6
|
||||
}
|
||||
|
||||
// OperConfig holds the complete operator configuration
|
||||
type OperConfig struct {
|
||||
Classes []OperClass `json:"classes"`
|
||||
Opers []Oper `json:"opers"`
|
||||
RankNames RankNames `json:"rank_names"`
|
||||
Settings struct {
|
||||
RequireSSL bool `json:"require_ssl"`
|
||||
MaxFailedAttempts int `json:"max_failed_attempts"`
|
||||
LockoutDuration int `json:"lockout_duration_minutes"`
|
||||
AllowedCommands []string `json:"allowed_commands"`
|
||||
LogOperActions bool `json:"log_oper_actions"`
|
||||
NotifyOnOperUp bool `json:"notify_on_oper_up"`
|
||||
AutoExpireInactive int `json:"auto_expire_inactive_days"`
|
||||
RequireTwoFactor bool `json:"require_two_factor"`
|
||||
} `json:"settings"`
|
||||
}
|
||||
|
||||
// LoadOperConfig loads operator configuration from file
|
||||
func LoadOperConfig(filename string) (*OperConfig, error) {
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read oper config file: %v", err)
|
||||
}
|
||||
|
||||
var config OperConfig
|
||||
if err := json.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse oper config file: %v", err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// SaveOperConfig saves operator configuration to file
|
||||
func SaveOperConfig(config *OperConfig, filename string) error {
|
||||
data, err := json.MarshalIndent(config, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal oper config: %v", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filename, data, 0644); err != nil {
|
||||
return fmt.Errorf("failed to write oper config file: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOperClass returns the operator class by name
|
||||
func (oc *OperConfig) GetOperClass(className string) *OperClass {
|
||||
for i := range oc.Classes {
|
||||
if oc.Classes[i].Name == className {
|
||||
return &oc.Classes[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOper returns the operator by name
|
||||
func (oc *OperConfig) GetOper(operName string) *Oper {
|
||||
for i := range oc.Opers {
|
||||
if oc.Opers[i].Name == operName {
|
||||
return &oc.Opers[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOperPermissions returns all permissions for an operator (including inherited)
|
||||
func (oc *OperConfig) GetOperPermissions(operName string) []string {
|
||||
oper := oc.GetOper(operName)
|
||||
if oper == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
class := oc.GetOperClass(oper.Class)
|
||||
if class == nil {
|
||||
return oper.Flags
|
||||
}
|
||||
|
||||
permissions := make(map[string]bool)
|
||||
|
||||
// Add class permissions
|
||||
for _, perm := range class.Permissions {
|
||||
permissions[perm] = true
|
||||
}
|
||||
|
||||
// Add inherited permissions
|
||||
if class.Inherits != "" {
|
||||
inherited := oc.GetOperClass(class.Inherits)
|
||||
if inherited != nil {
|
||||
for _, perm := range inherited.Permissions {
|
||||
permissions[perm] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add individual flags
|
||||
for _, flag := range oper.Flags {
|
||||
permissions[flag] = true
|
||||
}
|
||||
|
||||
// Convert back to slice
|
||||
result := make([]string, 0, len(permissions))
|
||||
for perm := range permissions {
|
||||
result = append(result, perm)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GetRankName returns the custom name for a rank level
|
||||
func (oc *OperConfig) GetRankName(rank int) string {
|
||||
switch rank {
|
||||
case 1:
|
||||
if oc.RankNames.Rank1 != "" {
|
||||
return oc.RankNames.Rank1
|
||||
}
|
||||
return "Helper"
|
||||
case 2:
|
||||
if oc.RankNames.Rank2 != "" {
|
||||
return oc.RankNames.Rank2
|
||||
}
|
||||
return "Moderator"
|
||||
case 3:
|
||||
if oc.RankNames.Rank3 != "" {
|
||||
return oc.RankNames.Rank3
|
||||
}
|
||||
return "Operator"
|
||||
case 4:
|
||||
if oc.RankNames.Rank4 != "" {
|
||||
return oc.RankNames.Rank4
|
||||
}
|
||||
return "Administrator"
|
||||
case 5:
|
||||
if oc.RankNames.Rank5 != "" {
|
||||
return oc.RankNames.Rank5
|
||||
}
|
||||
return "Owner"
|
||||
default:
|
||||
// Check custom ranks
|
||||
for name, rankNum := range oc.RankNames.CustomRanks {
|
||||
if rankNum == rank {
|
||||
return name
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("Rank %d", rank)
|
||||
}
|
||||
}
|
||||
|
||||
// GetOperRankName returns the rank name for an operator
|
||||
func (oc *OperConfig) GetOperRankName(operName string) string {
|
||||
oper := oc.GetOper(operName)
|
||||
if oper == nil {
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
class := oc.GetOperClass(oper.Class)
|
||||
if class == nil {
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
return oc.GetRankName(class.Rank)
|
||||
}
|
||||
|
||||
// SetCustomRankName allows adding custom rank names at runtime
|
||||
func (oc *OperConfig) SetCustomRankName(name string, rank int) {
|
||||
if oc.RankNames.CustomRanks == nil {
|
||||
oc.RankNames.CustomRanks = make(map[string]int)
|
||||
}
|
||||
oc.RankNames.CustomRanks[name] = rank
|
||||
}
|
||||
|
||||
// HasPermission checks if an operator has a specific permission
|
||||
func (oc *OperConfig) HasPermission(operName, permission string) bool {
|
||||
permissions := oc.GetOperPermissions(operName)
|
||||
for _, perm := range permissions {
|
||||
if perm == permission || perm == "*" { // * grants all permissions
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetOperRank returns the rank of an operator
|
||||
func (oc *OperConfig) GetOperRank(operName string) int {
|
||||
oper := oc.GetOper(operName)
|
||||
if oper == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
class := oc.GetOperClass(oper.Class)
|
||||
if class == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return class.Rank
|
||||
}
|
||||
|
||||
// CanOperateOn checks if oper1 can perform actions on oper2 (based on rank)
|
||||
func (oc *OperConfig) CanOperateOn(oper1Name, oper2Name string) bool {
|
||||
rank1 := oc.GetOperRank(oper1Name)
|
||||
rank2 := oc.GetOperRank(oper2Name)
|
||||
|
||||
// Higher rank can operate on lower rank
|
||||
// Same rank cannot operate on each other (unless they have override permission)
|
||||
return rank1 > rank2 || oc.HasPermission(oper1Name, "override_rank")
|
||||
}
|
||||
|
||||
// DefaultOperConfig returns a default operator configuration
|
||||
func DefaultOperConfig() *OperConfig {
|
||||
return &OperConfig{
|
||||
Classes: []OperClass{
|
||||
{
|
||||
Name: "helper",
|
||||
Rank: 1,
|
||||
Description: "Helper - Basic moderation commands",
|
||||
Permissions: []string{"kick", "topic", "mode_channel"},
|
||||
Color: "green",
|
||||
Symbol: "%",
|
||||
},
|
||||
{
|
||||
Name: "moderator",
|
||||
Rank: 2,
|
||||
Description: "Moderator - Channel and user management",
|
||||
Permissions: []string{"ban", "unban", "kick", "mute", "topic", "mode_channel", "mode_user", "who_override"},
|
||||
Inherits: "helper",
|
||||
Color: "blue",
|
||||
Symbol: "@",
|
||||
},
|
||||
{
|
||||
Name: "operator",
|
||||
Rank: 3,
|
||||
Description: "Operator - Server management commands",
|
||||
Permissions: []string{"kill", "gline", "rehash", "connect", "squit", "wallops", "operwall"},
|
||||
Inherits: "moderator",
|
||||
Color: "red",
|
||||
Symbol: "*",
|
||||
},
|
||||
{
|
||||
Name: "admin",
|
||||
Rank: 4,
|
||||
Description: "Administrator - Full server control",
|
||||
Permissions: []string{"*"}, // All permissions
|
||||
Color: "purple",
|
||||
Symbol: "&",
|
||||
},
|
||||
{
|
||||
Name: "owner",
|
||||
Rank: 5,
|
||||
Description: "Server Owner - Ultimate authority",
|
||||
Permissions: []string{"*", "override_rank", "shutdown", "restart"},
|
||||
Color: "gold",
|
||||
Symbol: "~",
|
||||
},
|
||||
},
|
||||
Opers: []Oper{
|
||||
{
|
||||
Name: "admin",
|
||||
Password: "changeme",
|
||||
Host: "*@localhost",
|
||||
Class: "admin",
|
||||
MaxClients: 1000,
|
||||
Contact: "admin@example.com",
|
||||
},
|
||||
},
|
||||
RankNames: RankNames{
|
||||
Rank1: "Helper", // Customizable: "Support Staff", "Junior Mod", etc.
|
||||
Rank2: "Moderator", // Customizable: "Channel Mod", "Guard", etc.
|
||||
Rank3: "Operator", // Customizable: "IRC Operator", "Senior Staff", etc.
|
||||
Rank4: "Administrator", // Customizable: "Admin", "Server Admin", etc.
|
||||
Rank5: "Owner", // Customizable: "Root", "Founder", etc.
|
||||
CustomRanks: map[string]int{
|
||||
// Example: "Super Admin": 6,
|
||||
// Example: "Network Founder": 10,
|
||||
},
|
||||
},
|
||||
Settings: struct {
|
||||
RequireSSL bool `json:"require_ssl"`
|
||||
MaxFailedAttempts int `json:"max_failed_attempts"`
|
||||
LockoutDuration int `json:"lockout_duration_minutes"`
|
||||
AllowedCommands []string `json:"allowed_commands"`
|
||||
LogOperActions bool `json:"log_oper_actions"`
|
||||
NotifyOnOperUp bool `json:"notify_on_oper_up"`
|
||||
AutoExpireInactive int `json:"auto_expire_inactive_days"`
|
||||
RequireTwoFactor bool `json:"require_two_factor"`
|
||||
}{
|
||||
RequireSSL: false,
|
||||
MaxFailedAttempts: 3,
|
||||
LockoutDuration: 30,
|
||||
AllowedCommands: []string{"OPER", "KILL", "GLINE", "REHASH", "WALLOPS"},
|
||||
LogOperActions: true,
|
||||
NotifyOnOperUp: true,
|
||||
AutoExpireInactive: 365,
|
||||
RequireTwoFactor: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user