astrox_macros 0.2.2

add user management and canister relation management for canister
Documentation
use std::borrow::{Borrow, BorrowMut};
use std::collections::BTreeMap;
use ic_cdk::export::Principal;
use candid::{CandidType};
use ic_cdk::export::candid::Deserialize;
use serde::Serialize;
use crate::user::Role::{OP, OWNER, USER};

#[derive(Debug)]
enum Role {
    OWNER,
    USER,
    OP
}

#[derive(CandidType, Serialize, Deserialize, Clone, Debug)]
pub struct User {
    owners: Option<BTreeMap<Principal, String>>,
    users: Option<BTreeMap<Principal, String>>,
    ops: Option<BTreeMap<Principal, String>>,
}

impl Default for User {
    fn default() -> Self {
        User {
            owners: Some(BTreeMap::default()),
            users: Some(BTreeMap::default()),
            ops: Some(BTreeMap::default()),
        }
    }
}

impl User {
    pub fn owners_set(&mut self, users: BTreeMap<Principal, String>) {
        self.role_users_set(OWNER, users);
    }

    pub fn owners(&self) -> Option<BTreeMap<Principal, String>> {
        self.role_users(OWNER).clone()
    }

    pub fn owner_add(&mut self, name: String, user_id: Principal) {
        self.role_user_add(OWNER, name, user_id);
    }

    pub fn owner_remove(&mut self, user_id: Principal) {
        self.role_user_remove(OWNER, user_id);
    }

    pub fn is_owner(&self, who: Principal) -> bool {
        self.is_a(OWNER, who)
    }

    pub fn users_set(&mut self, users: BTreeMap<Principal, String>) {
        self.role_users_set(USER, users);
    }

    pub fn users(&self) -> Option<BTreeMap<Principal, String>> {
        self.role_users(USER).clone()
    }

    pub fn user_add(&mut self, name: String, user_id: Principal) {
        self.role_user_add(USER, name, user_id);
    }

    pub fn user_remove(&mut self, user_id: Principal) {
        self.role_user_remove(USER, user_id);
    }

    pub fn is_user(&self, who: Principal) -> bool {
        self.is_a(USER, who) || self.is_a(OWNER, who)
    }

    pub fn ops_set(&mut self, users: BTreeMap<Principal, String>) {
        self.role_users_set(OP, users);
    }

    pub fn ops(&self) -> Option<BTreeMap<Principal, String>> {
        self.role_users(OP).clone()
    }

    pub fn op_add(&mut self, name: String, user_id: Principal) {
        self.role_user_add(OP, name, user_id);
    }

    pub fn op_remove(&mut self, user_id: Principal) {
        self.role_user_remove(OP, user_id);
    }

    pub fn is_op(&self, who: Principal) -> bool {
        self.is_a(OP, who) || self.is_a(OWNER, who)
    }

    fn role_users_set(&mut self, role: Role, users: BTreeMap<Principal, String>) {
        match role {
            OWNER => self.owners = Some(users),
            USER => self.users = Some(users),
            OP => self.ops = Some(users),
        }
    }

    fn role_users(&self, role: Role) -> &Option<BTreeMap<Principal, String>> {
        match role {
            OWNER => self.owners.borrow(),
            USER => self.users.borrow(),
            OP => self.ops.borrow(),
        }
    }

    fn role_users_mut(&mut self, role: Role) -> &mut Option<BTreeMap<Principal, String>>{
        match role {
            OWNER => self.owners.borrow_mut(),
            USER => self.users.borrow_mut(),
            OP => self.ops.borrow_mut(),
        }
    }

    fn role_user_add(&mut self, role: Role, name: String, user_id: Principal) {
        let users = self.role_users_mut(role).as_mut().unwrap();

        if !users.contains_key(&user_id) {
            users.insert(user_id, name);
        }
    }

    fn role_user_remove(&mut self, role: Role, user_id: Principal) {
        let users = self.role_users_mut(role).as_mut().unwrap();

        if users.contains_key(&user_id) {
            users.remove(&user_id);
        }
    }

    fn is_a(&self, role: Role, who: Principal) -> bool {
        let users = self.role_users(role).as_ref().unwrap();
        users.contains_key(&who)
    }

}