a06673b
use uuid::Uuid;
use crate::actor::{ActorContext, ChannelRole, RepoAccess, SpaceRole, TokenScope};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PermissionError {
Anonymous,
Insufficient,
Forbidden,
}
pub fn required_scope_for(access: RepoAccess) -> TokenScope {
match access {
RepoAccess::None | RepoAccess::Read => TokenScope::RepoRead,
RepoAccess::Write => TokenScope::RepoWrite,
RepoAccess::Admin => TokenScope::RepoAdmin,
}
}
pub fn effective_access(
actor: &ActorContext,
channel_role: Option<ChannelRole>,
space_role: Option<SpaceRole>,
collaborator_mode: Option<RepoAccess>,
is_public: bool,
) -> RepoAccess {
if actor.is_site_admin {
return RepoAccess::Admin;
}
if actor.has_scope(TokenScope::RepoAdmin) {
return RepoAccess::Admin;
}
if actor.has_scope(TokenScope::RepoWrite) {
return RepoAccess::Write;
}
if actor.has_scope(TokenScope::RepoRead) {
if matches!(
collaborator_mode,
Some(RepoAccess::Write) | Some(RepoAccess::Admin)
) {
return RepoAccess::Write;
}
return RepoAccess::Read;
}
if matches!(space_role, Some(SpaceRole::Owner | SpaceRole::Admin)) {
return RepoAccess::Admin;
}
if matches!(
channel_role,
Some(ChannelRole::Owner | ChannelRole::Moderator)
) {
return RepoAccess::Write;
}
if let Some(mode) = collaborator_mode {
return mode;
}
if is_public {
return RepoAccess::Read;
}
RepoAccess::None
}
pub fn require(
actor: &ActorContext,
required: RepoAccess,
channel_role: Option<ChannelRole>,
space_role: Option<SpaceRole>,
collaborator_mode: Option<RepoAccess>,
is_public: bool,
) -> Result<(), PermissionError> {
let has = effective_access(
actor,
channel_role,
space_role,
collaborator_mode,
is_public,
);
if has.at_least(required) {
Ok(())
} else if !actor.is_authenticated() && required == RepoAccess::Read && is_public {
Ok(())
} else if !actor.is_authenticated() {
Err(PermissionError::Anonymous)
} else {
Err(PermissionError::Insufficient)
}
}
pub fn require_write(actor: &ActorContext, is_admin_endpoint: bool) -> Result<(), PermissionError> {
if !actor.is_authenticated() {
return Err(PermissionError::Anonymous);
}
if actor.is_site_admin {
return Ok(());
}
if is_admin_endpoint {
if actor.has_scope(TokenScope::RepoAdmin) {
return Ok(());
}
} else if actor.has_scope(TokenScope::RepoWrite) {
return Ok(());
}
Err(PermissionError::Insufficient)
}