/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin */ use crate::CONF; use anyhow::anyhow; use jellycommon::{ user::{PermissionSet, UserPermission}, Node, }; pub trait PermissionSetExt { fn check_explicit(&self, perm: &UserPermission) -> Option; fn check(&self, perm: &UserPermission) -> bool { self.check_explicit(perm).unwrap_or(perm.default_value()) } fn assert(&self, perm: &UserPermission) -> Result<(), anyhow::Error>; } impl PermissionSetExt for PermissionSet { fn check_explicit(&self, perm: &UserPermission) -> Option { self.0 .get(&perm) .or(CONF.default_permission_set.0.get(&perm)) .map(|v| *v) } fn assert(&self, perm: &UserPermission) -> Result<(), anyhow::Error> { if self.check(perm) { Ok(()) } else { Err(anyhow!( "sorry, you need special permission {perm:?} for this action." )) } } } pub trait NodePermissionExt { fn only_if_permitted(self, perms: &PermissionSet) -> Self; } impl NodePermissionExt for Option { fn only_if_permitted(self, perms: &PermissionSet) -> Self { self.and_then(|node| { if check_node_permission(perms, &node) { Some(node) } else { None } }) } } fn check_node_permission(perms: &PermissionSet, node: &Node) -> bool { if let Some(v) = perms.check_explicit(&UserPermission::AccessNode(node.public.id.clone().unwrap())) { v } else { for com in node.public.path.clone().into_iter().rev() { if let Some(v) = perms.check_explicit(&UserPermission::AccessNode(com.to_owned())) { return v; } } return true; } }