147 lines
3.7 KiB
Go
147 lines
3.7 KiB
Go
package app
|
|
|
|
import (
|
|
transportcfgpkg "selective-vpn-api/app/transportcfg"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func createSingBoxProfileLocked(st *singBoxProfilesState, req SingBoxProfileCreateRequest) (SingBoxProfile, string, error) {
|
|
mode := SingBoxProfileModeTyped
|
|
if strings.TrimSpace(string(req.Mode)) != "" {
|
|
parsed, ok := normalizeSingBoxProfileMode(req.Mode)
|
|
if !ok {
|
|
return SingBoxProfile{}, singBoxProfileCodeBadMode, errSingBoxProfileMode()
|
|
}
|
|
mode = parsed
|
|
}
|
|
|
|
id := sanitizeID(req.ID)
|
|
if id == "" {
|
|
id = deriveSingBoxProfileID(req.Name, req.Protocol, st.Items)
|
|
}
|
|
if id == "" {
|
|
return SingBoxProfile{}, singBoxProfileCodeBadID, errSingBoxProfileID()
|
|
}
|
|
if findSingBoxProfileIndex(st.Items, id) >= 0 {
|
|
return SingBoxProfile{}, singBoxProfileCodeIDConflict, errSingBoxProfileExists()
|
|
}
|
|
|
|
enabled := true
|
|
if req.Enabled != nil {
|
|
enabled = *req.Enabled
|
|
}
|
|
now := time.Now().UTC().Format(time.RFC3339)
|
|
item := SingBoxProfile{
|
|
ID: id,
|
|
Name: strings.TrimSpace(req.Name),
|
|
Mode: mode,
|
|
Protocol: normalizeSingBoxProtocol(req.Protocol),
|
|
Enabled: enabled,
|
|
SchemaVersion: normalizeSingBoxSchemaVersion(req.SchemaVersion),
|
|
ProfileRevision: 1,
|
|
RenderRevision: 0,
|
|
Typed: cloneMapDeep(req.Typed),
|
|
RawConfig: cloneMapDeep(req.RawConfig),
|
|
Meta: cloneMapDeep(req.Meta),
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
if item.Name == "" {
|
|
item.Name = id
|
|
}
|
|
|
|
secretRes, err := applySingBoxSecretsPatch(id, false, req.Secrets)
|
|
if err != nil {
|
|
return SingBoxProfile{}, singBoxProfileCodeSecretsFailed, err
|
|
}
|
|
item.HasSecrets = secretRes.HasSecrets
|
|
item.SecretsMasked = secretRes.Masked
|
|
|
|
st.Items = append(st.Items, item)
|
|
ensureSingBoxProfilesActiveID(st)
|
|
st.Revision++
|
|
return item, "", nil
|
|
}
|
|
|
|
func patchSingBoxProfile(cur SingBoxProfile, req SingBoxProfilePatchRequest) (SingBoxProfile, singBoxSecretsPatchResult, bool, string, error) {
|
|
next := cur
|
|
changed := false
|
|
now := time.Now().UTC().Format(time.RFC3339)
|
|
|
|
if req.Name != nil {
|
|
v := strings.TrimSpace(*req.Name)
|
|
if v == "" {
|
|
v = next.ID
|
|
}
|
|
if next.Name != v {
|
|
next.Name = v
|
|
changed = true
|
|
}
|
|
}
|
|
if req.Mode != nil {
|
|
mode, ok := normalizeSingBoxProfileMode(*req.Mode)
|
|
if !ok {
|
|
return cur, singBoxSecretsPatchResult{}, false, singBoxProfileCodeBadMode, errSingBoxProfileMode()
|
|
}
|
|
if next.Mode != mode {
|
|
next.Mode = mode
|
|
changed = true
|
|
}
|
|
}
|
|
if req.Protocol != nil {
|
|
v := normalizeSingBoxProtocol(*req.Protocol)
|
|
if next.Protocol != v {
|
|
next.Protocol = v
|
|
changed = true
|
|
}
|
|
}
|
|
if req.Enabled != nil && next.Enabled != *req.Enabled {
|
|
next.Enabled = *req.Enabled
|
|
changed = true
|
|
}
|
|
if req.SchemaVersion != nil {
|
|
v := normalizeSingBoxSchemaVersion(*req.SchemaVersion)
|
|
if next.SchemaVersion != v {
|
|
next.SchemaVersion = v
|
|
changed = true
|
|
}
|
|
}
|
|
if req.Typed != nil {
|
|
next.Typed = cloneMapDeep(req.Typed)
|
|
changed = true
|
|
}
|
|
if req.RawConfig != nil {
|
|
next.RawConfig = cloneMapDeep(req.RawConfig)
|
|
changed = true
|
|
}
|
|
if req.Meta != nil {
|
|
next.Meta = cloneMapDeep(req.Meta)
|
|
changed = true
|
|
}
|
|
|
|
secretRes := singBoxSecretsPatchResult{
|
|
HasSecrets: next.HasSecrets,
|
|
Masked: transportcfgpkg.CloneStringMap(next.SecretsMasked),
|
|
}
|
|
if req.ClearSecrets || req.Secrets != nil {
|
|
var err error
|
|
secretRes, err = applySingBoxSecretsPatch(next.ID, req.ClearSecrets, req.Secrets)
|
|
if err != nil {
|
|
return cur, singBoxSecretsPatchResult{}, false, singBoxProfileCodeSecretsFailed, err
|
|
}
|
|
next.HasSecrets = secretRes.HasSecrets
|
|
next.SecretsMasked = secretRes.Masked
|
|
if secretRes.Changed {
|
|
changed = true
|
|
}
|
|
}
|
|
|
|
if !changed {
|
|
return cur, secretRes, false, "", nil
|
|
}
|
|
next.ProfileRevision = cur.ProfileRevision + 1
|
|
next.UpdatedAt = now
|
|
return next, secretRes, true, "", nil
|
|
}
|