use activitystreams_vocabulary::{Iri, Item, impl_default, impl_display};
use serde::{Deserialize, Serialize};
use crate::db::Iri as DbIri;
use crate::{Error, Result};
#[derive(
Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, sqlx::Type,
)]
#[serde(rename_all = "camelCase")]
#[sqlx(type_name = "role")]
pub enum Role {
Public,
Visit,
Report,
Triage,
Write,
Maintain,
Admin,
Delegate,
Deny,
}
impl Role {
pub const VISIT: &str = "visit";
pub const REPORT: &str = "report";
pub const TRIAGE: &str = "triage";
pub const WRITE: &str = "write";
pub const MAINTAIN: &str = "maintain";
pub const ADMIN: &str = "admin";
pub const DELEGATE: &str = "delegate";
pub const PUBLIC: &str = "public";
pub const DENY: &str = "deny";
pub const fn new() -> Self {
Self::Triage
}
pub const fn as_str(&self) -> &'static str {
match self {
Self::Visit => Self::VISIT,
Self::Report => Self::REPORT,
Self::Triage => Self::TRIAGE,
Self::Write => Self::WRITE,
Self::Maintain => Self::MAINTAIN,
Self::Admin => Self::ADMIN,
Self::Delegate => Self::DELEGATE,
Self::Public => Self::PUBLIC,
Self::Deny => Self::DENY,
}
}
}
impl_default!(Role);
impl_display!(Role, str);
impl From<Role> for Item {
fn from(val: Role) -> Self {
(&val).into()
}
}
impl From<&Role> for Item {
fn from(val: &Role) -> Self {
Self::iri(Iri::try_from(val.as_str()).unwrap_or_default())
}
}
impl TryFrom<&str> for Role {
type Error = Error;
fn try_from(val: &str) -> Result<Self> {
match val.to_lowercase().as_str() {
Self::VISIT => Ok(Self::Visit),
Self::REPORT => Ok(Self::Report),
Self::TRIAGE => Ok(Self::Triage),
Self::WRITE => Ok(Self::Write),
Self::MAINTAIN => Ok(Self::Maintain),
Self::ADMIN => Ok(Self::Admin),
Self::DELEGATE => Ok(Self::Delegate),
Self::PUBLIC => Ok(Self::Public),
Self::DENY => Ok(Self::Deny),
role => Err(Error::vocabulary(format!("role: invalid variant: {role}"))),
}
}
}
impl TryFrom<String> for Role {
type Error = Error;
fn try_from(val: String) -> Result<Self> {
val.as_str().try_into()
}
}
impl TryFrom<Iri> for Role {
type Error = Error;
fn try_from(val: Iri) -> Result<Self> {
(&val).try_into()
}
}
impl TryFrom<&Iri> for Role {
type Error = Error;
fn try_from(val: &Iri) -> Result<Self> {
val.as_str().try_into()
}
}
impl TryFrom<DbIri> for Role {
type Error = Error;
fn try_from(val: DbIri) -> Result<Self> {
(&val).try_into()
}
}
impl TryFrom<&DbIri> for Role {
type Error = Error;
fn try_from(val: &DbIri) -> Result<Self> {
val.as_str().try_into()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_role() {
[
(Role::Visit, Role::VISIT),
(Role::Report, Role::REPORT),
(Role::Triage, Role::TRIAGE),
(Role::Write, Role::WRITE),
(Role::Maintain, Role::MAINTAIN),
(Role::Admin, Role::ADMIN),
(Role::Delegate, Role::DELEGATE),
(Role::Public, Role::PUBLIC),
(Role::Deny, Role::DENY),
]
.into_iter()
.for_each(|(cap, cap_str)| {
let json_str = format!(r#""{cap_str}""#);
assert_eq!(serde_json::to_string_pretty(&cap).unwrap(), json_str);
assert_eq!(
serde_json::from_str::<Role>(json_str.as_str()).unwrap(),
cap,
);
});
assert!(Role::Public < Role::Visit);
assert!(Role::Public < Role::Report);
assert!(Role::Public < Role::Triage);
assert!(Role::Public < Role::Write);
assert!(Role::Public < Role::Maintain);
assert!(Role::Public < Role::Admin);
assert!(Role::Public < Role::Delegate);
assert!(Role::Public < Role::Deny);
assert!(Role::Visit < Role::Report);
assert!(Role::Visit < Role::Triage);
assert!(Role::Visit < Role::Write);
assert!(Role::Visit < Role::Maintain);
assert!(Role::Visit < Role::Admin);
assert!(Role::Visit < Role::Delegate);
assert!(Role::Visit < Role::Deny);
assert!(Role::Report < Role::Triage);
assert!(Role::Report < Role::Write);
assert!(Role::Report < Role::Maintain);
assert!(Role::Report < Role::Admin);
assert!(Role::Report < Role::Delegate);
assert!(Role::Report < Role::Deny);
assert!(Role::Triage < Role::Write);
assert!(Role::Triage < Role::Maintain);
assert!(Role::Triage < Role::Admin);
assert!(Role::Triage < Role::Delegate);
assert!(Role::Triage < Role::Deny);
assert!(Role::Write < Role::Maintain);
assert!(Role::Write < Role::Admin);
assert!(Role::Write < Role::Delegate);
assert!(Role::Write < Role::Deny);
assert!(Role::Maintain < Role::Admin);
assert!(Role::Maintain < Role::Delegate);
assert!(Role::Maintain < Role::Deny);
assert!(Role::Admin < Role::Delegate);
assert!(Role::Admin < Role::Deny);
assert!(Role::Delegate < Role::Deny);
}
}