SealSkin

admin

Administrator endpoints: users, groups, stores, installed apps, templates.

attributelogger
= logging.getLogger(__name__)
attributestatus_router
= APIRouter(route_class=EncryptedRoute)
attributerouter
= APIRouter(prefix='/api/admin', dependencies=[Depends(verify_admin), Depends(routing.announce_changes)], route_class=EncryptedRoute)
attributetemplate_router
= APIRouter(prefix='/api/admin', dependencies=[Depends(verify_template_editor), Depends(routing.announce_changes)], route_class=EncryptedRoute)
func_gpu_list() -> list[GPUInfo]

Return the GPUs sessions can request now, as API models.

Returns

list[app.models.GPUInfo]
funcadmin_status(user=Depends(verify_token)) -> dict[str, Any]

Return the caller's role, settings, and host statistics.

provider_groups are the groups the identity provider or proxy named, expires is when a web sign-in ends by the server's own clock, and storage_used the bytes under the user's storage on this node, for a user with persistent storage.

paramuserdict[str, Any]
= Depends(verify_token)

Returns

dict[str, typing.Any]
funcget_management_data() -> dict[str, Any]

Return users, groups, and server details for the dashboard.

Returns

dict[str, typing.Any]
func_require_safe_name(name, kind) -> str

Validate a store or template name for use in file paths.

paramnamestr
paramkindstr

Returns

str
funcget_app_stores() -> list[AppStore]

List configured app stores.

Returns

list[app.models.AppStore]
funcadd_app_store(decrypted_body=Depends(get_decrypted_request_body)) -> AppStore

Add an app store.

paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

app.models.AppStore
funcdelete_app_store(store_name) -> Response

Remove an app store.

paramstore_namestr

Returns

fastapi.Response
funcget_available_apps(store_name, url=None, refresh=False) -> list[dict[str, Any]]

Return the apps published by a configured store (cached unless refresh).

The store is fetched from the URL saved with it; a url query parameter is accepted for older clients but must match that saved URL.

paramstore_namestr
paramurlstr | None
= None
paramrefreshbool
= False

Returns

list[dict[str, typing.Any]]
func_catalog_status(catalog) -> ProotCatalogStatus

Attach this node's sync state to a catalog.

paramcatalogProotCatalog

Returns

app.models.ProotCatalogStatus
func_catalog_from(body, catalog_id, revision) -> ProotCatalog

Validate the catalog the admin UI sent, without repeats among its apps.

parambodydict[str, Any]
paramcatalog_idstr
paramrevisionint

Returns

app.models.ProotCatalog
funclist_proot_catalogs() -> list[ProotCatalogStatus]

List the PRoot Apps catalogs with the state of this node's copy of each.

Returns

list[app.models.ProotCatalogStatus]
funclist_proot_remote(remote, refresh=False) -> list[ProotRemoteApp]

Return the apps a PRoot Apps remote publishes (see prootapps.Remote).

paramremotestr
paramrefreshbool
= False

Returns

list[app.models.ProotRemoteApp]
funccreate_proot_catalog(decrypted_body=Depends(get_decrypted_request_body)) -> ProotCatalogStatus

Create a catalog; every node starts fetching its apps.

paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

app.models.ProotCatalogStatus
funcupdate_proot_catalog(catalog_id, decrypted_body=Depends(get_decrypted_request_body)) -> ProotCatalogStatus

Replace a catalog's name and apps; every node brings its copy along.

paramcatalog_idstr
paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

app.models.ProotCatalogStatus
funcrefresh_proot_catalog(catalog_id) -> ProotCatalogStatus

Fetch the catalog's apps again now, on every node, where their packages changed.

paramcatalog_idstr

Returns

app.models.ProotCatalogStatus
funcdelete_proot_catalog(catalog_id) -> Response

Delete a catalog; every node removes its copy. Users assigned to it keep the setting, which then does nothing.

paramcatalog_idstr

Returns

fastapi.Response
func_save_logo(app_id, logo) -> str | None

Persist a base64 logo as a PNG icon and return the icon URL.

paramapp_idstr

App the icon belongs to.

paramlogostr | None

Base64 image data, an address the server already serves, a web address, or None.

Returns

str | None

/api/app_icon/<id> when data was saved, otherwise logo unchanged.

func_normalise_scripts(provider_config) -> None

Turn empty autostart script strings into None in place.

paramprovider_configdict[str, Any]

Returns

None
func_with_status(app) -> InstalledAppWithStatus

Attach image metadata to an installed app.

paramappInstalledApp

Returns

app.models.InstalledAppWithStatus
funclist_installed_apps() -> list[InstalledAppWithStatus]

List installed apps with image status.

Returns

list[app.models.InstalledAppWithStatus]
funcinstall_app(decrypted_body=Depends(get_decrypted_request_body)) -> InstalledApp

Install an app from a store entry sent by the admin UI.

paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

app.models.InstalledApp
funcupdate_installed_app(app_id, decrypted_body=Depends(get_decrypted_request_body)) -> InstalledApp

Replace an installed app with a full definition.

paramapp_idstr
paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

app.models.InstalledApp
funcpatch_installed_app(app_id, decrypted_body=Depends(get_decrypted_request_body)) -> InstalledApp

Partially update an installed app.

Record fields (users, groups, app_template, auto_update, home_directories) are applied directly; any other InstalledApp field is merged into the record's overrides.

paramapp_idstr
paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

app.models.InstalledApp
funcdelete_installed_app(app_id) -> Response

Uninstall an app (and purge a meta-app's icon and home template).

paramapp_idstr

Returns

fastapi.Response
funccheck_app_update(app_id) -> ImageUpdateCheckResponse

Compare the local image digest with the registry.

paramapp_idstr

Returns

app.models.ImageUpdateCheckResponse
funcpull_latest_app_image(app_id) -> ImagePullResponse

Pull the latest image of an app and refresh its autostart cache.

paramapp_idstr

Returns

app.models.ImagePullResponse
funccreate_meta_app(decrypted_body=Depends(get_decrypted_request_body)) -> InstalledApp

Create a meta-app: a copy of an installed app with its own home template.

paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

app.models.InstalledApp
func_lab_session(username) -> tuple[str, dict[str, Any]] | None

Return the App Laboratory session an administrator has open on this node, if any.

paramusernamestr

Returns

tuple[str, dict[str, typing.Any]] | None
funclab_session(auth_user=Depends(verify_admin)) -> dict[str, Any]

Return the caller's open App Laboratory session, which no session list shows.

paramauth_userdict[str, Any]
= Depends(verify_admin)

Returns

dict

{"session": null}, or the session with app_id, app_name,

func_measure(path) -> dict[str, int]

Return the file count and size of a directory.

parampathstr

Returns

dict[str, int]
funcclose_lab_session(progress_id='', auth_user=Depends(verify_admin)) -> dict[str, Any]

Stop the caller's App Laboratory session, which keeps what it changed as the meta-app's template.

With progress_id, a UUID the client chose, the closing reports its stages to GET /api/launch/progress/{progress_id}: stopping the session, then saving, which measures the template, then ready with the template's files and bytes.

paramprogress_idstr
= ''
paramauth_userdict[str, Any]
= Depends(verify_admin)

Returns

dict

{"files": n, "bytes": n} of the template kept, zeros when no

funclaunch_meta_for_customization(decrypted_body=Depends(get_decrypted_request_body), auth_user=Depends(verify_admin)) -> dict[str, str]

Launch a meta-app with its home template mounted read-write.

An administrator of a web sign-in has one such session at a time: a second is refused with 409 until the first is closed.

paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)
paramauth_userdict[str, Any]
= Depends(verify_admin)

Returns

dict[str, str]
func_run_option_settings(template_settings) -> dict[str, str]

A template's DOCKER_* and KUBERNETES_* settings, as text.

They become container run options (privileged mode, devices, namespaces, binds) or the pod template a session starts from, and so carry authority over the Docker host or the namespace. Text, since a hand-edited template may hold them as YAML booleans or numbers.

paramtemplate_settingsdict[str, Any]

Returns

dict[str, str]
func_identity_settings(template_settings) -> dict[str, str]

A template's settings that name the session's identity (RESERVED_ENV), as text.

paramtemplate_settingsdict[str, Any]

Returns

dict[str, str]
funceditor_settings(stored, submitted) -> dict[str, Any]

Return the settings a template editor who is not an administrator may save.

The stored template's DOCKER_* and KUBERNETES_* run options and identity variables stay as they are: one left out keeps its value, and one added or changed is refused.

paramstoreddict[str, Any]
paramsubmitteddict[str, Any]

Returns

dict[str, typing.Any]
funcget_app_templates() -> list[dict[str, Any]]

List app templates.

Returns

list[dict[str, typing.Any]]
funcsave_app_template(decrypted_body=Depends(get_decrypted_request_body), user=Depends(verify_template_editor)) -> AppTemplate

Create or replace a template.

A template editor who is not an administrator keeps the template's DOCKER_* and KUBERNETES_* settings and the session's identity variables as they are (editor_settings). A PodTemplate the template names must be a valid name.

paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)
paramuserdict[str, Any]
= Depends(verify_template_editor)

Returns

app.models.AppTemplate
funcdelete_app_template(template_name, user=Depends(verify_template_editor)) -> Response

Delete a user template; one with DOCKER_* or KUBERNETES_* settings only as an administrator.

paramtemplate_namestr
paramuserdict[str, Any]
= Depends(verify_template_editor)

Returns

fastapi.Response
funcget_all_sessions(request, user=Depends(verify_admin)) -> list[UserSessionList]

List every session on every node grouped by user.

paramrequestRequest
paramuserdict[str, Any]
= Depends(verify_admin)

Returns

list[app.models.UserSessionList]
funcstop_any_session(session_id) -> Response

Stop any user's session.

paramsession_idstr

Returns

fastapi.Response
funccreate_admin(decrypted_body=Depends(get_decrypted_request_body)) -> dict[str, Any]

Create a key-file administrator; refused where key files are off, since administrators then come from the provider.

paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

dict[str, typing.Any]
funcdelete_admin(username) -> Response

Delete an administrator.

paramusernamestr

Returns

fastapi.Response
funccreate_user(decrypted_body=Depends(get_decrypted_request_body)) -> dict[str, Any]

Create a user; with key files off, a sign-in-only user, whatever key the request carries.

paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

dict[str, typing.Any]
funcupdate_user(username, decrypted_body=Depends(get_decrypted_request_body)) -> dict[str, Any]

Replace a user's settings.

paramusernamestr
paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

dict[str, typing.Any]
funcapprove_user(username, decrypted_body=Depends(get_decrypted_request_body)) -> dict[str, Any]

Let a held user in, placed in the groups the body names; none leaves them in default.

paramusernamestr
paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

dict[str, typing.Any]
funcdelete_user(username) -> Response

Delete a user and their storage.

paramusernamestr

Returns

fastapi.Response
func_require_storage_user(username) -> None

Ensure a user exists and has persistent storage enabled.

paramusernamestr

Returns

None
func_require_admin_user(username) -> None

Ensure username is an administrator.

paramusernamestr

Returns

None
funclist_user_home_dirs(username) -> dict[str, list[str]]

List a user's home directories.

paramusernamestr

Returns

dict[str, list[str]]
funccreate_user_home_dir(username, decrypted_body=Depends(get_decrypted_request_body)) -> dict[str, str]

Create a home directory for a user.

paramusernamestr
paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

dict[str, str]
funcdelete_user_home_dir(username, home_name) -> Response

Delete a user's home directory.

paramusernamestr
paramhome_namestr

Returns

fastapi.Response
funclist_admin_home_dirs(username) -> dict[str, list[str]]

List an administrator's home directories.

paramusernamestr

Returns

dict[str, list[str]]
funccreate_admin_home_dir(username, decrypted_body=Depends(get_decrypted_request_body)) -> dict[str, str]

Create a home directory for an administrator.

paramusernamestr
paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

dict[str, str]
funcdelete_admin_home_dir(username, home_name) -> Response

Delete an administrator's home directory.

paramusernamestr
paramhome_namestr

Returns

fastapi.Response
funccreate_group(decrypted_body=Depends(get_decrypted_request_body)) -> dict[str, Any]

Create a group.

paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

dict[str, typing.Any]
funcupdate_group(group_name, decrypted_body=Depends(get_decrypted_request_body)) -> dict[str, Any]

Replace a group's settings; default has none to replace.

paramgroup_namestr
paramdecrypted_bodydict[str, Any]
= Depends(get_decrypted_request_body)

Returns

dict[str, typing.Any]
funcdelete_group(group_name) -> Response

Delete a group; default cannot be.

paramgroup_namestr

Returns

fastapi.Response