Add server file manager workflow
This commit is contained in:
@@ -150,7 +150,9 @@ func TestMetricsAndConfigReadAPIAreSafeAndRoleScoped(t *testing.T) {
|
||||
otherSession := postOKJSON[dto.AuthSessionResponse](t, router, "/api/v1/auth/login", dto.LoginRequest{Account: "other-metrics@example.test", Password: "secret-password"}).SessionID
|
||||
|
||||
postJSON[dto.GamePluginResponse](t, router, "/api/v1/game-plugins", validGamePluginRequest())
|
||||
postJSON[dto.RunEndpointResponse](t, router, "/api/v1/run/endpoints", validRunEndpointRequest())
|
||||
endpointRequest := validRunEndpointRequest()
|
||||
endpointRequest.Capabilities = append(endpointRequest.Capabilities, domain.JobCapabilityFilesList)
|
||||
postJSON[dto.RunEndpointResponse](t, router, "/api/v1/run/endpoints", endpointRequest)
|
||||
instance := postJSONWithAuth[dto.ServerInstanceResponse](t, router, "/api/v1/server-instances", dto.ServerInstanceCreateRequest{
|
||||
ID: "server-metrics-api",
|
||||
PluginID: "server.scum",
|
||||
@@ -234,11 +236,20 @@ func TestConfigWriteAndFileDispatchAPIAreScopedAndSafe(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreAPIDeclaredFileReadSnapshotRouteIsScopedAndRedacted(t *testing.T) {
|
||||
func TestCoreAPIServerFileWorkspaceRoutesAreScoped(t *testing.T) {
|
||||
router := newTestRouter()
|
||||
adminSession := createAdminSession(t, router)
|
||||
postJSON[dto.GamePluginResponse](t, router, "/api/v1/game-plugins", validGamePluginRequest())
|
||||
postJSON[dto.RunEndpointResponse](t, router, "/api/v1/run/endpoints", validRunEndpointRequest())
|
||||
postJSONWithAuth[dto.UserResponse](t, router, "/api/v1/users", dto.UserCreateRequest{ID: "file-workspace-other", DisplayName: "File Workspace Other", Email: "file-workspace-other@example.test", Roles: []string{"server-admin"}, Password: "secret-password"}, adminSession)
|
||||
otherSession := postOKJSON[dto.AuthSessionResponse](t, router, "/api/v1/auth/login", dto.LoginRequest{Account: "file-workspace-other@example.test", Password: "secret-password"}).SessionID
|
||||
pluginRequest := validGamePluginRequest()
|
||||
pluginRequest.RequiredRunCapabilities = append(pluginRequest.RequiredRunCapabilities, domain.JobCapabilityFilesList, domain.JobCapabilityFilesRead, domain.JobCapabilityFilesWrite)
|
||||
pluginRequest.DeclaredPermissions = []string{"server.files.read", "server.files.write"}
|
||||
pluginRequest.Permissions.Files = true
|
||||
pluginRequest.FileWorkspace = dto.PluginFileWorkspaceBody{DefaultDirectoryKey: "scum-config", Directories: []dto.PluginLogicalDirectoryBody{{Key: "scum-config", Label: "服务器配置", Scope: "config"}, {Key: "scum-logs", Label: "日志文件", Scope: "logs"}}, Files: []dto.PluginLogicalFileBody{{Key: "scum-server-settings", DirectoryKey: "scum-config", Label: "ServerSettings.ini", Kind: "config", Editable: true}, {Key: "scum-chat-log", DirectoryKey: "scum-logs", Label: "Chat.log", Kind: "log", StreamKey: "scum.chat"}}}
|
||||
postJSON[dto.GamePluginResponse](t, router, "/api/v1/game-plugins", pluginRequest)
|
||||
endpointRequest := validRunEndpointRequest()
|
||||
endpointRequest.Capabilities = append(endpointRequest.Capabilities, domain.JobCapabilityFilesList)
|
||||
postJSON[dto.RunEndpointResponse](t, router, "/api/v1/run/endpoints", endpointRequest)
|
||||
instance := postJSONWithAuth[dto.ServerInstanceResponse](t, router, "/api/v1/server-instances", dto.ServerInstanceCreateRequest{
|
||||
ID: "server-file-snapshot-api",
|
||||
PluginID: "server.scum",
|
||||
@@ -246,8 +257,33 @@ func TestCoreAPIDeclaredFileReadSnapshotRouteIsScopedAndRedacted(t *testing.T) {
|
||||
Name: "File Snapshot API Server",
|
||||
State: domain.ServerInstanceStateRunning,
|
||||
}, adminSession)
|
||||
putJSONWithAuth[dto.RuntimeBindingResponse](t, router, "/api/v1/server-instances/"+instance.ID+"/runtime-binding", dto.RuntimeBindingUpdateRequest{ProfileKey: "local", Bindings: map[string]string{}}, adminSession)
|
||||
|
||||
assertStatus(t, requestWithAuth(t, router, http.MethodGet, "/api/v1/server-instances/"+instance.ID+"/files/read-snapshot?key=scum-server-settings", "", adminSession), http.StatusNotFound)
|
||||
workspace := getJSONWithAuth[dto.ServerFileWorkspaceResponse](t, router, "/api/v1/server-instances/"+instance.ID+"/files/workspace", adminSession)
|
||||
if workspace.DefaultDirectoryKey != "scum-config" || workspace.Transfer.Channel != "run-file-transfer" || len(workspace.Files) != 2 {
|
||||
t.Fatalf("unexpected workspace: %+v", workspace)
|
||||
}
|
||||
list := getJSONWithAuth[dto.ServerFileListResponse](t, router, "/api/v1/server-instances/"+instance.ID+"/files/list?directoryKey=scum-config", adminSession)
|
||||
foundSettings := false
|
||||
for _, entry := range list.Entries {
|
||||
if entry.LogicalKey == "scum-server-settings" && entry.Editable && entry.Downloadable {
|
||||
foundSettings = true
|
||||
}
|
||||
}
|
||||
if list.State != "declared" || !foundSettings {
|
||||
t.Fatalf("expected declared file list, got %+v", list)
|
||||
}
|
||||
readRecorder := requestJSONWithAuth(t, router, http.MethodPost, "/api/v1/server-instances/"+instance.ID+"/files/read", dto.ServerFileReadRequest{PluginID: "server.scum", Key: "scum-server-settings", IdempotencyKey: "api-file-read"}, adminSession)
|
||||
assertStatus(t, readRecorder, http.StatusAccepted)
|
||||
read := decodeBody[dto.FileOperationDispatchResponse](t, readRecorder)
|
||||
if read.Job.Capability != domain.JobCapabilityFilesRead || read.Job.TargetKey != "scum-server-settings" {
|
||||
t.Fatalf("unexpected read dispatch: %+v", read)
|
||||
}
|
||||
snapshot := getJSONWithAuth[dto.DeclaredFileReadSnapshotResponse](t, router, "/api/v1/server-instances/"+instance.ID+"/files/read-snapshot?key=scum-server-settings", adminSession)
|
||||
if snapshot.State != "pending" || snapshot.JobID != read.Job.ID {
|
||||
t.Fatalf("expected pending read snapshot, got %+v", snapshot)
|
||||
}
|
||||
assertErrorResponse(t, requestWithAuth(t, router, http.MethodGet, "/api/v1/server-instances/"+instance.ID+"/files/workspace", "", otherSession), http.StatusForbidden, errorCodeForbidden)
|
||||
}
|
||||
|
||||
func TestCoreAPIServerRuntimeDistributionAndJobWorkflows(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user