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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
package global
import (
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"sync"
"github.com/adrian-lorenz/noxway/auth"
"github.com/adrian-lorenz/noxway/config"
"github.com/adrian-lorenz/noxway/database"
"github.com/adrian-lorenz/noxway/pservice"
log "github.com/sirupsen/logrus"
)
var (
Services = pservice.Services{}
Config = config.ConfigStruct{}
mu sync.RWMutex
Path string
Log *log.Logger
Auth = auth.AuthStruct{}
)
// GetConfig returns a copy of the global config with read-lock protection
func GetConfig() config.ConfigStruct {
mu.RLock()
defer mu.RUnlock()
return Config
}
// GetServices returns a copy of the services config with read-lock protection
func GetServices() pservice.Services {
mu.RLock()
defer mu.RUnlock()
return Services
}
// GetAuth returns a copy of the auth config with read-lock protection
func GetAuth() auth.AuthStruct {
mu.RLock()
defer mu.RUnlock()
return Auth
}
// safeLogPath returns true when the path does not escape via path traversal.
func safeLogPath(p string) bool {
if strings.Contains(p, "..") {
return false
}
cleaned := filepath.Clean(p)
return !strings.Contains(cleaned, "..")
}
func InitLogger() {
Log = log.New()
Log.SetLevel(log.DebugLevel)
if Config.ExportLog {
logPath := Config.ExportLogPath
if !safeLogPath(logPath) {
fmt.Println("Warning: ExportLogPath contains path traversal, falling back to stderr")
Log.SetOutput(os.Stderr)
return
}
// Ensure parent directory exists
_ = os.MkdirAll(filepath.Dir(logPath), 0755)
file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
if err == nil {
Log.SetOutput(io.MultiWriter(file, os.Stderr))
} else {
Log.Info("Failed to log to file, using default stderr")
}
} else {
Log.SetOutput(os.Stderr)
}
}
func SetGlobConfig(newConfig config.ConfigStruct) {
mu.Lock()
Config = newConfig
mu.Unlock()
}
func SetSrvConfig(newConfig pservice.Services) {
mu.Lock()
Services = newConfig
mu.Unlock()
}
func SetAuthConfig(newConfig auth.AuthStruct) {
mu.Lock()
Auth = newConfig
mu.Unlock()
}
func LoadAllConfig() {
var err error
Path, err = os.Getwd()
if err != nil {
fmt.Println("Error getting working directory:", err)
panic(err)
}
CheckConfigGlob()
CheckConfigService()
CheckConfigAuth()
val, err := database.LoadConfigEntry("global")
if err != nil {
fmt.Println("Error loading global config:", err)
panic(err)
}
var cfg config.ConfigStruct
if err := json.Unmarshal([]byte(val), &cfg); err != nil {
fmt.Println("Error parsing global config:", err)
panic(err)
}
val, err = database.LoadConfigEntry("services")
if err != nil {
fmt.Println("Error loading services config:", err)
panic(err)
}
var svcs pservice.Services
if err := json.Unmarshal([]byte(val), &svcs); err != nil {
fmt.Println("Error parsing services config:", err)
panic(err)
}
val, err = database.LoadConfigEntry("auth")
if err != nil {
fmt.Println("Error loading auth config:", err)
panic(err)
}
var authCfg auth.AuthStruct
if err := json.Unmarshal([]byte(val), &authCfg); err != nil {
fmt.Println("Error parsing auth config:", err)
panic(err)
}
fmt.Println("Config loaded from database")
SetSrvConfig(svcs)
SetGlobConfig(cfg)
SetAuthConfig(authCfg)
}
func SaveGlobalConfig() {
mu.Lock()
defer mu.Unlock()
data, err := json.Marshal(Config)
if err != nil {
fmt.Println("Error marshaling global config:", err)
panic(err)
}
if err := database.SaveConfigEntry("global", string(data)); err != nil {
fmt.Println("Error saving global config:", err)
panic(err)
}
}
func SaveServiceConfig() {
mu.Lock()
defer mu.Unlock()
data, err := json.Marshal(Services)
if err != nil {
fmt.Println("Error marshaling services config:", err)
panic(err)
}
if err := database.SaveConfigEntry("services", string(data)); err != nil {
fmt.Println("Error saving services config:", err)
panic(err)
}
}
func SaveAuthConfig() {
mu.Lock()
defer mu.Unlock()
data, err := json.Marshal(Auth)
if err != nil {
fmt.Println("Error marshaling auth config:", err)
panic(err)
}
if err := database.SaveConfigEntry("auth", string(data)); err != nil {
fmt.Println("Error saving auth config:", err)
panic(err)
}
}
|