use crate::lib::{alloc::boxed::Box, alloc::string::String};
const READ: u8 = 0b0000_0001;
const WRITE: u8 = 0b0000_0010;
const MANAGE: u8 = 0b0000_0100;
const DELETE: u8 = 0b0000_1000;
const GET: u8 = 0b0010_0000;
const UPDATE: u8 = 0b0100_0000;
const JOIN: u8 = 0b1000_0000;
pub trait Permission {
fn id(&self) -> &String;
fn value(&self) -> &u8;
fn resource_type(&self) -> ResourceType;
}
pub enum ResourceType {
Channel,
ChannelGroup,
UserId,
}
#[derive(Debug)]
pub struct ChannelPermission {
pub name: String,
pub bits: u8,
}
#[derive(Debug)]
pub struct ChannelGroupPermission {
pub name: String,
pub bits: u8,
}
#[derive(Debug)]
pub struct UserIdPermission {
pub id: String,
pub bits: u8,
}
impl ChannelPermission {
pub fn read(mut self) -> Box<Self> {
self.bits |= READ;
Box::new(self)
}
pub fn write(mut self) -> Box<Self> {
self.bits |= WRITE;
Box::new(self)
}
pub fn delete(mut self) -> Box<Self> {
self.bits |= DELETE;
Box::new(self)
}
pub fn get(mut self) -> Box<Self> {
self.bits |= GET;
Box::new(self)
}
pub fn update(mut self) -> Box<Self> {
self.bits |= UPDATE;
Box::new(self)
}
pub fn manage(mut self) -> Box<Self> {
self.bits |= MANAGE;
Box::new(self)
}
pub fn join(mut self) -> Box<Self> {
self.bits |= JOIN;
Box::new(self)
}
}
impl Permission for ChannelPermission {
fn id(&self) -> &String {
&self.name
}
fn value(&self) -> &u8 {
&self.bits
}
fn resource_type(&self) -> ResourceType {
ResourceType::Channel
}
}
impl ChannelGroupPermission {
pub fn read(mut self) -> Box<Self> {
self.bits |= READ;
Box::new(self)
}
pub fn manage(mut self) -> Box<Self> {
self.bits |= MANAGE;
Box::new(self)
}
}
impl Permission for ChannelGroupPermission {
fn id(&self) -> &String {
&self.name
}
fn value(&self) -> &u8 {
&self.bits
}
fn resource_type(&self) -> ResourceType {
ResourceType::ChannelGroup
}
}
impl UserIdPermission {
pub fn get(mut self) -> Box<Self> {
self.bits |= GET;
Box::new(self)
}
pub fn update(mut self) -> Box<Self> {
self.bits |= UPDATE;
Box::new(self)
}
pub fn delete(mut self) -> Box<Self> {
self.bits |= DELETE;
Box::new(self)
}
}
impl Permission for UserIdPermission {
fn id(&self) -> &String {
&self.id
}
fn value(&self) -> &u8 {
&self.bits
}
fn resource_type(&self) -> ResourceType {
ResourceType::UserId
}
}
pub fn channel<N>(name: N) -> Box<ChannelPermission>
where
N: Into<String>,
{
Box::new(ChannelPermission {
name: name.into(),
bits: 0,
})
}
pub fn channel_group<N>(name: N) -> Box<ChannelGroupPermission>
where
N: Into<String>,
{
Box::new(ChannelGroupPermission {
name: name.into(),
bits: 0,
})
}
pub fn user_id<I>(id: I) -> Box<UserIdPermission>
where
I: Into<String>,
{
Box::new(UserIdPermission {
id: id.into(),
bits: 0,
})
}
#[cfg(test)]
mod it_should {
use super::*;
use test_case::test_case;
#[test_case(channel("test").read().value(), &0b0000_0001 ; "compare read permission")]
#[test_case(channel("test").write().value(), &0b0000_0010 ; "compare write permission")]
#[test_case(channel("test").manage().value(), &0b0000_0100 ; "compare manage permission")]
#[test_case(channel("test").delete().value(), &0b0000_1000 ; "compare delete permission")]
#[test_case(channel("test").get().value(), &0b0010_0000 ; "compare get permission")]
#[test_case(channel("test").update().value(), &0b0100_0000 ; "compare update permission")]
#[test_case(channel("test").join().value(), &0b1000_0000 ; "compare join permission")]
fn bits_properly_set(expected: &u8, actual: &u8) {
assert_eq!(expected, actual);
}
#[test]
fn create_channel_with_read_delete_join_permission() {
let channel_name = "test-channel";
let permission = channel(channel_name).read().delete().join();
assert_eq!(permission.value(), &0b1000_1001);
assert_eq!(permission.id(), channel_name);
}
#[test]
fn create_channel_group_manage_permission() {
let channel_group_name = "test-channel-group";
let permission = channel_group(channel_group_name).manage();
assert_eq!(permission.value(), &0b0000_0100);
assert_eq!(permission.id(), channel_group_name);
}
#[test]
fn create_user_id_get_update_permission() {
let user_id_value = "test-user-id";
let permission = user_id(user_id_value).get().update();
assert_eq!(permission.value(), &0b0110_0000);
assert_eq!(permission.id(), user_id_value);
}
}