This commit separates user credentials from resource record configs to allow user credentials to be used for multiple records instead of one.
89 lines
2.2 KiB
Go
89 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/pelletier/go-toml"
|
|
"os"
|
|
)
|
|
|
|
type Config struct {
|
|
ServerPort uint16 `toml:"port"`
|
|
Users []User `toml:"user"`
|
|
RRConfigs []RRConfig `toml:"rrconfig"`
|
|
|
|
users map[string]*User
|
|
rrconfigs map[string]*RRConfig
|
|
}
|
|
|
|
type User struct {
|
|
Username string `toml:"username"`
|
|
Password string `toml:"password"`
|
|
Records []string `toml:"records"`
|
|
|
|
records map[string]bool
|
|
}
|
|
|
|
type RRConfig struct {
|
|
Recordname string `toml:"recordname"`
|
|
Zonename string `toml:"zonename"`
|
|
Nameserver string `toml:"nameserver"`
|
|
Tsigalgo string `toml:"tsig_algo"`
|
|
Tsigid string `toml:"tsig_id"`
|
|
Tsigkey string `toml:"tsig_key"`
|
|
Ttl int `toml:"ttl" default:"60"`
|
|
}
|
|
|
|
func LoadConfig(path string) (*Config, error) {
|
|
var cfg Config
|
|
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
decoder := toml.NewDecoder(f).Strict(true)
|
|
err = decoder.Decode(&cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// temporary map for preventing duplicate records between users
|
|
records := make(map[string]bool)
|
|
|
|
// populate user map
|
|
cfg.users = map[string]*User{}
|
|
for _, user := range cfg.Users {
|
|
if _, ok := cfg.users[user.Username]; ok {
|
|
return nil, fmt.Errorf("Duplicate username detected: %s", user.Username)
|
|
}
|
|
|
|
// initialize and populate user.records map
|
|
user.records = make(map[string]bool)
|
|
if len(user.Records) <= 0 {
|
|
return nil, fmt.Errorf("User without records detected: %s", user.Username)
|
|
}
|
|
for _, record := range user.Records {
|
|
// check for duplicate records
|
|
if records[record] {
|
|
return nil, fmt.Errorf("Record associated with multiple users detected: %s", record)
|
|
}
|
|
// memorize record both in the user as well as in the temporary map
|
|
user.records[record] = true
|
|
records[record] = true
|
|
}
|
|
cfg.users[user.Username] = &user
|
|
}
|
|
|
|
// populate record map
|
|
cfg.rrconfigs = map[string]*RRConfig{}
|
|
for _, record := range cfg.RRConfigs {
|
|
if !records[record.Recordname] {
|
|
return nil, fmt.Errorf("Record without associated user detected: %s", record.Recordname)
|
|
}
|
|
if _, ok := cfg.rrconfigs[record.Recordname]; ok {
|
|
return nil, fmt.Errorf("Duplicate record detected: %s", record.Recordname)
|
|
}
|
|
cfg.rrconfigs[record.Recordname] = &record
|
|
}
|
|
return &cfg, nil
|
|
}
|