---
id: gh-extension-user-approval
name: "extension-user-approval"
url: https://skills.yangsir.net/skill/gh-extension-user-approval
author: caffeinelabs
domain: ai-agent-core-development
tags: ["user-management", "access-control", "approval-workflow", "security", "backend-extension"]
install_count: 27400
rating: 4.60 (120 reviews)
github: https://github.com/caffeinelabs/skills/tree/main/skills/extension-user-approval
---

# extension-user-approval

> 此技能为 AI 平台提供基于审批的用户管理功能。用户可请求访问，管理员可审批或拒绝，确保只有授权用户才能访问受保护功能。它简化了用户权限管理流程，提升了系统安全性与合规性。

**Stats**: 27,400 installs · 4.6/5 (120 reviews)

## Before / After 对比

### 用户访问审批效率提升

**Before**:

在没有此技能之前，管理员需要手动处理每个用户的访问请求，包括核对身份、记录审批状态并手动更新权限，这不仅耗时，还容易因疏忽导致权限配置错误。

**After**:

该 Skill 自动化了用户访问审批流程，用户请求后管理员可快速审批或拒绝，系统自动更新权限。这显著减少了管理员的工作量，并确保了权限管理的准确性和及时性。

| Metric | Before | After | Change |
|---|---|---|---|
| 审批处理时间 | 30分钟 | 5分钟 | -83% |
| 权限配置错误率 | 15% | 2% | -87% |

## Readme

# User Approval
User approval extension for [Caffeine AI](https://caffeine.ai?utm_source=caffeine-skill&utm_medium=referral).

## Overview

This skill adds approval-based user management. Users request access; admins approve or reject. Approved users gain access to protected features.

# Backend

Approval-based user management:

Prerequisite: You must follow [extension-authorization](../extension-authorization/SKILL.md) first, as this integration depends on it.

There is a prefabricated module `mo:caffeineai-user-approval/approval` that cannot be modified. It provides approval-based user management with role-based access control.

```mo:caffeineai-user-approval/approval
import AccessControl "mo:caffeineai-authorization/access-control";

module {
    public type ApprovalStatus = {
        #approved;
        #rejected;
        #pending;
    };

    public type UserApprovalState = { /* internal state */ };

    public func initState(accessControlState: AccessControl.AccessControlState) : UserApprovalState;

    public func isApproved(state : UserApprovalState, caller : Principal) : Bool;
    public func setApproval(state : UserApprovalState, user : Principal, approval : ApprovalStatus);

    public type UserApprovalInfo = {
        principal : Principal;
        status : ApprovalStatus;
    };

    public func listApprovals(state : UserApprovalState) : [UserApprovalInfo];
}
```

Usage (all the following functions are required to be added):

```motoko filepath=src/backend/main.mo
import AccessControl "mo:caffeineai-authorization/access-control";
import MixinAuthorization "mo:caffeineai-authorization/MixinAuthorization";
import UserApproval "mo:caffeineai-user-approval/approval";
import Principal "mo:core/Principal";
import Runtime "mo:core/Runtime";

actor {
    // Include authorization
    let accessControlState = AccessControl.initState();
    include MixinAuthorization(accessControlState);

    let approvalState = UserApproval.initState(accessControlState);

    public query ({ caller }) func isCallerApproved() : async Bool {
        AccessControl.hasPermission(accessControlState, caller, #admin) or UserApproval.isApproved(approvalState, caller);
    };

    public shared ({ caller }) func requestApproval() : async () {
        UserApproval.requestApproval(approvalState, caller);
    };

    public shared ({ caller }) func setApproval(user : Principal, status : UserApproval.ApprovalStatus) : async () {
        if (not (AccessControl.hasPermission(accessControlState, caller, #admin))) {
            Runtime.trap("Unauthorized: Only admins can perform this action");
        };
        UserApproval.setApproval(approvalState, user, status);
    };

    public query ({ caller }) func listApprovals() : async [UserApproval.UserApprovalInfo] {
        if (not (AccessControl.hasPermission(accessControlState, caller, #admin))) {
            Runtime.trap("Unauthorized: Only admins can perform this action");
        };
        UserApproval.listApprovals(approvalState);
    };

    // In addition to access control guards, add an approval check where needed:
    // Admins should have the permission do use all functionality
    // * Approved users only:
    //   if (not (UserApproval.isApproved(approvalState, caller) or AccessControl.hasPermission(accessControlState, caller, #admin))) {
    //      Runtime.trap("Unauthorized: Only approved users can perform this action");
    //   };
};
```

On `initState`, existing admins are automatically approved. All other users are pending.

IMPORTANT: Apply the right authorization and/or approval check to each public function.

# Frontend

Approval-based user management:

# User Approval Flow
- Check approval status (`isCallerApproved`)
- If not approved, show option to request approval (`requestApproval`)
- Block access to main features for non-approved users
- Admins have access to all features of the application
- Display approval status clearly in the UI

# Admin Dashboard
For admin users, provide a dashboard to:
- List all users with their approval status (`listApprovals`)
- Approve or reject users (`setApproval`)
- View and assign user roles (using `getCallerUserRole` and `assignCallerUserRole`)

# Backend Integration
The backend already implements the following functionality.
The full interface can be found in <backend-interface>

// Check if current user is approved, admins are always approved
isCallerApproved(): Promise<boolean>;

// Submit approval request
requestApproval(): Promise<void>;

// Get all users and their approval status (admin only)
listApprovals(): Promise<Array<UserApprovalInfo>>;

// Approve or reject a user (admin only)
setApproval(user: Principal, status: ApprovalStatus): Promise<void>;

// Assign a role to a user (admin only)
assignCallerUserRole(user: Principal, role: UserRole): Promise<void>;

// Get current role for a specific user
getCallerUserRole(): Promise<UserRole>;


---
*Source: https://skills.yangsir.net/skill/gh-extension-user-approval*
*Markdown mirror: https://skills.yangsir.net/api/skill/gh-extension-user-approval/markdown*