platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
transportcfgpkg "selective-vpn-api/app/transportcfg"
|
||||
)
|
||||
|
||||
func prepareSingBoxClientProfile(client TransportClient, checkBinary bool) transportBackendActionResult {
|
||||
if client.Kind != TransportClientSingBox {
|
||||
return transportBackendActionResult{
|
||||
OK: true,
|
||||
Message: "singbox preflight skipped",
|
||||
}
|
||||
}
|
||||
|
||||
singBoxProfilesMu.Lock()
|
||||
defer singBoxProfilesMu.Unlock()
|
||||
|
||||
st := loadSingBoxProfilesState()
|
||||
idx := findSingBoxProfileIndexForClient(st, client.ID)
|
||||
if idx < 0 {
|
||||
return transportBackendActionResult{
|
||||
OK: false,
|
||||
Code: singBoxProfileCodeNotFound,
|
||||
Message: "singbox profile not linked to client " + client.ID,
|
||||
ExitCode: -1,
|
||||
}
|
||||
}
|
||||
cur := st.Items[idx]
|
||||
now := time.Now().UTC().Format(time.RFC3339Nano)
|
||||
|
||||
eval := evaluateSingBoxProfile(cur, checkBinary)
|
||||
cur.LastValidatedAt = now
|
||||
cur.UpdatedAt = now
|
||||
if !eval.Valid {
|
||||
cur.LastError = joinSingBoxIssueMessages(eval.Errors)
|
||||
st.Items[idx] = cur
|
||||
_ = saveSingBoxProfilesState(st)
|
||||
return transportBackendActionResult{
|
||||
OK: false,
|
||||
Code: singBoxProfileCodeValidationFailed,
|
||||
Message: "profile preflight failed: " + strings.TrimSpace(cur.LastError),
|
||||
ExitCode: -1,
|
||||
}
|
||||
}
|
||||
|
||||
renderPath, err := writeSingBoxRenderedConfig(cur.ID, eval.Config)
|
||||
if err != nil {
|
||||
cur.LastError = err.Error()
|
||||
st.Items[idx] = cur
|
||||
_ = saveSingBoxProfilesState(st)
|
||||
return transportBackendActionResult{
|
||||
OK: false,
|
||||
Code: singBoxProfileCodeRenderFailed,
|
||||
Message: "profile preflight render failed: " + err.Error(),
|
||||
ExitCode: -1,
|
||||
}
|
||||
}
|
||||
|
||||
configPath := transportSingBoxConfigPath(client)
|
||||
if strings.TrimSpace(configPath) == "" {
|
||||
configPath = defaultSingBoxAppliedConfigPath(cur.ID)
|
||||
}
|
||||
if err := transportcfgpkg.WriteJSONConfigFile(configPath, eval.Config); err != nil {
|
||||
cur.LastError = err.Error()
|
||||
st.Items[idx] = cur
|
||||
_ = saveSingBoxProfilesState(st)
|
||||
return transportBackendActionResult{
|
||||
OK: false,
|
||||
Code: singBoxProfileCodeApplyFailed,
|
||||
Message: "profile preflight write failed: " + err.Error(),
|
||||
ExitCode: -1,
|
||||
Stdout: renderPath,
|
||||
}
|
||||
}
|
||||
|
||||
cur.LastError = ""
|
||||
st.Items[idx] = cur
|
||||
if err := saveSingBoxProfilesState(st); err != nil {
|
||||
return transportBackendActionResult{
|
||||
OK: false,
|
||||
Code: singBoxProfileCodeSaveFailed,
|
||||
Message: "profile preflight save failed: " + err.Error(),
|
||||
ExitCode: -1,
|
||||
Stdout: renderPath,
|
||||
}
|
||||
}
|
||||
|
||||
return transportBackendActionResult{
|
||||
OK: true,
|
||||
ExitCode: 0,
|
||||
Message: "profile preflight ready: " + cur.ID,
|
||||
Stdout: strings.TrimSpace(configPath),
|
||||
Stderr: strings.TrimSpace(renderPath),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user