Vai al contenuto principale

Plugin Permissions

Ogni plugin di Owncast viene eseguito in una sandbox senza accesso implicito a nulla al di fuori del plugin stesso. Per fare del lavoro utile (leggere la chat, pubblicare sul fediverse, recuperare un URL, scrivere in uno store chiave-valore) il tuo plugin richiede all'host tramite i metodi owncast.*. Almost every one of those methods is gated by a permission you declare in your manifest. The exceptions are a handful of ambient methods that reach nothing sensitive and need no permission: owncast.log.*, owncast.timer.*, reading your own bundled assets, and owncast.config.get.

Plugin permissions require Owncast v0.3.0

Plugins require Owncast 0.3.0 or later.

Quando un amministratore installa un plugin, la scheda Permessi nella pagina dei dettagli del plugin elenca esattamente cosa ha richiesto il plugin, in linguaggio semplice. Questa è la soglia di fiducia: un amministratore può installare un plugin di terze parti senza dover controllare ogni riga di codice, poiché il manifesto è il limite superiore su ciò che il plugin può fare.

La scheda dei Permessi nella pagina dei dettagli di un plugin, che elenca ciascun permesso richiesto con una descrizione in linguaggio semplice
Owncat informs youDisponibile in ogni SDK

Gli identificatori dei permessi e il modello di fiducia qui sotto sono gli stessi indipendentemente da quale SDK utilizzi. I metodi owncast.* sono qui menzionati con i loro nomi canonici. Per la correttezza ortografica nella tua lingua, vedi il riferimento JavaScript o Python SDK.

Come funziona

  1. Dichiari i permessi in plugin.manifest.json:

    { "permissions": ["chat.send", "storage.kv"] }
  2. L'amministratore li esamina quando abilita. La pagina dei dettagli del plugin di Owncast elenca ciascun permesso con una descrizione leggibile dall'utente.

  3. L'host li applica in fase di esecuzione. Calling owncast.chat.send(...) without chat.send in your manifest never reaches Owncast: the host logs the denial and the call does nothing. Mutating calls that report an outcome raise an error (moderation, users.register, auth.grantSession, kv.set, videoConfig.write, actions.add, actions.clear, and every sql method), readers return an empty or zero value, and calls that return nothing become silent no-ops. fs.write, fs.delete, and storage.upload report failure in their return value instead of raising.

  4. L'host rileva le deviazioni. Il tuo plugin costruito dichiara i permessi che utilizza in fase di esecuzione. L'host confronta questo con il manifesto e rifiuta di caricare il plugin se l'esecuzione richiede più di quanto concesso dal manifesto. Non puoi ottenere accesso extra sostituendo il file del plugin in un secondo momento.

Ri-approvazione quando i permessi si espandono

If you ship an update that asks for more permissions than the admin previously approved, the old approved version keeps running (it holds only the approved permissions) and the new package waits as pending. The plugin list shows a "needs re-approval" badge. The admin reviews the new permissions in the Permissions tab and clicks Approve to accept the expanded set and load the update. Ridurre i permessi è silenzioso.

Le capacità effettive di un plugin installato non crescono mai senza che l'amministratore dica di sì di nuovo.

Riferimento ai permessi

chat.send

Concede:

  • owncast.chat.send(text): invia come identità bot del plugin
  • owncast.chat.sendAction(text): invia un messaggio "/me"
  • owncast.chat.sendTo(clientId, text): messaggio privato a un client connesso
  • owncast.chat.replyTo(msg, text): whisper a reply back to whoever sent a chat message (sugar over sendTo)
  • owncast.chat.system(body): invia un messaggio di sistema senza identità utente, visualizzato come annuncio del server (il corpo è HTML)

I messaggi attraversano il normale flusso di chat di Owncast (filtro, limiti di velocità, persistenza, moderazione). I plugin non possono inviare con nomi arbitrari o impersonare utenti reali.

chat.history

Concede:

  • owncast.chat.history(limit?): legge i messaggi recenti della chat
  • owncast.chat.clients(): elenca i client della chat connessi

Solo per lettura.

chat.moderate

Concede:

  • owncast.chat.deleteMessage(messageId): nasconde un messaggio dai visualizzatori
  • owncast.chat.kick(clientId): disconnette un client della chat

chat.filter

Concede la possibilità di definire filterChatMessage(msg): vedere ogni messaggio di chat prima che venga trasmesso, con la possibilità di riscriverlo o scartarlo.

Il filtraggio avviene in tempo reale su ogni messaggio di chat, quindi l'amministratore deve vedere questo segnalato esplicitamente. L'host rifiuta di caricare se un plugin definisce filterChatMessage senza dichiarare questo permesso.

users.read

Grants:

  • owncast.users.list(): legge l'elenco degli utenti della chat
  • owncast.users.get(id): legge un singolo record utente

users.moderate

Concede:

  • owncast.users.setEnabled(id, enabled, reason?): abilita o disabilita un utente
  • owncast.users.banIP(ip): banna un IP dall'unirsi alla chat

users.register

Grants owncast.users.register({ authId, displayName?, scopes?, profileUrl?, handle?, public? }): find or create an authenticated Owncast user for an external identity and return its userId. The authId is a stable, provider-scoped identifier such as "github:583231". Pass it raw, without prefixing your slug. The host records the slug separately and scopes every lookup to that pair, so two plugins cannot collide with or spoof each other's users.

The optional profileUrl, handle, and public fields attach a verified external identity. The profile URL must be empty or an absolute HTTP(S) URL. Set public to true only after the viewer opts into public display. These profile fields are captured on the first registration.

Questo è il modo in cui un plugin trasforma un accesso di terze parti (OAuth, Discord, una password condivisa) in un vero utente di Owncast con un'identità di chat autenticata. Di per sé non né delimita il sito né emette una sessione: abbinalo a auth.gate per costruire un gate di accesso, o usalo da solo per coniare identità di chat verificate.

auth.gate

Concede il gate di autenticazione dell'utente:

  • owncast.auth.grantSession({ userId, ttl? }): issue a signed session for an already-registered user (see users.register)
  • owncast.auth.endSession(): cancella la sessione dell'utente corrente (disconnetti)
  • il gestore opzionale onAuthCheck: rivalida la sessione di un utente ad ogni caricamento di pagina

Un plugin che possiede auth.gate è un fornitore di identità. While it is enabled, viewers must authenticate through it before they can reach the page, chat, or the API. The operator selects one cumulative access mode on the plugin's Authentication tab to decide whether Owncast-hosted video and stream status also require a session. Solo un plugin auth.gate può essere attivato alla volta, e il gate fallisce in modo sicuro: se il plugin non è disponibile, gli spettatori non possono entrare piuttosto che essere accolti. Vedi Autenticazione per il modello completo.

storage.kv

Grants owncast.kv.get(key), owncast.kv.set(key, value), and the JSON helpers owncast.kv.getJSON(key, fallback?) and owncast.kv.setJSON(key, value): a per-plugin namespaced key/value store. I plugin non possono leggere le chiavi degli altri.

Lo stato persiste attraverso i ricaricamenti e i riavvii dell'host.

storage.upload

Grants owncast.storage.upload(name, data): upload a file to Owncast's public file area and get back a URL. Utile per badge, immagini generate dinamicamente, allegati ai post del fediverse.

storage.fs

Grants owncast.fs.*: a private, sandboxed filesystem at data/plugin-storage/<your-slug>/files/ that your plugin can read, write, list, and delete within. Utile per cache, file di dati generati, log di tipo append, o qualsiasi cosa tu abbia bisogno di mantenere come file reali piuttosto che stringhe chiave/valore.

A differenza di storage.upload, questi file rimangono lato server: non vengono mai serviti tramite HTTP. Ogni percorso è limitato alla directory del tuo plugin: un plugin non può leggere i file di un altro plugin o fuggire dalla sua sandbox (i percorsi ../ e assoluti vengono collassati all'interno).

storage.sql

Grants owncast.sql.*: one private SQLite database per plugin, at data/plugin-storage/<your-slug>/db/plugin.db. owncast.sql.exec(sql, params?) runs statements, owncast.sql.query(sql, params?) returns matching rows, and owncast.sql.queryRow(sql, params?) reads a single row. Reach for this instead of storage.kv when you need to sort, filter, or aggregate rather than just remember a value. See owncast.sql.* for the methods in both languages, the per-call limits, and the SQL the host refuses.

The database is private to your plugin and separate from Owncast's own database. The storage.fs sandbox is rooted at files/, so db/ is not a path owncast.fs.* refuses but one it cannot express, and the filesystem quota walk covers files/ only, so the two quotas stay independent: the database has its own 128 MiB cap, and files written through storage.fs count against a separate 256 MiB quota.

Plugin databases are not included in Owncast's database backups, so treat the contents as rebuildable or export what matters yourself. SQL data is retained when a plugin is uninstalled, the same as its config and its storage.fs files, so a reinstall finds its tables where it left them. An admin who wants the space back deletes data/plugin-storage/<your-slug>/.

network.fetch

Concede owncast.http.fetch(url, opts?): HTTP in uscita sincrono.

Richiede una lista di network.allowedHosts nel manifesto. L'host rifiuta di caricare se network.fetch è concesso senza una lista di autorizzazione. Ogni chiamata è controllata contro la lista di autorizzazione. Gli host che non corrispondono restituiscono un errore prima che qualsiasi byte lasci il server.

{
"permissions": ["network.fetch"],
"network": { "allowedHosts": ["api.discord.com", "*.weather.com"] }
}

Il carattere jolly "*" è consentito ma deve essere scritto esplicitamente affinché gli amministratori esaminando il manifesto vedano l'ambito. L'interfaccia utente dell'amministratore mostra l'intera lista di allowedHosts nella scheda Permessi accanto alla riga network.fetch, quindi un operatore del server che esamina un plugin vede esattamente quali host può raggiungere senza estrarre il .ocpkg.

events.emit

Grants owncast.events.emit(eventType, payload). Pass the receiving plugin's fully qualified <recipient-slug>.<hook> name. The host does not rewrite the emitted name. Declaring and receiving a plugin-owned custom hook does not require a permission.

http.serve

Consente al router HTTP dell'host di inviare richieste a /plugins/<your-slug>/* al tuo plugin. Questo copre sia i file statici nella tua directory public/ che le richieste dinamiche instradate al tuo gestore onHttpRequest.

Senza questo permesso, l'intero spazio URL /plugins/<your-slug>/ restituisce 404.

http.sse

Concede owncast.sse.send(channel, event, data) ed espone un endpoint di proprietà dell'host a /plugins/<your-slug>/_sse/<channel> a cui i browser si connettono con EventSource. Indipendente da http.serve. Un plugin può inviare eventi senza servire altre rotte.

server.read

Concede le API di stato di lettura e streaming:

  • owncast.stream.current(): stato di streaming live
  • owncast.stream.broadcaster(): telemetria di codifica in entrata
  • owncast.server.info(): nome del server, versione, riepilogo
  • owncast.server.socials(): link social configurati
  • owncast.server.emotes(): custom chat emotes configured on this server
  • owncast.server.federation(): impostazioni del fediverse
  • owncast.server.tags(): tag configurati

videoconfig.read

Concede owncast.videoConfig.read(): legge la configurazione di output e transcodifica (codec, livello di latenza, varianti di streaming).

videoconfig.write

Concede owncast.videoConfig.write(partial): modifica la configurazione di output video.

Alta fiducia. Le modifiche si applicano all'inizio del prossimo streaming. L'host non riavvia una trasmissione attiva. Gli amministratori dovrebbero concedere con parsimonia.

notifications.send

Concede le API di notifica del broadcaster:

  • owncast.notifications.discord(text): attraverso il webhook Discord configurato dallo streamer
  • owncast.notifications.browserPush({ title, body, url? }): to subscribed browsers
  • owncast.notifications.fediverse({ type, body, image?, link? }): fediverse-formatted notification

fediverse.inbound

Concede l'iscrizione a tutti e sette gli eventi plugin inbound del Fediverse:

  • fediverse.follow
  • fediverse.like
  • fediverse.repost
  • fediverse.quote
  • fediverse.mention
  • fediverse.reply
  • fediverse.activity

Il fediverse.activity catch-all riceve l'oggetto JSON grezzo dell'attività verificata. Funziona in aggiunta a qualsiasi evento specializzato corrispondente. Questo permesso copre solo la ricezione dell'attività. Inviare dal account Owncast richiede il separato permesso fediverse.post.

fediverse.post

Concede owncast.fediverse.post(text): pubblica un post pubblico sul fediverse dall'account di Owncast.

Alta fiducia: i post vengono effettuati con l'handle fediverse dello streamer e non possono essere revocati silenziosamente. Gli amministratori dovrebbero concedere con parsimonia.

ui.modify

Concede la possibilità di posizionare l'interfaccia utente all'interno del proprio chrome di Owncast:

  • Dichiarare manifest.actions (pulsanti di azione sotto lo streaming).
  • Chiamare owncast.actions.add(...) / .clear() in fase di esecuzione.
  • Dichiarare manifest.styles (CSS in linea nella pagina del visualizzatore).
  • Dichiarare manifest.scripts (JavaScript in linea nella pagina del visualizzatore).
  • Dichiarare manifest.extraPageContent (un blocco HTML inserito nell'area di contenuto extra del visualizzatore).
  • Dichiarare manifest.tabs (schede aggiuntive nella riga delle schede della pagina del visualizzatore).
  • Implementare un gestore onPageStyles o onPageScripts (CSS o JavaScript restituiti al momento della richiesta, senza campo di manifesto).

Senza questo permesso, i manifesti che dichiarano uno di quei campi vengono rifiutati al caricamento. I gestori onPageStyles e onPageScripts non hanno campo di manifesto, quindi non vengono rifiutati al caricamento. L'host semplicemente non li chiama a meno che il plugin non possieda ui.modify. Ognuna di queste si inserisce nella pagina del visualizzatore piuttosto che rimanere nello spazio URL del plugin, quindi l'amministratore deve vedere il permesso per comprendere che il plugin interviene nell'interfaccia utente dell'host.

Nessuno dei quattro campi di iniezione nel visualizzatore richiede http.serve, e nemmeno i due gestori. L'host legge ogni file dalla directory assets/ del plugin (non da un URL), oppure chiama il gestore, e inserisce il resultato nelle risposte config / custom-JS esistenti, quindi ui.modify da solo è sufficiente.

PermessoConcessioni
chat.sendowncast.chat.send, .sendAction, .sendTo, .replyTo, .system
chat.historyowncast.chat.history, .clients
chat.moderateowncast.chat.deleteMessage, .kick
chat.filterIscriviti a filterChatMessage (leggi, modifica o elimina ogni messaggio di chat).
users.readowncast.users.list, .get
users.moderateowncast.users.setEnabled, .banIP
users.registerowncast.users.register: trova o crea un utente autenticato per un'identità esterna
auth.gateowncast.auth.grantSession, .endSession, e il gestore onAuthCheck: essere il cancello di autenticazione del sito
storage.kvNegozio di chiavi/valori con spazio dei nomi per plugin
storage.uploadCarica file nell'area file pubblica di Owncast
storage.fsPrivate, sandboxed server-side filesystem at data/plugin-storage/<your-slug>/files/
storage.sqlPrivate per-plugin SQLite database at data/plugin-storage/<your-slug>/db/plugin.db
network.fetchHTTP in uscita. Richiede anche network.allowedHosts
events.emitEmetti eventi personalizzati per altri plugin
http.serveServe HTTP a /plugins/<your-slug>/*
http.sseInvia eventi in tempo reale tramite owncast.sse.send e l'endpoint /_sse/
server.readLeggi lo stato del stream, la configurazione del server, codifica dei telemetria
videoconfig.readLeggi la configurazione di output/transcodifica
videoconfig.writeModifica la configurazione di output video (applicata all'avvio del prossimo stream)
notifications.sendInvia notifiche Discord, push del browser o notifiche del fediverse
fediverse.inboundIscriviti a tutti e sette gli eventi in ingresso: fediverse.follow, .like, .repost, .quote, .mention, .reply, e .activity
fediverse.postInvio pubblico al fediverse (con limitazione di rate)
ui.modifyAggiungi pulsanti di azione o schede al chrome del visualizzatore di Owncast. CSS, JavaScript o HTML in linea nel la pagina del visualizzatore

Principio del minimo privilegio

Dichiarare solo ciò che utilizzi effettivamente. Più è ristretto il tuo manifesto, più semplice sarà la decisione di fiducia dell'amministratore. Se ti ritrovi a elencare ogni permesso, fermati e vedi se il tuo plugin dovrebbe davvero essere due plugin.

Se smetti di usare un permesso durante lo sviluppo, rimuovilo dal manifesto. La riduzione è silenziosa. Non ci sono attriti nella rimozione di voci non utilizzate.


Improve this page

See something missing or incorrect? Edit this page and improve the documentation for everyone.

Contributors to this documentation
Gabe KangasGabe Kangas
G
Gabe Kangas