mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-12-20 09:11:55 +03:00
fix(acl): command scope should not error out if missing (#8675)
* fix(acl): command scope should not error out if missing * propagate error
This commit is contained in:
parent
ec9818accb
commit
2631e97e2b
@ -2,8 +2,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::{collections::BTreeMap, ops::Deref};
|
||||||
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use state::TypeMap;
|
use state::TypeMap;
|
||||||
@ -112,9 +112,27 @@ impl<T: Debug + DeserializeOwned + Send + Sync + 'static> ScopeValue<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum OwnedOrRef<'a, T: Debug> {
|
||||||
|
Owned(T),
|
||||||
|
Ref(&'a T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Debug> Deref for OwnedOrRef<'a, T> {
|
||||||
|
type Target = T;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
match self {
|
||||||
|
Self::Owned(t) => t,
|
||||||
|
Self::Ref(r) => r,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Access scope for a command that can be retrieved directly in the command function.
|
/// Access scope for a command that can be retrieved directly in the command function.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CommandScope<'a, T: Debug + DeserializeOwned + Send + Sync + 'static>(&'a ScopeValue<T>);
|
pub struct CommandScope<'a, T: Debug + DeserializeOwned + Send + Sync + 'static>(
|
||||||
|
OwnedOrRef<'a, ScopeValue<T>>,
|
||||||
|
);
|
||||||
|
|
||||||
impl<'a, T: Debug + DeserializeOwned + Send + Sync + 'static> CommandScope<'a, T> {
|
impl<'a, T: Debug + DeserializeOwned + Send + Sync + 'static> CommandScope<'a, T> {
|
||||||
/// What this access scope allows.
|
/// What this access scope allows.
|
||||||
@ -133,22 +151,22 @@ impl<'a, R: Runtime, T: Debug + DeserializeOwned + Send + Sync + 'static> Comman
|
|||||||
{
|
{
|
||||||
/// Grabs the [`ResolvedScope`] from the [`CommandItem`] and returns the associated [`CommandScope`].
|
/// Grabs the [`ResolvedScope`] from the [`CommandItem`] and returns the associated [`CommandScope`].
|
||||||
fn from_command(command: CommandItem<'a, R>) -> Result<Self, InvokeError> {
|
fn from_command(command: CommandItem<'a, R>) -> Result<Self, InvokeError> {
|
||||||
command
|
if let Some(scope_id) = command.acl.as_ref().and_then(|resolved| resolved.scope) {
|
||||||
.acl
|
Ok(CommandScope(OwnedOrRef::Ref(
|
||||||
.as_ref()
|
|
||||||
.and_then(|resolved| resolved.scope)
|
|
||||||
.and_then(|scope_id| {
|
|
||||||
command
|
command
|
||||||
.message
|
.message
|
||||||
.webview
|
.webview
|
||||||
.manager()
|
.manager()
|
||||||
.runtime_authority
|
.runtime_authority
|
||||||
.scope_manager
|
.scope_manager
|
||||||
.get_command_scope_typed(&scope_id)
|
.get_command_scope_typed(&scope_id)?,
|
||||||
.unwrap_or_default()
|
)))
|
||||||
.map(CommandScope)
|
} else {
|
||||||
})
|
Ok(CommandScope(OwnedOrRef::Owned(ScopeValue {
|
||||||
.ok_or_else(|| InvokeError::from_anyhow(anyhow::anyhow!("scope not found")))
|
allow: Vec::new(),
|
||||||
|
deny: Vec::new(),
|
||||||
|
})))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +193,11 @@ impl<'a, R: Runtime, T: Debug + DeserializeOwned + Send + Sync + 'static> Comman
|
|||||||
fn from_command(command: CommandItem<'a, R>) -> Result<Self, InvokeError> {
|
fn from_command(command: CommandItem<'a, R>) -> Result<Self, InvokeError> {
|
||||||
command
|
command
|
||||||
.plugin
|
.plugin
|
||||||
|
.ok_or_else(|| {
|
||||||
|
InvokeError::from_anyhow(anyhow::anyhow!(
|
||||||
|
"global scope not available for app commands"
|
||||||
|
))
|
||||||
|
})
|
||||||
.and_then(|plugin| {
|
.and_then(|plugin| {
|
||||||
command
|
command
|
||||||
.message
|
.message
|
||||||
@ -183,10 +206,9 @@ impl<'a, R: Runtime, T: Debug + DeserializeOwned + Send + Sync + 'static> Comman
|
|||||||
.runtime_authority
|
.runtime_authority
|
||||||
.scope_manager
|
.scope_manager
|
||||||
.get_global_scope_typed(plugin)
|
.get_global_scope_typed(plugin)
|
||||||
.ok()
|
.map_err(InvokeError::from_error)
|
||||||
})
|
})
|
||||||
.map(GlobalScope)
|
.map(GlobalScope)
|
||||||
.ok_or_else(|| InvokeError::from_anyhow(anyhow::anyhow!("global scope not found")))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,29 +250,31 @@ impl ScopeManager {
|
|||||||
fn get_command_scope_typed<T: Send + Sync + DeserializeOwned + Debug + 'static>(
|
fn get_command_scope_typed<T: Send + Sync + DeserializeOwned + Debug + 'static>(
|
||||||
&self,
|
&self,
|
||||||
key: &ScopeKey,
|
key: &ScopeKey,
|
||||||
) -> crate::Result<Option<&ScopeValue<T>>> {
|
) -> crate::Result<&ScopeValue<T>> {
|
||||||
let cache = self.command_cache.get(key).unwrap();
|
let cache = self.command_cache.get(key).unwrap();
|
||||||
match cache.try_get() {
|
match cache.try_get() {
|
||||||
cached @ Some(_) => Ok(cached),
|
Some(cached) => Ok(cached),
|
||||||
None => match self.command_scope.get(key).map(|r| {
|
None => {
|
||||||
|
let resolved_scope = self
|
||||||
|
.command_scope
|
||||||
|
.get(key)
|
||||||
|
.unwrap_or_else(|| panic!("missing command scope for key {key}"));
|
||||||
|
|
||||||
let mut allow: Vec<T> = Vec::new();
|
let mut allow: Vec<T> = Vec::new();
|
||||||
let mut deny: Vec<T> = Vec::new();
|
let mut deny: Vec<T> = Vec::new();
|
||||||
|
|
||||||
for allowed in &r.allow {
|
for allowed in &resolved_scope.allow {
|
||||||
allow.push(serde_json::from_value(allowed.clone().into())?);
|
allow.push(serde_json::from_value(allowed.clone().into())?);
|
||||||
}
|
}
|
||||||
for denied in &r.deny {
|
for denied in &resolved_scope.deny {
|
||||||
deny.push(serde_json::from_value(denied.clone().into())?);
|
deny.push(serde_json::from_value(denied.clone().into())?);
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::Result::Ok(Some(ScopeValue { allow, deny }))
|
let value = ScopeValue { allow, deny };
|
||||||
}) {
|
|
||||||
None => Ok(None),
|
let _ = cache.set(value);
|
||||||
Some(value) => {
|
Ok(cache.get())
|
||||||
let _ = cache.set(value);
|
}
|
||||||
Ok(cache.try_get())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user