mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 06:05:08 +00:00
Plug-ins: only an approval records a grant, and installs need one
registry::grant takes a GrantToken, which the engine makes after a person's approval and when it loads grants.json. registry::install, install_bytes and folder loads refuse a module that lists permissions no recorded grant gives this very module (Error::NeedsApproval), and leave the plug-in under its id and the revision as they were. A folder load's approve callback only narrows what installs. A module without permissions, or with an empty list, installs as before. A folder load in a session with a plug-in store records the store's grant for each module it approves, so those modules still load. docs/plugins.md says what the approval does not protect against: native code linked into the app, and another program running as the same user, which can edit the Plug-ins folder and its unsigned grants.json.
This commit is contained in:
@@ -52,7 +52,7 @@ use vectorcraft_plugins::{Budget, Command, Kind, Plugin, effect, export, objects
|
||||
|
||||
use super::{CommandSpec, EngineError, NodeId, Result, Session, always, bad, cmd, has_doc, ids_param, str_param, switch_or};
|
||||
|
||||
use vectorcraft_plugins::permissions::{self, Grant, Permission};
|
||||
use vectorcraft_plugins::permissions::{self, Grant, GrantToken, Permission};
|
||||
|
||||
/// What a plug-in error looks like to the user. A run the caller cancelled changed nothing.
|
||||
fn err(e: vectorcraft_plugins::Error) -> EngineError {
|
||||
@@ -748,7 +748,7 @@ fn install(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let mut stored = (previous.is_ok() || !m.asks_permissions()) && s.store_plugin(plugin.id(), &bytes);
|
||||
if m.asks_permissions() {
|
||||
let g = Grant { id: m.id.clone(), hash: plugin.hash().to_string(), permissions: wanted };
|
||||
registry::grant(g.clone());
|
||||
registry::grant(GrantToken::after_engine_approval(g.clone()));
|
||||
if stored && !s.store_grant(&m.id, Some(g)) {
|
||||
s.put_back_plugin(plugin.id(), previous.ok().flatten().as_deref());
|
||||
stored = false;
|
||||
@@ -786,7 +786,8 @@ fn install(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
if changed {
|
||||
s.store_disabled_plugins();
|
||||
}
|
||||
let mut v = describe_installed(®istry::install(plugin));
|
||||
let installed = registry::install(plugin).map_err(err)?;
|
||||
let mut v = describe_installed(&installed);
|
||||
if !unknown.is_empty() {
|
||||
v["unknownCommands"] = json!(unknown);
|
||||
}
|
||||
@@ -885,7 +886,7 @@ fn load_folder(s: &Session, folder: &str) -> Value {
|
||||
None if crate::file_access::current().is_none() => Ok(()),
|
||||
None => Err(format!("automation path rejected: {} isn't valid text", f.display())),
|
||||
};
|
||||
match registry::load_folder_where(std::path::Path::new(folder), allow, s.plugin_approver()) {
|
||||
match registry::load_folder_where(std::path::Path::new(folder), allow, s.plugin_folder_approver()) {
|
||||
Ok(r) => {
|
||||
for id in &r.loaded {
|
||||
s.attach_plugin_storage(id);
|
||||
|
||||
Reference in New Issue
Block a user