diff --git a/base-config.yaml b/base-config.yaml
index 96c03f6..cf823be 100644
--- a/base-config.yaml
+++ b/base-config.yaml
@@ -34,3 +34,8 @@ repo_aliases:
     repository: "KDE_Unstable_Frameworks_openSUSE_Factory"
     state: "failed"
     arch: "all"
+acl:
+  admin:
+    - "@CHANGE_ME"
+  user: []
+
diff --git a/oscbot/__init__.py b/oscbot/__init__.py
index 02ff417..73735b5 100644
--- a/oscbot/__init__.py
+++ b/oscbot/__init__.py
@@ -83,6 +83,7 @@ class Config(BaseProxyConfig):
 
         helper.copy("username")
         helper.copy("repo_aliases")
+        helper.copy("acl")
 
 
 class OSCBot(Plugin):
@@ -114,6 +115,18 @@ class OSCBot(Plugin):
 
         return (project, package, repository, state, arch)
 
+    def check_acl(self, user_id: str, need_admin: bool = False) -> bool:
+
+        acls = self.config["acl"]
+        if not need_admin:
+            if user_id in acls["admin"] or acls["user"]:
+                return True
+        else:
+            if user_id in acls["admin"]:
+                return True
+        self.log.debug(f"Denied operation as {user_id}")
+        return False
+
     async def parse_rebuilpac(
             self,
             project: str,
@@ -222,6 +235,10 @@ class OSCBot(Plugin):
     @alias.subcommand("list", help="List configured aliases")
     async def list_aliases(self, evt: MessageEvent) -> None:
 
+        if not self.check_acl(evt.sender, need_admin=False):
+            await evt.reply("You are not authorized to perform this action.")
+            return
+
         body = self.template.from_string(ALIAS_TEMPLATE)
 
         if self.config.get("repo_aliases", None) is None:
@@ -246,6 +263,10 @@ class OSCBot(Plugin):
                          arch: Optional[str] = None,
                          state: Optional[str] = None) -> None:
 
+        if not self.check_acl(evt.sender, need_admin=True):
+            await evt.reply("You are not authorized to perform this action.")
+            return
+
         if alias not in self.config["repo_aliases"]:
             await evt.respond(f"Unknown alias {alias}")
             return
@@ -286,6 +307,10 @@ class OSCBot(Plugin):
                            arch: Optional[str] = None,
                            state: Optional[str] = None) -> None:
 
+        if not self.check_acl(evt.sender, need_admin=True):
+            await evt.reply("You are not authorized to perform this action.")
+            return
+
         repository = "all" if not repository else repository
         package = "all" if not package else package
         arch = "all" if not arch else arch
@@ -304,6 +329,11 @@ class OSCBot(Plugin):
     @alias.subcommand("delete", help="Delete an alias", aliases=("rm", ))
     @command.argument("alias", "alias name")
     async def delete_alias(self, evt: MessageEvent, alias: str):
+
+        if not self.check_acl(evt.sender, need_admin=True):
+            await evt.reply("You are not authorized to perform this action.")
+            return
+
         if alias not in self.config["repo_aliases"]:
             await evt.respond(f"Unknown alias {alias}")
             return
@@ -325,6 +355,10 @@ class OSCBot(Plugin):
                          repository: Optional[str] = None,
                          arch: Optional[str] = None) -> None:
 
+        if not self.check_acl(evt.sender, need_admin=True):
+            await evt.reply("You are not authorized to perform this action.")
+            return
+
         if project in self.config["repo_aliases"]:
             # We're not interested in state and we query package explicitly
             project, _, repository, _, arch = self.get_alias(project)
@@ -353,6 +387,10 @@ class OSCBot(Plugin):
                          project: str,
                          package: str) -> None:
 
+        if not self.check_acl(evt.sender, need_admin=True):
+            await evt.reply("You are not authorized to perform this action.")
+            return
+
         token = self.config["trigger_token"]
         trigger_url = f"{self.config['api_url']}/trigger/runservice"
         params = {"project": project, "package": package}
@@ -382,6 +420,10 @@ class OSCBot(Plugin):
                      repository: Optional[str] = None,
                      arch: Optional[str] = None) -> None:
 
+        if not self.check_acl(evt.sender, need_admin=False):
+            await evt.reply("You are not authorized to perform this action.")
+            return
+
         if project in self.config["repo_aliases"]:
             project, package, repository, state, arch = self.get_alias(project)
         else:
@@ -428,5 +470,5 @@ class OSCBot(Plugin):
                 message = body.render(packages=packagelist, base_url=base_url,
                                       project=project, repo=repository)
                 await evt.respond(message, markdown=True)
-                # Wait 100 milliseconds to avoid triggering rate limiting
-                sleep(0.1)
+                # Wait 200 milliseconds to avoid triggering rate limiting
+                sleep(0.2)