From 608ce1d9910cd68ce825838ea313e02c598f908e Mon Sep 17 00:00:00 2001 From: Mica White Date: Mon, 8 Dec 2025 20:08:21 -0500 Subject: Stuff --- src/scopes/admin.rs | 56 ++++++------ src/scopes/mod.rs | 256 ++++++++++++++++++++++++++-------------------------- 2 files changed, 156 insertions(+), 156 deletions(-) (limited to 'src/scopes') diff --git a/src/scopes/admin.rs b/src/scopes/admin.rs index 1e13b85..31e7880 100644 --- a/src/scopes/admin.rs +++ b/src/scopes/admin.rs @@ -1,28 +1,28 @@ -use std::fmt::{self, Display}; - -use crate::models::{client::Client, user::User}; - -use super::{Action, Scope}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct Admin; - -impl Display for Admin { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("admin") - } -} - -impl Scope for Admin { - fn parse_modifiers(_modifiers: &str) -> Result> { - Ok(Self) - } - - fn has_user_permission(&self, _: &User, _: &Action) -> bool { - true - } - - fn has_client_permission(&self, _: &User, _: &Action) -> bool { - true - } -} +use std::fmt::{self, Display}; + +use crate::models::{client::Client, user::User}; + +use super::{Action, Scope}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Admin; + +impl Display for Admin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("admin") + } +} + +impl Scope for Admin { + fn parse_modifiers(_modifiers: &str) -> Result> { + Ok(Self) + } + + fn has_user_permission(&self, _: &User, _: &Action) -> bool { + true + } + + fn has_client_permission(&self, _: &User, _: &Action) -> bool { + true + } +} diff --git a/src/scopes/mod.rs b/src/scopes/mod.rs index fb7780f..25296fd 100644 --- a/src/scopes/mod.rs +++ b/src/scopes/mod.rs @@ -1,128 +1,128 @@ -use std::collections::HashSet; - -use self::admin::Admin; -use crate::models::{client::Client, user::User}; - -mod admin; - -/// The action which was attempted on a resource -pub enum Action { - Create(T), - Read(T), - Update(T, T), - Delete(T), -} - -trait ScopeSuperSet { - fn is_superset_of(&self, other: &Self) -> bool; -} - -trait Scope: ToString { - /// Parse a scope of the format: `{Scope::NAME}:{modifiers}` - fn parse_modifiers(modifiers: &str) -> Result> - where - Self: Sized; - - /// Returns `true` if and only if the given `user` is allowed to take the - /// given `action` with this scope - fn has_user_permission(&self, user: &User, action: &Action) -> bool; - - // Returns `true` if and only if the given `user` is allowed to take the - /// given `action` with this scope - fn has_client_permission(&self, user: &User, action: &Action) -> bool; -} - -pub struct ParseScopeError { - scope: Box, - error: ParseScopeErrorType, -} - -impl ParseScopeError { - fn invalid_type(scope: &str, scope_type: &str) -> Self { - let scope = scope.into(); - let error = ParseScopeErrorType::InvalidType(scope_type.into()); - Self { scope, error } - } -} - -pub enum ParseScopeErrorType { - InvalidType(Box), - InvalidModifiers(Box), -} - -fn parse_scope(scope: &str) -> Result, ParseScopeError> { - let mut split = scope.split(':'); - let scope_type = split.next().unwrap(); - let _modifiers: String = split.collect(); - - match scope_type { - "admin" => Ok(Box::new(Admin)), - _ => Err(ParseScopeError::invalid_type(scope, scope_type)), - } -} - -fn parse_scopes(scopes: &str) -> Result>, ParseScopeError> { - scopes - .split_whitespace() - .map(|scope| parse_scope(scope)) - .collect() -} - -fn parse_scopes_errors( - results: &[Result, ParseScopeError>], -) -> Vec<&ParseScopeError> { - let mut errors = Vec::with_capacity(results.len()); - for result in results { - if let Err(pse) = result { - errors.push(pse) - } - } - - errors -} - -/// Returns `true` if and only if all values in `left_scopes` are contained in -/// `right_scopes`. -pub fn is_subset_of(left_scopes: &str, right_scopes: &str) -> bool { - let right_scopes: HashSet<&str> = right_scopes.split_whitespace().collect(); - - for scope in left_scopes.split_whitespace() { - if !right_scopes.contains(scope) { - return false; - } - } - - true -} - -pub fn has_user_permission( - user: User, - action: Action, - client_scopes: &str, -) -> Result { - let scopes = parse_scopes(client_scopes)?; - - for scope in scopes { - if scope.has_user_permission(&user, &action) { - return Ok(true); - } - } - - Ok(false) -} - -pub fn has_client_permission( - user: User, - action: Action, - client_scopes: &str, -) -> Result { - let scopes = parse_scopes(client_scopes)?; - - for scope in scopes { - if scope.has_client_permission(&user, &action) { - return Ok(true); - } - } - - Ok(false) -} +use std::collections::HashSet; + +use self::admin::Admin; +use crate::models::{client::Client, user::User}; + +mod admin; + +/// The action which was attempted on a resource +pub enum Action { + Create(T), + Read(T), + Update(T, T), + Delete(T), +} + +trait ScopeSuperSet { + fn is_superset_of(&self, other: &Self) -> bool; +} + +trait Scope: ToString { + /// Parse a scope of the format: `{Scope::NAME}:{modifiers}` + fn parse_modifiers(modifiers: &str) -> Result> + where + Self: Sized; + + /// Returns `true` if and only if the given `user` is allowed to take the + /// given `action` with this scope + fn has_user_permission(&self, user: &User, action: &Action) -> bool; + + // Returns `true` if and only if the given `user` is allowed to take the + /// given `action` with this scope + fn has_client_permission(&self, user: &User, action: &Action) -> bool; +} + +pub struct ParseScopeError { + scope: Box, + error: ParseScopeErrorType, +} + +impl ParseScopeError { + fn invalid_type(scope: &str, scope_type: &str) -> Self { + let scope = scope.into(); + let error = ParseScopeErrorType::InvalidType(scope_type.into()); + Self { scope, error } + } +} + +pub enum ParseScopeErrorType { + InvalidType(Box), + InvalidModifiers(Box), +} + +fn parse_scope(scope: &str) -> Result, ParseScopeError> { + let mut split = scope.split(':'); + let scope_type = split.next().unwrap(); + let _modifiers: String = split.collect(); + + match scope_type { + "admin" => Ok(Box::new(Admin)), + _ => Err(ParseScopeError::invalid_type(scope, scope_type)), + } +} + +fn parse_scopes(scopes: &str) -> Result>, ParseScopeError> { + scopes + .split_whitespace() + .map(|scope| parse_scope(scope)) + .collect() +} + +fn parse_scopes_errors( + results: &[Result, ParseScopeError>], +) -> Vec<&ParseScopeError> { + let mut errors = Vec::with_capacity(results.len()); + for result in results { + if let Err(pse) = result { + errors.push(pse) + } + } + + errors +} + +/// Returns `true` if and only if all values in `left_scopes` are contained in +/// `right_scopes`. +pub fn is_subset_of(left_scopes: &str, right_scopes: &str) -> bool { + let right_scopes: HashSet<&str> = right_scopes.split_whitespace().collect(); + + for scope in left_scopes.split_whitespace() { + if !right_scopes.contains(scope) { + return false; + } + } + + true +} + +pub fn has_user_permission( + user: User, + action: Action, + client_scopes: &str, +) -> Result { + let scopes = parse_scopes(client_scopes)?; + + for scope in scopes { + if scope.has_user_permission(&user, &action) { + return Ok(true); + } + } + + Ok(false) +} + +pub fn has_client_permission( + user: User, + action: Action, + client_scopes: &str, +) -> Result { + let scopes = parse_scopes(client_scopes)?; + + for scope in scopes { + if scope.has_client_permission(&user, &action) { + return Ok(true); + } + } + + Ok(false) +} -- cgit v1.2.3