1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
package admin
import (
"errors"
"fmt"
"log/slog"
"strconv"
casbin "github.com/casbin/casbin/v2"
)
// Servicer container for dependencies and functions
type Servicer struct {
*casbin.SyncedEnforcer
Conf *ServerRepos
serverConfigPath string
reposDir string
mgmtRepo bool
}
// Reload reoload server config and sync policies
func (s *Servicer) Reload() {
tmpConfig, err := loadServerConfig(s.mgmtRepo, s.reposDir, s.serverConfigPath)
if err != nil {
// log.error
slog.Error("failed to load config", "error", err)
slog.Error("refusing to reload config")
return
}
slog.Debug("config base after load", "path", tmpConfig.basePath)
// copy
oldConfig := *s.Conf
slog.Debug("config base before copy", "path", s.Conf.basePath)
s.Conf = tmpConfig
slog.Debug("config base after copy", "path", s.Conf.basePath)
if err := s.InitServer(); err != nil {
slog.Error("couldn't init server with new config, falling back", slog.Any("error", err))
s.Conf = &oldConfig
if err := s.InitServer(); err != nil {
slog.Error("couldn't init server with old config, falling back", slog.Any("error", err))
panic("new and old config couldn't init server, no available config to run")
}
slog.Error("server has fallen back to old config but it lives in memory only, in fragile state")
}
}
// InitServer initialize a git server and configure
func (s *Servicer) InitServer() error {
policies := s.Conf.ServerPolicies()
numAdded := 0
slog.Debug(fmt.Sprintf("number of repos %s", strconv.Itoa(len(s.Conf.Repos))))
for _, policy := range policies {
added, err := s.AddPolicy(policy[0], policy[1], policy[2])
if err != nil {
// log.error
slog.Error("error adding policy", "role", policy[0], "slug", policy[1], "action", policy[2], "err", err)
continue
}
if added {
numAdded++
}
}
slog.Info("policy generated", "added", numAdded)
if err := s.SavePolicy(); err != nil {
return fmt.Errorf("policy couldn't be saved %w", err)
}
slog.Info("policy saved")
if err := s.LoadPolicy(); err != nil {
return fmt.Errorf("cloudn't load policy %w", err)
}
slog.Info("policy loaded")
slog.Debug("init server", "repoDir", s.reposDir)
slog.Debug("init server", "repoDir", s.Conf.basePath)
if err := s.Conf.ConfigureRepos(); err != nil {
return fmt.Errorf("couldn't configure repos %w", err)
}
slog.Info("configured repos")
return nil
}
// NewService create a new admin service, load config, and generate policies
func NewService(modelPath, policyPath, serverConfigPath, reposDir string, mgmtRepo bool) (*Servicer, error) {
workingPolicyPath, err := setupPolicyFile(policyPath)
if err != nil {
return &Servicer{}, err
}
slog.Debug(fmt.Sprintf("policy path %s", workingPolicyPath))
enf, err := casbin.NewSyncedEnforcer(modelPath, workingPolicyPath)
if err != nil {
return &Servicer{}, fmt.Errorf("couldn't load the enforcer encountered the following error: %w", err)
}
conf, err := loadServerConfig(mgmtRepo, reposDir, serverConfigPath)
if errors.Is(err, ErrMgmtRepoNotFound) {
slog.Info("no server config found, using default")
conf = defaultServerConfig
conf.basePath = reposDir
} else if err != nil {
return &Servicer{}, fmt.Errorf("coudln't load server config. %w", err)
}
svc := &Servicer{
enf,
conf,
serverConfigPath,
reposDir,
mgmtRepo,
}
if err := svc.InitServer(); err != nil {
return nil, err
}
return svc, nil
}
|