mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-10 04:19:32 +00:00
fix(admin): require adminRoles option for a role to be considered an admin role
This commit is contained in:
@@ -514,6 +514,20 @@ admin({
|
|||||||
defaultRole: "regular",
|
defaultRole: "regular",
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
### Admin Roles
|
||||||
|
|
||||||
|
The roles that are considered admin roles. Defaults to `["admin"]`.
|
||||||
|
|
||||||
|
```ts title="auth.ts"
|
||||||
|
admin({
|
||||||
|
adminRoles: ["admin", "superadmin"],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
<Callout type="warning">
|
||||||
|
Any role that isn't in the `adminRoles` list, even if they have the permission,
|
||||||
|
will not be considered an admin.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
### Admin userIds
|
### Admin userIds
|
||||||
|
|
||||||
@@ -525,6 +539,8 @@ admin({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If a user is in the `adminUserIds` list, they will be able to perform any admin operation.
|
||||||
|
|
||||||
### impersonationSessionDuration
|
### impersonationSessionDuration
|
||||||
|
|
||||||
The duration of the impersonation session in seconds. Defaults to 1 hour.
|
The duration of the impersonation session in seconds. Defaults to 1 hour.
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ describe("Admin plugin", async () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
//should reject cause the user is not admin
|
//should reject cause the user is not admin
|
||||||
expect(impersonatedUserRes.error?.status).toBe(403);
|
expect(impersonatedUserRes.error?.status).toBe(401);
|
||||||
const res = await client.admin.stopImpersonating(
|
const res = await client.admin.stopImpersonating(
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import { getDate } from "../../utils/date";
|
|||||||
import { getEndpointResponse } from "../../utils/plugin-helper";
|
import { getEndpointResponse } from "../../utils/plugin-helper";
|
||||||
import { mergeSchema } from "../../db/schema";
|
import { mergeSchema } from "../../db/schema";
|
||||||
import { type AccessControl, type Role } from "../access";
|
import { type AccessControl, type Role } from "../access";
|
||||||
import { adminMiddleware } from "./call";
|
|
||||||
import { ADMIN_ERROR_CODES } from "./error-codes";
|
import { ADMIN_ERROR_CODES } from "./error-codes";
|
||||||
import { defaultStatements } from "./access";
|
import { defaultStatements } from "./access";
|
||||||
import { hasPermission } from "./has-permission";
|
import { hasPermission } from "./has-permission";
|
||||||
@@ -41,6 +40,15 @@ export interface AdminOptions {
|
|||||||
* @default "user"
|
* @default "user"
|
||||||
*/
|
*/
|
||||||
defaultRole?: string;
|
defaultRole?: string;
|
||||||
|
/**
|
||||||
|
* Roles that are considered admin roles.
|
||||||
|
*
|
||||||
|
* Any user role that isn't in this list, even if they have the permission,
|
||||||
|
* will not be considered an admin.
|
||||||
|
*
|
||||||
|
* @default ["admin"]
|
||||||
|
*/
|
||||||
|
adminRoles?: string | string[];
|
||||||
/**
|
/**
|
||||||
* A default ban reason
|
* A default ban reason
|
||||||
*
|
*
|
||||||
@@ -85,12 +93,32 @@ export interface AdminOptions {
|
|||||||
export const admin = <O extends AdminOptions>(options?: O) => {
|
export const admin = <O extends AdminOptions>(options?: O) => {
|
||||||
const opts = {
|
const opts = {
|
||||||
defaultRole: "user",
|
defaultRole: "user",
|
||||||
|
adminRoles: ["admin"],
|
||||||
...options,
|
...options,
|
||||||
};
|
};
|
||||||
type DefaultStatements = typeof defaultStatements;
|
type DefaultStatements = typeof defaultStatements;
|
||||||
type Statements = O["ac"] extends AccessControl<infer S>
|
type Statements = O["ac"] extends AccessControl<infer S>
|
||||||
? S
|
? S
|
||||||
: DefaultStatements;
|
: DefaultStatements;
|
||||||
|
|
||||||
|
const adminMiddleware = createAuthMiddleware(async (ctx) => {
|
||||||
|
const session = await getSessionFromCtx(ctx);
|
||||||
|
if (
|
||||||
|
(!session?.session || !opts.adminRoles.includes(session.user.role)) &&
|
||||||
|
!opts.adminUserIds?.includes(session?.session?.user.id)
|
||||||
|
) {
|
||||||
|
throw new APIError("UNAUTHORIZED");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
session,
|
||||||
|
} as {
|
||||||
|
session: {
|
||||||
|
user: UserWithRole;
|
||||||
|
session: Session;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: "admin",
|
id: "admin",
|
||||||
init(ctx) {
|
init(ctx) {
|
||||||
|
|||||||
Reference in New Issue
Block a user