diff --git a/packages/better-auth/src/plugins/organization/routes/crud-access-control.ts b/packages/better-auth/src/plugins/organization/routes/crud-access-control.ts index cf010e2d..e7ff075c 100644 --- a/packages/better-auth/src/plugins/organization/routes/crud-access-control.ts +++ b/packages/better-auth/src/plugins/organization/routes/crud-access-control.ts @@ -292,12 +292,12 @@ export const deleteOrgRole = (options: O) => { .and( z.union([ z.object({ - roleName: z.string().meta({ + roleName: z.string().nonempty().meta({ description: "The name of the role to delete", }), }), z.object({ - roleId: z.string().meta({ + roleId: z.string().nonempty().meta({ description: "The id of the role to delete", }), }), @@ -307,14 +307,11 @@ export const deleteOrgRole = (options: O) => { use: [orgSessionMiddleware], metadata: { $Infer: { - body: {} as ( - | { - roleName: string; - } - | { - roleId: string; - } - ) & { organizationId?: string | undefined }, + body: {} as { + roleName?: string | undefined; + roleId?: string | undefined; + organizationId?: string | undefined; + }, }, }, }, @@ -392,7 +389,7 @@ export const deleteOrgRole = (options: O) => { }); } - if ("roleName" in ctx.body) { + if (ctx.body.roleName) { const roleName = ctx.body.roleName; const defaultRoles = options.roles ? Object.keys(options.roles) @@ -413,20 +410,29 @@ export const deleteOrgRole = (options: O) => { } let condition: Where; - if ("roleName" in ctx.body) { + if (ctx.body.roleName) { condition = { field: "role", value: ctx.body.roleName, operator: "eq", connector: "AND", }; - } else { + } else if (ctx.body.roleId) { condition = { field: "id", value: ctx.body.roleId, operator: "eq", connector: "AND", }; + } else { + // shouldn't be able to reach here given the schema validation. + // But just in case, throw an error. + ctx.context.logger.error( + `[Dynamic Access Control] The role name/id is not provided in the request body.`, + ); + throw new APIError("BAD_REQUEST", { + message: ORGANIZATION_ERROR_CODES.ROLE_NOT_FOUND, + }); } const existingRoleInDB = await ctx.context.adapter.findOne({ @@ -619,12 +625,12 @@ export const getOrgRole = (options: O) => { .and( z.union([ z.object({ - roleName: z.string().meta({ + roleName: z.string().nonempty().meta({ description: "The name of the role to read", }), }), z.object({ - roleId: z.string().meta({ + roleId: z.string().nonempty().meta({ description: "The id of the role to read", }), }), @@ -635,7 +641,9 @@ export const getOrgRole = (options: O) => { $Infer: { query: {} as { organizationId?: string | undefined; - } & ({ roleName: string } | { roleId: string }), + roleName?: string | undefined; + roleId?: string | undefined; + }, }, }, }, @@ -710,20 +718,29 @@ export const getOrgRole = (options: O) => { } let condition: Where; - if ("roleName" in ctx.query) { + if (ctx.query.roleName) { condition = { field: "role", value: ctx.query.roleName, operator: "eq", connector: "AND", }; - } else { + } else if (ctx.query.roleId) { condition = { field: "id", value: ctx.query.roleId, operator: "eq", connector: "AND", }; + } else { + // shouldn't be able to reach here given the schema validation. + // But just in case, throw an error. + ctx.context.logger.error( + `[Dynamic Access Control] The role name/id is not provided in the request query.`, + ); + throw new APIError("BAD_REQUEST", { + message: ORGANIZATION_ERROR_CODES.ROLE_NOT_FOUND, + }); } let role = await ctx.context.adapter.findOne({ model: "organizationRole", @@ -791,12 +808,12 @@ export const updateOrgRole = (options: O) => { .and( z.union([ z.object({ - roleName: z.string().meta({ + roleName: z.string().nonempty().meta({ description: "The name of the role to update", }), }), z.object({ - roleId: z.string().meta({ + roleId: z.string().nonempty().meta({ description: "The id of the role to update", }), }), @@ -810,7 +827,9 @@ export const updateOrgRole = (options: O) => { permission?: Record | undefined; roleName?: string | undefined; } & AdditionalFields; - } & ({ roleName: string } | { roleId: string }), + roleName?: string | undefined; + roleId?: string | undefined; + }, }, }, use: [orgSessionMiddleware], @@ -893,20 +912,29 @@ export const updateOrgRole = (options: O) => { } let condition: Where; - if ("roleName" in ctx.body) { + if (ctx.body.roleName) { condition = { field: "role", value: ctx.body.roleName, operator: "eq", connector: "AND", }; - } else { + } else if (ctx.body.roleId) { condition = { field: "id", value: ctx.body.roleId, operator: "eq", connector: "AND", }; + } else { + // shouldn't be able to reach here given the schema validation. + // But just in case, throw an error. + ctx.context.logger.error( + `[Dynamic Access Control] The role name/id is not provided in the request body.`, + ); + throw new APIError("BAD_REQUEST", { + message: ORGANIZATION_ERROR_CODES.ROLE_NOT_FOUND, + }); } let role = await ctx.context.adapter.findOne({ model: "organizationRole",