Skip to main content
Hayon includes a built-in admin layer that lets privileged users manage accounts, override subscription plans, and control user access. All admin operations are protected by two layers of middleware: authenticate and isAdmin.

Admin role

Users in Hayon have a role field that is either user (default) or admin. The role is stored on the user document in MongoDB:
role: {
  type: String,
  enum: ["user", "admin"],
  default: "user"
}
To grant admin access to an account, update the user’s role field directly in the database. There is no self-serve promotion flow — admin access must be granted by a database operator or another admin via a direct update.

How admin access is enforced

Every route under /api/admin applies two middleware functions in order:
router.use(authenticate);  // Verifies JWT and attaches req.auth
router.use(isAdmin);       // Checks req.auth.role === "admin"
The isAdmin middleware:
export const isAdmin = (req, res, next) => {
  if (!req.auth) {
    return new ErrorResponse("Unauthorized", { status: 401 }).send(res);
  }
  if (req.auth.role !== "admin") {
    return new ErrorResponse("Forbidden - Admin only", { status: 403 }).send(res);
  }
  next();
};
Any request to /api/admin/* from a non-admin user receives a 403 Forbidden response. This check runs on every admin route — there are no public admin endpoints.

Admin login

Admins authenticate through the standard auth endpoint with admin credentials:
curl -X POST http://localhost:5000/api/auth/admin-login \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "password": "your-password"}'
This returns a JWT token. Include this token as a Bearer token in the Authorization header for all subsequent admin API calls.
The admin login endpoint performs the same authentication as the regular login but is intended for admin-facing tooling and scripts. The returned JWT contains the user’s role, which the isAdmin middleware reads.

Listing all users

Retrieve a list of every registered user on the platform:
curl http://localhost:5000/api/admin/get-all-users \
  -H "Authorization: Bearer <admin-token>"
Response:
{
  "message": "Users retrieved successfully",
  "data": [
    {
      "_id": "664abc...",
      "email": "[email protected]",
      "name": "Jane Doe",
      "role": "user",
      "isDisabled": false,
      "subscription": {
        "plan": "free",
        "status": "active"
      },
      "usage": {
        "postsCreated": 5,
        "captionGenerations": 2
      },
      "limits": {
        "maxPosts": 30,
        "maxCaptionGenerations": 15
      },
      "createdAt": "2025-01-15T10:00:00.000Z",
      "lastLogin": "2025-03-20T08:30:00.000Z"
    }
  ]
}
The response includes full user documents with subscription, usage, limits, and activity metadata.

Updating a user’s plan

Override a user’s subscription plan directly, bypassing Stripe. This is useful for granting Pro access to team members, resolving billing issues, or resetting a user to Free.
# Upgrade a user to Pro
curl -X PATCH "http://localhost:5000/api/admin/update-user-plan/664abc?plan=pro" \
  -H "Authorization: Bearer <admin-token>"

# Downgrade a user to Free
curl -X PATCH "http://localhost:5000/api/admin/update-user-plan/664abc?plan=free" \
  -H "Authorization: Bearer <admin-token>"
The plan query parameter must be either free or pro. Any other value returns a 400 error. Successful response:
{
  "message": "User plan updated successfully",
  "data": {
    "userId": "664abc...",
    "plan": "pro"
  }
}
Updating a plan via this endpoint changes the user’s subscription.plan and updates their limits accordingly (maxPosts and maxCaptionGenerations). It does not create or modify any Stripe subscription — it is a direct database override.

Activating and deactivating accounts

You can disable or re-enable a user account. Disabled accounts (isDisabled: true) are blocked from logging in and using the platform.
# Deactivate a user account
curl -X PATCH http://localhost:5000/api/admin/update-user-activity/664abc \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"activity": false}'

# Reactivate a user account
curl -X PATCH http://localhost:5000/api/admin/update-user-activity/664abc \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"activity": true}'
The activity field in the request body must be a boolean. Any other type returns a 400 error. Successful response:
{
  "message": "User activity status updated successfully",
  "data": {
    "_id": "664abc...",
    "email": "[email protected]",
    "isDisabled": false
  }
}
Deactivating a user (activity: false) sets isDisabled: true on their account. Ensure you are targeting the correct user ID before making this call — there is no confirmation step.

Admin routes summary

MethodPathDescription
GET/api/admin/get-all-usersList all users
PATCH/api/admin/update-user-plan/:idOverride a user’s subscription plan
PATCH/api/admin/update-user-activity/:idEnable or disable a user account
GET/api/admin/analyticsRetrieve platform-wide analytics
All routes require authenticate + isAdmin middleware.

Build docs developers (and LLMs) love