extension-user-approval

Gestión de usuarios basada en aprobación.

npx skills add https://github.com/caffeinelabs/skills --skill extension-user-approval

User Approval

User approval extension for Caffeine AI.

Overview

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

Prerequisite: You must follow extension-authorization first, as this integration depends on it.

Backend

Module API

The prefabricated module mo:caffeineai-user-approval/approval provides low-level approval state management. Do not modify it.

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 requestApproval(state : UserApprovalState, caller : Principal);
    public func setApproval(state : UserApprovalState, user : Principal, approval : ApprovalStatus);

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

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

Setup in main.mo

include MixinUserApproval(accessControlState, approvalState) MUST be placed in main.mo, not in a custom mixin file. Create approvalState at actor top level with UserApproval.initState(accessControlState) and pass it into the mixin. The mixin provides these public endpoints automatically:

  • isCallerApproved()
  • requestApproval()
  • setApproval(user, status)
  • listApprovals()

Keep approvalState in scope for custom approval guards in app-specific endpoints.

Do NOT redeclare any of the mixin-provided functions.

import AccessControl "mo:caffeineai-authorization/access-control";
import MixinAuthorization "mo:caffeineai-authorization/MixinAuthorization";
import MixinUserApproval "mo:caffeineai-user-approval/MixinUserApproval";
import UserApproval "mo:caffeineai-user-approval/approval";
import Runtime "mo:core/Runtime";

actor {
    let accessControlState = AccessControl.initState();
    include MixinAuthorization(accessControlState, null);
    let approvalState = UserApproval.initState(accessControlState);
    include MixinUserApproval(accessControlState, approvalState);

    // Example custom endpoint with an approval guard:
    // public shared ({ caller }) func protectedFeature() : async () {
    //     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 custom 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

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

// Submit approval request requestApproval(): Promise;

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

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

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

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

Más skills de caffeinelabs

extension-stripe
caffeinelabs
Soporte de pagos basado en Stripe, compatible con tarjetas de crédito y débito.
extension-object-storage
caffeinelabs
Almacenamiento general de archivos/objetos, como para imágenes, videos, archivos, documentos y otros datos masivos. Perfecto para galerías de imágenes, galerías de videos y otra gestión de archivos u objetos. Soporta archivos grandes más allá del límite de IC, con acceso a URL HTTP almacenadas en caché del navegador.
developmentmedia
extension-openai
caffeinelabs
MANDATORY recipe for every Caffeine build that calls OpenAI (ChatGPT, GPT-4o, an LLM, a chatbot, embeddings). The ONLY supported path is the `openai-client` mops package with a canister-side API-key bearer. Hand-rolling `ic.http_request` to `api.openai.com/v1/...` is a FORBIDDEN anti-pattern — it leaks the bearer across replicated outcalls (security + 13× billing impact), bypasses the typed request/response bindings, and forces hand-rolled JSON on a language with poor JSON support. Load this...
developmentapisecurity
extension-http-outcalls
caffeinelabs
Las llamadas HTTP salientes realizadas por el canister del backend (no en el frontend).
developmentapi
connector-googlemail
caffeinelabs
Use the `googlemail-client` mops package whenever the user asks the canister to send email, compose a draft, list or read Gmail messages, or fetch the authenticated user's Gmail profile. The package wraps the Gmail REST API v1 at `https://gmail.googleapis.com` via outbound HTTPS calls.
communicationapiproductivity
extension-querying-oql
caffeinelabs
Quick reference for the Caffeine Data Intelligence agent to query an OQL-exposing canister (schema() + execute()) through the `icp` CLI against the project's `backend` canister: read the schema, form JSON queries (filter / order / paginate / aggregate / dotted-path edges), and parse the Candid result rows.
developmentdatabaseapi
extension-core-infrastructure
caffeinelabs
Infraestructura central que proporciona configuración de conexión backend, cliente de almacenamiento y punto de entrada de la aplicación React.
developmentapidevops
extension-posting-to-x
caffeinelabs
MANDATORY recipe for every Caffeine build that posts to X (Twitter). The ONLY supported path is the `x-client` mops package with OAuth 2.0 PKCE. Hand-rolling `ic.http_request` or `icBooking.http_request` calls to `api.x.com/2/tweets`, `api.x.com/2/oauth2/token`, or any other X endpoint is a FORBIDDEN anti-pattern — it bypasses bearer auth, replication-cost safeguards, and `x-client`'s null-field handling. Load this skill whenever the user, spec, or any prior task mentions tweeting,...
developmentapi