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
| Method | Path | Description |
|---|
GET | /api/admin/get-all-users | List all users |
PATCH | /api/admin/update-user-plan/:id | Override a user’s subscription plan |
PATCH | /api/admin/update-user-activity/:id | Enable or disable a user account |
GET | /api/admin/analytics | Retrieve platform-wide analytics |
All routes require authenticate + isAdmin middleware.