跳到內容
Syno Package Land
語言: 繁體中文

App API 參考

原生 App 有一個 Go 後端。UI 以具名的方法呼叫它,例如 greeting.get。本頁列出呼叫格式、權限等級、模板內建的方法、新增 route 的 Go API,以及產生的 UI 中的用戶端輔助函式。

UI 呼叫 ctx.call(method, params)。DSM 會在視窗開啟時把 ctx 交給你的 UI。ctx.call 會用使用者的 DSM 工作階段,向 App 的後端送出 JSON POST。

項目值
請求內容{"method": "app.status", "params": {}}。未知的欄位會被拒絕。
成功{"success": true, "data": …}。ctx.call 會以 data 完成。
錯誤{"success": false, "error": {"code": "…", "message": "…"}}。ctx.call 會以 {code, message} 拒絕。
HTTP 狀態API 錯誤一律為 200,避免 DSM 取代回應內容。
來源只接受同源。Content-Type 必須是 application/json。

錯誤碼列在錯誤碼。檔案上傳與下載不使用 ctx.call。它們使用 HTTP 傳輸,方法名稱放在查詢字串(?method=nas.files.upload 與 ?method=nas.files.download)。產生的檔案輔助函式會替你處理。

每個方法有一個權限等級。等級設在處理函式之外,也就是 backend/internal/api/permissions.json。

等級誰可以呼叫
administratorsDSM 管理員群組的成員。這是預設值。
authenticated任何通過 entry 檢查的已登入 DSM 使用者。
public任何人,不需登入。只有 identity.* 方法使用。

沒有列出的方法會使用 administrators。非管理員呼叫未列出的方法,會得到 admin_required。呼叫沒有註冊的方法,所有已登入的呼叫者都會得到 unknown_method。

{
"schema": 1,
"default": "administrators",
"methods": {
"app.status": "authenticated",
"reports.list": "authenticated"
}
}
規則值
檔案結構恰好是 schema、default 與 methods。default 是 administrators。
方法名稱小寫的 area.action 格式,例如 reports.list。格式為 ^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$,最多 128 個字元。
大小最多 1024 個方法,檔案最大 64 KiB。重複的 key 會被拒絕。
已註冊的方法列出的每個方法都必須有處理函式。
能力的方法nas.*、bg.*、identity.*、portal.*、executor.*、root.run 與 delegate.* 的權限是固定的。你無法在 permissions.json 修改。

check 與 build 會驗證這個檔案。錯誤會使用 STANDALONE_API_PERMISSIONS_INVALID。請見錯誤碼。

dsm-package.yaml 的 entry 欄位限制誰可以開啟 App。

entry效果
省略沒有額外檢查。能開啟視窗的使用者都可以呼叫 authenticated 方法。
admin-only只有管理員。其他人會得到 admin_required。
app-privilege只有 DSM 應用程式權限允許的使用者。其他人會得到 app_privilege_denied。它需要至少一個不是 administrators 的方法。只有 files 或 jobs 就足夠。

管理員一律通過閘門。public 方法會略過它。請見 Manifest 參考。

只有在對應的能力開啟時,方法才存在。以 synopkgland add <name> 或 init --with <name> 加入能力。

方法權限用途
app.statusadministrators套件名稱、版本、呼叫者(user、admin)、程序、平台與時間。App 有共用資料夾時會加上 shared_folders。
greeting.getadministrators讀取範例問候語。回傳 {text}。
greeting.setadministrators寫入範例問候語。{text} 必須是 1 到 200 個字元。

這三個是範例。請以你自己的方法取代它們。init --with delegate 也會把 app.status 列為 authenticated。

方法權限參數用途
nas.session.statusauthenticated無檔案存取開啟時,回傳 {mode: "filestation-session"}。
nas.files.sharesauthenticatedoffset列出使用者看得到的共用資料夾。
nas.files.listauthenticatedpath、offset、limit(最多 100)、sortBy(name、size、type、mtime)、sortDirection(ASC、DESC)列出資料夾內容。
nas.files.infoauthenticatedpath回傳單一檔案或資料夾。
nas.files.create_folderauthenticatedparent、name建立資料夾。回傳 {created: true}。
nas.files.uploadauthenticated查詢字串 parent、name。內容是檔案。上傳檔案。不會覆寫,也不會建立上層資料夾。需要 Content-Length,最大 16 GiB。
nas.files.downloadauthenticated查詢字串 path以附件形式下載檔案。

每個呼叫都以登入使用者自己的 DSM 權限執行。路徑必須是絕對路徑、最多 4096 個字元,且不含 \、,、" 或控制字元。一頁清單最多 100 筆。

方法權限用途
bg.statusauthenticated擁有者、上限,以及排隊中與執行中的工作數量。
bg.browseauthenticated瀏覽呼叫者的資料夾,以選擇工作輸入。不需要 files。
bg.jobs.submitauthenticated將工作排入佇列。參數 key、folder、relative。回傳 {job, duplicate}。
bg.jobs.listauthenticated列出呼叫者的工作,最新的在前。
bg.jobs.getauthenticated以 id 取得一個工作。
bg.jobs.cancelauthenticated以 id 取消工作。
bg.jobs.resultauthenticated已完成工作的結果,格式為 JSON。完成前會回傳 not_ready。
bg.jobs.purgeadministrators清除某個使用者的工作資料(owner: {user, uid})。
bg.schedules.listauthenticated列出排程。
bg.schedules.createauthenticated重複執行工作。參數 key、jobId、intervalSeconds(3600、86400 或 604800)、consent: true。
bg.schedules.disableauthenticated以 id 停止排程。
bg.schedules.deleteauthenticated以 id 刪除排程。
bg.schedules.enableadministrators重新啟動排程。參數 id、consent: true。

工作的 key 符合 ^[A-Za-z0-9._-]{1,64}$。工作狀態有 queued、running、succeeded、failed、canceled 與 interrupted。失敗的工作有 errorCode,請見錯誤碼。

所有 identity.* 方法都是 public。它們需要 HTTPS 與同源的 JSON POST。

方法參數用途
identity.status無回傳 {enabled: true}。
identity.sessionbootstrap(選用)回傳 App 工作階段的 {user, uid, expiresAt}。使用 bootstrap: true 且沒有 App 工作階段時,會從 DSM 登入狀態建立一個。
identity.loginaccount、password、otp(選用)以使用者的 DSM 帳號登入,並建立 App 工作階段。
identity.logout無結束 App 工作階段。回傳 {loggedOut: true}。

應用程式入口網站 (Application Portal)(portal)

Section titled “應用程式入口網站 (Application Portal)(portal)”
方法權限用途
portal.statusauthenticated讀取已儲存的入口網站別名,以及是否已啟用。

管理員透過 ctx.portal 從 UI 設定或清除別名。請見應用程式入口網站指南。

方法權限參數用途
executor.statusauthenticated無已核准輔助程式的狀態:digest、版本、ready、disabled,以及 tasks,即 executor 自己對核准任務的核對結果 {state, checked_at}:啟動後第一次核對結束前為 checking,之後是 ready、stale(ready 的核對已超過 15 分鐘)或 failed。executor 啟動時核對一次,通過後每 10 分鐘、失敗後每 1 分鐘再核對。executor 暫停時回傳 {ready: false, state: "paused", reason: "executor_not_listening", next}。
executor.controladministratorsaction:start、stop 或 purge啟動、停止或清除輔助程式。
root.runadministratorsname以 root 執行 root/<name>.sh,並回傳 {output}。不能帶引數。

delegate 專案也會有 executor.*。root.run 失敗,或 executor.status 除了 executor 暫停以外的失敗,UI 會收到 internal。請見管理員操作指南。

預設的 delegate 設定(lifetime: until-revoked)使用這些方法。

方法權限參數用途
delegate.statusauthenticated無狀態(ready、disabled、needs-admin-approval、blocked、needs-scope-confirmation)、生命週期、目的地與範圍。
delegate.destinationauthenticatedkey單一目的地的狀態:active、missing、reselection-required、needs-scope-confirmation 或 disabled。
delegate.select_destinationauthenticatedkey、path讓使用者為目的地選一個資料夾。會檢查寫入權限,然後儲存授權。
delegate.move_from_stagingauthenticateddelegation_id、job_id、staging、name、size,可選 conflict把完成的檔案從暫存區移到選定的資料夾。name 可以包含資料夾,例如 Album/CD1/01.flac;conflict 為 fail(預設)、overwrite 或 rename。
delegate.operations.getauthenticateddelegation_id、job_id移動的狀態。
delegate.operations.cancelauthenticateddelegation_id、job_id取消移動。
delegate.operations.listauthenticated無(送出 {})列出移動。
delegate.example.exportauthenticatedkey、job_id稍後儲存面板使用的範例匯出。
delegate.disable、delegate.enableadministrators無關閉或開啟這項整合。兩者都會結束所有授權。
delegate.auditauthenticated無套件的事件。管理員看得到全部,其他人只看得到自己的。最多 256 筆。

使用 delegate 且沒有 lifetime 時,會改用限時方法:delegate.create(job_id、ops、path、ttl_seconds 為 1 到 3600)、delegate.list、delegate.revoke、delegate.jobs.submit、delegate.jobs.list 與 delegate.jobs.cancel。全部都是 authenticated。delegate.* 方法需要 DSM 工作階段 cookie 與 token,否則會回傳 session_required。請見 Delegate 指南。

App 後端以 executor 協定 v1 的這些操作與 executor 溝通;下表由 SDK 的操作 schema 產生。以 ? 結尾的參數為選用。需要 DSM 工作階段的操作在沒有工作階段時以 AUTH_DENIED 拒絕。請見 Executor 協定錯誤碼。

操作DSM 工作階段參數
delegate.audit必要—
delegate.create必要job_id?, ops, scope, path, ttl_seconds?, destination?, lifetime?
delegate.disable必要—
delegate.enable必要—
delegate.list必要—
delegate.revoke選用delegation_id, job_id?
files.cancelOperation選用delegation_id, job_id
files.checkPermission選用delegation_id, job_id, path
files.copy選用delegation_id, job_id, path, dest_dir, conflict?
files.createFolder選用delegation_id, job_id, path, name, parents?
files.delete選用delegation_id, job_id, path, recursive?, permanent?
files.info選用delegation_id, job_id, path
files.list選用delegation_id, job_id, path
files.move選用delegation_id, job_id, path, dest_dir, conflict?
files.moveFromStaging選用delegation_id, job_id, staging, name, size, conflict?
files.operationStatus選用delegation_id, job_id
files.read選用delegation_id, job_id, path, max_bytes?
files.rename選用delegation_id, job_id, path, name
files.taskCancel選用delegation_id, job_id, task_id
files.taskStatus選用delegation_id, job_id, task_id
files.write選用delegation_id, job_id, staging, dest_dir, name, conflict?
portal.register必要—
portal.unregister必要—
root.jobs.get必要job_id
root.jobs.list必要—
root.jobs.stop必要job_id
root.run必要name, params?
root.start必要name, params?
status選用—

route 在 backend/internal/app/routes.go。在那裡註冊處理函式,然後在 permissions.json 為該方法設定權限。

// routes.go: add to the list in Routes
api.HandleRequest("reports.list", cfg.listReports),
reports.go
package app
import (
"context"
"encoding/json"
"net/http"
"github.com/synopackageland/syno-pkg-land-sdk/api"
"github.com/synopackageland/syno-pkg-land-sdk/filestation"
)
func (cfg Config) listReports(ctx context.Context, caller api.Caller, r *http.Request, params json.RawMessage) (any, error) {
var in struct {
Folder string `json:"folder"`
}
if err := decodeParams(params, &in); err != nil {
return nil, err
}
if in.Folder == "" {
return nil, api.BadRequest("folder is required")
}
return cfg.SessionFiles.List(ctx, caller, r, in.Folder, filestation.ListOptions{Limit: 50})
}
{
"schema": 1,
"default": "administrators",
"methods": { "reports.list": "authenticated" }
}
函式處理函式簽章用途
api.Handle(method, h)func(ctx, caller api.Caller, params json.RawMessage) (any, error)大多數 route。
api.HandleRequest(method, h)在 ctx 之後加上 *http.Request。以使用者工作階段呼叫 File Station 或 executor 的 route。
api.HandleResponse(method, h)加上 http.ResponseWriter 與 *http.Request。回傳 error。設定 cookie 或自行寫入回應的 route。
api.HandleStream(method, h)func(ctx, caller, w, r) error上傳與下載。方法來自查詢字串,內容不是 JSON。

處理函式的回傳值會成為 data。route 的權限永遠不是由你使用的函式決定,而是由 permissions.json 決定。

項目用途
caller.User()DSM 使用者名稱。
caller.Admin()DSM 管理員為 true。
caller.Authenticated()有使用者登入時為 true。
api.RequireAdmin(caller)呼叫者不是管理員時回傳 admin_required。用它保留共用 route 的一部分。
api.BadRequest(msg)回傳帶有你訊息的 bad_request。
&api.Error{Code: "…", Message: "…"}回傳你自己的錯誤碼。UI 看得到。
其他任何 error記錄在 NAS 上,並以 internal 回傳給 UI。

擁有者請從 caller.User() 取得。不要信任 params 裡送來的使用者名稱。

你需要使用
以使用者權限存取檔案cfg.SessionFiles.List、Info、CreateFolder、Upload 與 Download。每個都接受 ctx、caller 與請求 r。需要 files。
同時適用於即時請求與 delegate 工作的介面filestation.RequestContext{Caller, Request, Service}.Files(),提供 List、Info、CreateFolder、CheckPermission 與 Write。需要 delegate。
delegate 工作的檔案操作delegate.JobContext.Files() 另外提供 CreateFolderAll、Rename、Read,以及任務操作 Copy、Move、Delete、TaskStatus 與 CancelTask。每個都需要在 delegate 的 operations 中宣告對應操作。見 Delegate 指南。
背景工作從 UI 呼叫 bg.* 方法。worker 是固定的,會計算 SHA-256。請見背景工作指南。
之後在沒有使用者工作階段時儲存檔案Delegate。使用者在場時呼叫 service.Destination(ctx, caller, req, "save"),保留 Destination.ID,之後呼叫 service.MoveFromStaging(ctx, MoveParams{DelegationID, JobID, Staging, Name, Size})。
root 操作管理員的 UI 以腳本名稱呼叫 root.run。把腳本放在 root/<name>.sh。產生的 UI 都不會呼叫它,請自己呼叫 ctx.call('root.run', {name})。

ctx 是 DSM 視窗傳給 UI 的 context。其他輔助函式來自 @synopackageland/sdk(headless,不含 Vue)與 @synopackageland/sdk/vue(Vue 元件與 composable;@synopackageland/sdk/vue/style.css 匯入一次)。其版本必須等於 backend/go.mod 的 SDK 版本,否則 check 回報 SDK_VERSION_MISMATCH。@synopackageland/ui 只有視覺元件,沒有後端用戶端。

輔助函式位置用途
ctx.call(method, params)ctx(所有 UI)呼叫後端方法。以 data 完成,以 {code, message} 拒絕。
ctx.localectxDSM 語言,例如 en 或 zh-TW。
ctx.reopen(fn)ctx視窗再次顯示時執行 fn。回傳一個用來移除它的函式。
ctx.hostctx視窗與檔案管理員動作:setTitle、openApp、openURL、openFileManager、revealFile、subscribe。
ctx.userctx來自 DSM 的 {name, isAdmin}。只用來隱藏控制項,存取權由後端決定。
ctx.filesctx檔案傳輸用的 {endpoint, token}。App 有 files 時才存在。
ctx.portalctxstatus()、apply(alias)、disable()、openControlPanel()、mountPanel(el)。App 宣告 portal 時才存在。
ctx.executorctx管理員核准:status()、authorize(password, scope?)、control(action)。有 rootOps 或 delegate 時才存在。
ctx.t(key, params)ctx(DSM 視窗)來自 i18n/messages 的翻譯文字。
createNasProvider(ctx)@synopackageland/sdk供選擇器使用的檔案 provider:shares、list、info、createFolder、upload、download。
createSession(ctx)@synopackageland/sdk/vue登入工作階段的狀態與呼叫:login、bootstrap、logout、call。
createBackgroundSaveFacade(ctx)@synopackageland/sdk為稍後儲存面板包裝 delegate.* 方法。
FilesPage、FileBrowser、NasPicker@synopackageland/sdk/vue用來瀏覽並選擇檔案與資料夾的 Vue 元件。
LoginPage@synopackageland/sdk/vueVue 登入表單。需要 https:。
BackgroundPanel@synopackageland/sdk/vue以 bg.browse 為基礎的工作 Vue 面板。
ExecutorSettings@synopackageland/sdk/vue管理員核准背景存取的 Vue 面板。
ExecutorApproval@synopackageland/sdk/vue在 executor 核准前接管 App 的頁面。加上 preload 時,頁面在第一次讀取狀態期間先隱藏掛載,自己的讀取與核對並行;狀態為 ready 就顯示同一個實例,其他狀態則丟棄。
useExecutorPreload()@synopackageland/sdk/vue頁面預載期間為 true。狀態不是 ready 時,它會在頁面卸載前就變成 false,所以 false 不代表頁面已顯示:要開 teleport 的對話框或 toast,請用 watchPostEffect。AuthorizationGate 會自行等待。
PortalSettings@synopackageland/sdk/vue入口網站別名的 Vue 面板。
// A Vue component with ctx as a prop
const list = await ctx.call<{ files: { name: string; isdir: boolean }[] }>('reports.list', {
folder: '/volume1/reports',
})
try {
await ctx.call('greeting.set', { text: 'Hello' })
} catch (e) {
const code = (e as { code?: string }).code // for example "admin_required"
}
限制值
請求內容1 MiB
單一請求的時間20 秒
permissions.json 的方法數1024,檔案最大 64 KiB
清單頁100 筆
上傳大小16 GiB
App 登入工作階段最長 15 分鐘
登入嘗試每個帳號每分鐘 5 次,每個位址每分鐘 20 次