platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
86
selective-vpn-api/app/transport_singbox_profiles_secrets.go
Normal file
86
selective-vpn-api/app/transport_singbox_profiles_secrets.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
transportcfgpkg "selective-vpn-api/app/transportcfg"
|
||||
)
|
||||
|
||||
type singBoxSecretsPatchResult struct {
|
||||
HasSecrets bool
|
||||
Masked map[string]string
|
||||
Changed bool
|
||||
Rollback func()
|
||||
}
|
||||
|
||||
func applySingBoxSecretsPatch(profileID string, clear bool, updates map[string]string) (singBoxSecretsPatchResult, error) {
|
||||
id := sanitizeID(profileID)
|
||||
if id == "" {
|
||||
return singBoxSecretsPatchResult{}, errSingBoxProfileID()
|
||||
}
|
||||
|
||||
prev, err := readSingBoxSecrets(id)
|
||||
if err != nil {
|
||||
return singBoxSecretsPatchResult{}, err
|
||||
}
|
||||
next := map[string]string{}
|
||||
if !clear {
|
||||
next = transportcfgpkg.CloneStringMap(prev)
|
||||
if next == nil {
|
||||
next = map[string]string{}
|
||||
}
|
||||
}
|
||||
for key, val := range transportcfgpkg.NormalizeSecretUpdates(updates) {
|
||||
if val == "" {
|
||||
delete(next, key)
|
||||
continue
|
||||
}
|
||||
next[key] = val
|
||||
}
|
||||
changed := !transportcfgpkg.EqualStringMap(prev, next)
|
||||
if changed {
|
||||
if err := writeSingBoxSecrets(id, next); err != nil {
|
||||
return singBoxSecretsPatchResult{}, err
|
||||
}
|
||||
}
|
||||
res := singBoxSecretsPatchResult{
|
||||
HasSecrets: len(next) > 0,
|
||||
Masked: transportcfgpkg.MaskStringMap(next, "******"),
|
||||
Changed: changed,
|
||||
}
|
||||
if changed {
|
||||
rollbackPrev := transportcfgpkg.CloneStringMap(prev)
|
||||
res.Rollback = func() {
|
||||
_ = writeSingBoxSecrets(id, rollbackPrev)
|
||||
}
|
||||
}
|
||||
if !res.HasSecrets {
|
||||
res.Masked = nil
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func readSingBoxSecrets(profileID string) (map[string]string, error) {
|
||||
id := sanitizeID(profileID)
|
||||
if id == "" {
|
||||
return nil, errSingBoxProfileID()
|
||||
}
|
||||
path := singBoxSecretsPath(id)
|
||||
return transportcfgpkg.ReadStringMapJSON(path)
|
||||
}
|
||||
|
||||
func writeSingBoxSecrets(profileID string, secrets map[string]string) error {
|
||||
id := sanitizeID(profileID)
|
||||
if id == "" {
|
||||
return errSingBoxProfileID()
|
||||
}
|
||||
path := singBoxSecretsPath(id)
|
||||
return transportcfgpkg.WriteStringMapJSON(path, secrets, 0o700, 0o600)
|
||||
}
|
||||
|
||||
func singBoxSecretsPath(profileID string) string {
|
||||
id := sanitizeID(profileID)
|
||||
if id == "" {
|
||||
return filepath.Join(singBoxSecretsRootDir, "invalid.json")
|
||||
}
|
||||
return filepath.Join(singBoxSecretsRootDir, id+".json")
|
||||
}
|
||||
Reference in New Issue
Block a user