diff --git a/src/cmd_acl.rs b/src/cmd_acl.rs
new file mode 100644
index 0000000000000000000000000000000000000000..49aa25c25c52095276c9391b3d42645fb8b5a789
--- /dev/null
+++ b/src/cmd_acl.rs
@@ -0,0 +1,70 @@
+use crate::bool_to_result;
+use matrix_sdk::{room::Room, ruma::UserId};
+use std::result::Result;
+
+#[allow(dead_code)]
+pub enum CmdAcl {
+    RoomOnly(String),
+    AdminOnly,
+    List(Vec<CmdAcl>),
+}
+
+#[allow(dead_code)]
+pub struct CmdAdminRegister {
+    admins: Vec<UserId>,
+}
+
+impl CmdAdminRegister {
+    fn is_admin(&self, user_id: UserId) -> bool {
+        return self.admins.iter().position(|x| *x == user_id).is_some();
+    }
+
+    #[allow(dead_code)]
+    pub fn add_admin(&mut self, user_id: UserId) {
+        if !self.is_admin(user_id.clone()) {
+            self.admins.push(user_id);
+        }
+    }
+
+    #[allow(dead_code)]
+    pub fn revoke_admin(&mut self, user_id: UserId) -> Result<(), String> {
+        match self.admins.iter().position(|x| *x == user_id) {
+            Some(index) => {
+                self.admins.remove(index);
+                return Ok(());
+            }
+            None => return Err("Is not an admin".to_string()),
+        }
+    }
+}
+
+#[allow(dead_code)]
+pub fn action_permited(
+    cmd_admin_register: &CmdAdminRegister,
+    acls: &CmdAcl,
+    room: &Room,
+    user_id: &UserId,
+) -> Result<(), String> {
+    return match acls {
+        CmdAcl::AdminOnly => bool_to_result!(
+            cmd_admin_register.is_admin(user_id.clone()),
+            (),
+            "Is not an admin".to_string()
+        ),
+        CmdAcl::RoomOnly(room_id) => bool_to_result!(
+            room.room_id() == room_id,
+            (),
+            "Not permited in this room".to_string()
+        ),
+        CmdAcl::List(acl_list) => match acl_list
+            .iter()
+            .map(|acl| action_permited(cmd_admin_register, acl, room, user_id))
+            .filter(|acl_res| acl_res.is_err())
+            .map(|acl_res| acl_res.clone().unwrap_err())
+            .reduce(|err1, err2| err1 + ", " + &err2)
+        {
+            Some(err) => Err(err),
+            None => Ok(()),
+        },
+    };
+}
diff --git a/src/utils.rs b/src/utils.rs
new file mode 100644
index 0000000000000000000000000000000000000000..529987eefb521c3cf24dc2f8f0d448f4ccd076ee
--- /dev/null
+++ b/src/utils.rs
@@ -0,0 +1,29 @@
+#![allow(dead_code)]
+
+#[macro_export]
+macro_rules! return_if {
+    ($var:expr, $ret:expr) => {{
+        if ($var) {
+            return $ret;
+        }
+    }};
+}
+
+#[macro_export]
+macro_rules! return_unless {
+    ($var:expr, $ret:expr) => {{
+        if (!($var)) {
+            return $ret;
+        }
+    }};
+}
+
+#[macro_export]
+macro_rules! bool_to_result {
+    ($cond:expr, $ok:expr, $err:expr) => {{
+        match $cond {
+            true => Ok($ok),
+            false => Err($err),
+        }
+    }};
+}