mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-04 17:16:37 +08:00
Merge branch 'main' into opencode/lucky-otter
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go-backend/internal/http/client"
|
||||
@@ -40,6 +41,17 @@ type resetPeerShareFlowRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type updatePeerShareRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
MaxBandwidth int64 `json:"maxBandwidth"`
|
||||
ExpiryTime int64 `json:"expiryTime"`
|
||||
PortRangeStart int `json:"portRangeStart"`
|
||||
PortRangeEnd int `json:"portRangeEnd"`
|
||||
AllowedDomains string `json:"allowedDomains"`
|
||||
AllowedIPs string `json:"allowedIps"`
|
||||
}
|
||||
|
||||
type nodeImportRequest struct {
|
||||
RemoteURL string `json:"remoteUrl"`
|
||||
Token string `json:"token"`
|
||||
@@ -325,6 +337,80 @@ func (h *Handler) federationShareResetFlow(w http.ResponseWriter, r *http.Reques
|
||||
response.WriteJSON(w, response.OKEmpty())
|
||||
}
|
||||
|
||||
func (h *Handler) federationShareUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
response.WriteJSON(w, response.ErrDefault("Invalid method"))
|
||||
return
|
||||
}
|
||||
|
||||
var req updatePeerShareRequest
|
||||
if err := decodeJSON(r.Body, &req); err != nil {
|
||||
response.WriteJSON(w, response.ErrDefault("Invalid JSON"))
|
||||
return
|
||||
}
|
||||
if req.ID <= 0 {
|
||||
response.WriteJSON(w, response.ErrDefault("Share ID is required"))
|
||||
return
|
||||
}
|
||||
|
||||
share, err := h.repo.GetPeerShare(req.ID)
|
||||
if err != nil {
|
||||
response.WriteJSON(w, response.Err(-2, err.Error()))
|
||||
return
|
||||
}
|
||||
if share == nil {
|
||||
response.WriteJSON(w, response.ErrDefault("Share not found"))
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name == "" {
|
||||
response.WriteJSON(w, response.ErrDefault("Name is required"))
|
||||
return
|
||||
}
|
||||
|
||||
if req.MaxBandwidth < 0 {
|
||||
response.WriteJSON(w, response.ErrDefault("Max bandwidth cannot be negative"))
|
||||
return
|
||||
}
|
||||
|
||||
if req.ExpiryTime < 0 {
|
||||
response.WriteJSON(w, response.ErrDefault("Expiry time cannot be negative"))
|
||||
return
|
||||
}
|
||||
|
||||
if req.PortRangeStart < 0 || req.PortRangeStart > 65535 || req.PortRangeEnd < 0 || req.PortRangeEnd > 65535 {
|
||||
response.WriteJSON(w, response.ErrDefault("Invalid port range"))
|
||||
return
|
||||
}
|
||||
|
||||
if req.PortRangeStart > req.PortRangeEnd {
|
||||
response.WriteJSON(w, response.ErrDefault("Port range start cannot be greater than end"))
|
||||
return
|
||||
}
|
||||
|
||||
allowedIPs, err := normalizePeerShareAllowedIPs(req.AllowedIPs)
|
||||
if err != nil {
|
||||
response.WriteJSON(w, response.ErrDefault(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
share.Name = req.Name
|
||||
share.MaxBandwidth = req.MaxBandwidth
|
||||
share.ExpiryTime = req.ExpiryTime
|
||||
share.PortRangeStart = req.PortRangeStart
|
||||
share.PortRangeEnd = req.PortRangeEnd
|
||||
share.AllowedDomains = req.AllowedDomains
|
||||
share.AllowedIPs = allowedIPs
|
||||
share.UpdatedTime = time.Now().UnixMilli()
|
||||
|
||||
if err := h.repo.UpdatePeerShare(share); err != nil {
|
||||
response.WriteJSON(w, response.Err(-2, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteJSON(w, response.OKEmpty())
|
||||
}
|
||||
|
||||
func (h *Handler) federationRemoteUsageList(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
response.WriteJSON(w, response.ErrDefault("Invalid method"))
|
||||
@@ -1317,6 +1403,74 @@ func isPeerIPAllowed(clientIP net.IP, whitelist string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *Handler) syncRemoteNodeStatuses(items []map[string]interface{}) {
|
||||
type remoteEntry struct {
|
||||
index int
|
||||
remoteURL string
|
||||
remoteToken string
|
||||
}
|
||||
|
||||
var remotes []remoteEntry
|
||||
for i, item := range items {
|
||||
isRemote, _ := item["isRemote"].(int)
|
||||
if isRemote != 1 {
|
||||
continue
|
||||
}
|
||||
url, _ := item["remoteUrl"].(string)
|
||||
token, _ := item["remoteToken"].(string)
|
||||
url = strings.TrimSpace(url)
|
||||
token = strings.TrimSpace(token)
|
||||
if url == "" || token == "" {
|
||||
continue
|
||||
}
|
||||
remotes = append(remotes, remoteEntry{index: i, remoteURL: url, remoteToken: token})
|
||||
}
|
||||
if len(remotes) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
localDomain := h.federationLocalDomain()
|
||||
fc := client.NewFederationClientWithTimeout(5 * time.Second)
|
||||
|
||||
type syncResult struct {
|
||||
index int
|
||||
status int
|
||||
syncError string
|
||||
}
|
||||
|
||||
results := make([]syncResult, len(remotes))
|
||||
var wg sync.WaitGroup
|
||||
for i, entry := range remotes {
|
||||
wg.Add(1)
|
||||
go func(idx int, e remoteEntry) {
|
||||
defer wg.Done()
|
||||
info, err := fc.Connect(e.remoteURL, e.remoteToken, localDomain)
|
||||
if err != nil {
|
||||
errMsg := err.Error()
|
||||
if strings.Contains(errMsg, "401") || strings.Contains(errMsg, "Invalid token") || strings.Contains(errMsg, "Unauthorized") {
|
||||
results[idx] = syncResult{index: e.index, status: 0, syncError: "provider_share_deleted"}
|
||||
} else if strings.Contains(errMsg, "403") || strings.Contains(errMsg, "Share is disabled") {
|
||||
results[idx] = syncResult{index: e.index, status: 0, syncError: "provider_share_disabled"}
|
||||
} else if strings.Contains(errMsg, "Share expired") {
|
||||
results[idx] = syncResult{index: e.index, status: 0, syncError: "provider_share_expired"}
|
||||
} else {
|
||||
results[idx] = syncResult{index: e.index, status: 0, syncError: errMsg}
|
||||
}
|
||||
} else {
|
||||
results[idx] = syncResult{index: e.index, status: info.Status, syncError: ""}
|
||||
}
|
||||
}(i, entry)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for _, r := range results {
|
||||
items[r.index]["status"] = r.status
|
||||
if r.syncError != "" {
|
||||
items[r.index]["syncError"] = r.syncError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) cleanupPeerShareRuntimes(shareID int64) {
|
||||
if h == nil || h.repo == nil || shareID <= 0 {
|
||||
return
|
||||
|
||||
@@ -159,6 +159,7 @@ func (h *Handler) Register(mux *http.ServeMux) {
|
||||
mux.HandleFunc("/api/v1/open_api/sub_store", h.openAPISubStore)
|
||||
mux.HandleFunc("/api/v1/federation/share/list", h.federationShareList)
|
||||
mux.HandleFunc("/api/v1/federation/share/create", h.federationShareCreate)
|
||||
mux.HandleFunc("/api/v1/federation/share/update", h.federationShareUpdate)
|
||||
mux.HandleFunc("/api/v1/federation/share/delete", h.federationShareDelete)
|
||||
mux.HandleFunc("/api/v1/federation/share/reset-flow", h.federationShareResetFlow)
|
||||
mux.HandleFunc("/api/v1/federation/share/remote-usage/list", h.federationRemoteUsageList)
|
||||
@@ -324,6 +325,9 @@ func (h *Handler) nodeList(w http.ResponseWriter, r *http.Request) {
|
||||
response.WriteJSON(w, response.Err(-2, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
h.syncRemoteNodeStatuses(items)
|
||||
|
||||
response.WriteJSON(w, response.OK(items))
|
||||
}
|
||||
|
||||
|
||||
@@ -413,7 +413,7 @@ func (h *Handler) nodeInstall(w http.ResponseWriter, r *http.Request) {
|
||||
response.WriteJSON(w, response.Err(-2, err.Error()))
|
||||
return
|
||||
}
|
||||
cmd := fmt.Sprintf("curl -L https://github.com/Sagit-chu/flux-panel/releases/latest/download/install.sh -o ./install.sh && chmod +x ./install.sh && ./install.sh -a %s -s %s", processServerAddress(panelAddr), secret)
|
||||
cmd := fmt.Sprintf("curl -L https://gcode.hostcentral.cc/https://github.com/Sagit-chu/flux-panel/releases/latest/download/install.sh -o ./install.sh && chmod +x ./install.sh && ./install.sh -a %s -s %s", processServerAddress(panelAddr), secret)
|
||||
response.WriteJSON(w, response.OK(cmd))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user