refactor(api): simplify instance listing response and add running status

Remove sensitive information from instance listing response for all users and add isRunning field
Fix backend to prevent starting already running frpc instances
This commit is contained in:
2026-03-25 21:50:52 +08:00
parent 92a0e24db7
commit 25f88249c2
3 changed files with 11 additions and 62 deletions

View File

@@ -67,6 +67,7 @@ For detailed API documentation, please see [docs/api.md](docs/api.md)
- [ ] Add frpc instance log display API - [ ] Add frpc instance log display API
- [ ] Fix random database lock when processing logs - [ ] Fix random database lock when processing logs
- [ ] Add frpc createdBy storage and display - [ ] Add frpc createdBy storage and display
- [x] Fix backend can still start frpc instance when it is already running
## License ## License

View File

@@ -1138,7 +1138,7 @@ X-Timestamp: 1704067200000
| X-Token | string | Yes | Authentication token | | X-Token | string | Yes | Authentication token |
| X-Timestamp | int64 | Yes | Client timestamp in milliseconds | | X-Timestamp | int64 | Yes | Client timestamp in milliseconds |
**Response (admin/superuser):** **Response:**
```json ```json
{ {
"success": true, "success": true,
@@ -1147,33 +1147,9 @@ X-Timestamp: 1704067200000
{ {
"instanceID": 1, "instanceID": 1,
"name": "my_frpc", "name": "my_frpc",
"serverAddr": "127.0.0.1",
"serverPort": "7000",
"auth.method": "token",
"bootAtStart": true,
"runUser": "root",
"configPath": "./configs/superfrpc_user_my_frpc.toml",
"createdAt": "2024-01-01T00:00:00Z", "createdAt": "2024-01-01T00:00:00Z",
"createdBy": "admin" "createdBy": "admin",
} "isRunning": true
]
}
```
**Response (visitor):**
```json
{
"success": true,
"message": "instances retrieved successfully",
"data": [
{
"instanceID": 1,
"name": "my_frpc",
"bootAtStart": true,
"runUser": "root",
"configPath": "./configs/superfrpc_user_my_frpc.toml",
"createdAt": "2024-01-01T00:00:00Z",
"createdBy": "admin"
} }
] ]
} }
@@ -1183,16 +1159,9 @@ X-Timestamp: 1704067200000
|-------|------|-------------| |-------|------|-------------|
| instanceID | int | Instance ID | | instanceID | int | Instance ID |
| name | string | Instance name | | name | string | Instance name |
| serverAddr | string | frps server address (admin/superuser only) |
| serverPort | string | frps server port (admin/superuser only) |
| auth.method | string | Authentication method (admin/superuser only) |
| bootAtStart | bool | Auto-start on system boot |
| runUser | string | User to run the frpc instance as |
| configPath | string | Path to the configuration file |
| createdAt | string | Instance creation time (ISO 8601 format) | | createdAt | string | Instance creation time (ISO 8601 format) |
| createdBy | string | Username of the user who created this instance | | createdBy | string | Username of the user who created this instance |
| isRunning | bool | Instance running status: true (running) or false (stopped) |
> Note: Visitor users do not see sensitive information (serverAddr, serverPort, auth.method).
--- ---

View File

@@ -539,13 +539,6 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
userType, err := GetUserType(userID)
if err != nil {
postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to get user type: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user type")
return
}
instances, err := GetUserInstances(userID) instances, err := GetUserInstances(userID)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to get user instances: %v", err)) postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to get user instances: %v", err))
@@ -556,32 +549,18 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) {
instanceList := make([]map[string]interface{}, len(instances)) instanceList := make([]map[string]interface{}, len(instances))
for i, inst := range instances { for i, inst := range instances {
instanceData := map[string]interface{}{ instanceData := map[string]interface{}{
"instanceID": inst.ID, "instanceID": inst.ID,
"name": inst.Name, "name": inst.Name,
"bootAtStart": inst.BootAtStart, "createdAt": inst.CreatedAt,
"runUser": inst.RunUser, "createdBy": inst.CreatedBy,
"configPath": inst.ConfigPath, "isRunning": IsInstanceRunning(inst.ID),
"createdAt": inst.CreatedAt,
"createdBy": inst.CreatedBy,
}
if userType == "admin" || userType == "superuser" {
serverAddr, err := getKeyText(inst.ConfigPath, "serverAddr", "")
serverPort, err := getKeyText(inst.ConfigPath, "serverPort", "")
authMethod, err := getKeyText(inst.ConfigPath, "auth.method", "")
if err != nil {
postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to read config for instance %d: %v", inst.ID, err))
}
instanceData["serverAddr"] = serverAddr
instanceData["serverPort"] = serverPort
instanceData["auth_method"] = authMethod
} }
instanceList[i] = instanceData instanceList[i] = instanceData
} }
SendSuccessResponse(w, "Instances retrieved successfully", instanceList) SendSuccessResponse(w, "Instances retrieved successfully", instanceList)
postLog.Info(fmt.Sprintf("[ListInstancesHandler] Retrieved %d instances for user %d (type: %s)", len(instances), userID, userType)) postLog.Info(fmt.Sprintf("[ListInstancesHandler] Retrieved %d instances for user %d", len(instances), userID))
} }
func StartInstanceHandler(w http.ResponseWriter, r *http.Request) { func StartInstanceHandler(w http.ResponseWriter, r *http.Request) {