mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-19 11:24:57 -05:00
feat: add getActiveRoleMember (#4484)
Co-authored-by: KinfeMichael Tariku <65047246+Kinfe123@users.noreply.github.com> Co-authored-by: Alex Yang <himself65@outlook.com>
This commit is contained in:
co-authored by
KinfeMichael Tariku
Alex Yang
parent
7faaeac9fc
commit
f6f1902b59
@@ -56,4 +56,6 @@ export const {
|
||||
organization,
|
||||
useListOrganizations,
|
||||
useActiveOrganization,
|
||||
useActiveMember,
|
||||
useActiveMemberRole,
|
||||
} = client;
|
||||
|
||||
@@ -1162,6 +1162,21 @@ To get the current member of the active organization you can use the `organizati
|
||||
```
|
||||
</APIMethod>
|
||||
|
||||
### Get Active Member Role
|
||||
To get the current role member of the active organization you can use the `organization.getActiveMemberRole` function. This function will return the user's member role in their active organization.
|
||||
|
||||
<APIMethod
|
||||
path="/organization/get-active-member-role"
|
||||
method="GET"
|
||||
requireSession
|
||||
resultVariable="{ role }"
|
||||
>
|
||||
```ts
|
||||
type getActiveMemberRole = {
|
||||
}
|
||||
```
|
||||
</APIMethod>
|
||||
|
||||
### Add Member
|
||||
|
||||
If you want to add a member directly to an organization without sending an invitation, you can use the `addMember` function which can only be invoked on the server.
|
||||
|
||||
@@ -64,6 +64,7 @@ export const organizationClient = <CO extends OrganizationClientOptions>(
|
||||
const $listOrg = atom<boolean>(false);
|
||||
const $activeOrgSignal = atom<boolean>(false);
|
||||
const $activeMemberSignal = atom<boolean>(false);
|
||||
const $activeMemberRoleSignal = atom<boolean>(false);
|
||||
|
||||
type DefaultStatements = typeof defaultStatements;
|
||||
type Statements = CO["ac"] extends AccessControl<infer S>
|
||||
@@ -204,13 +205,24 @@ export const organizationClient = <CO extends OrganizationClientOptions>(
|
||||
},
|
||||
);
|
||||
|
||||
const activeMemberRole = useAuthQuery<{ role: string }>(
|
||||
[$activeMemberRoleSignal],
|
||||
"/organization/get-active-member-role",
|
||||
$fetch,
|
||||
{
|
||||
method: "GET",
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
$listOrg,
|
||||
$activeOrgSignal,
|
||||
$activeMemberSignal,
|
||||
$activeMemberRoleSignal,
|
||||
activeOrganization,
|
||||
listOrganizations,
|
||||
activeMember,
|
||||
activeMemberRole,
|
||||
};
|
||||
},
|
||||
pathMethods: {
|
||||
@@ -246,6 +258,12 @@ export const organizationClient = <CO extends OrganizationClientOptions>(
|
||||
},
|
||||
signal: "$activeMemberSignal",
|
||||
},
|
||||
{
|
||||
matcher(path) {
|
||||
return path.includes("/organization/update-member-role");
|
||||
},
|
||||
signal: "$activeMemberRoleSignal",
|
||||
},
|
||||
],
|
||||
} satisfies BetterAuthClientPlugin;
|
||||
};
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
listMembers,
|
||||
removeMember,
|
||||
updateMemberRole,
|
||||
getActiveMemberRole,
|
||||
} from "./routes/crud-members";
|
||||
import {
|
||||
checkOrganizationSlug,
|
||||
@@ -405,6 +406,22 @@ export const organization = <O extends OrganizationOptions>(options?: O) => {
|
||||
* `authClient.organization.listMembers`
|
||||
*/
|
||||
listMembers: listMembers(options as O),
|
||||
/**
|
||||
* ### Endpoint
|
||||
*
|
||||
* GET `/organization/get-active-member-role`
|
||||
*
|
||||
* ### API Methods
|
||||
*
|
||||
* **server:**
|
||||
* `auth.api.getActiveMemberRole`
|
||||
*
|
||||
* **client:**
|
||||
* `authClient.organization.getActiveMemberRole`
|
||||
*
|
||||
* @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/organization#api-method-organization-get-active-member-role)
|
||||
*/
|
||||
getActiveMemberRole: getActiveMemberRole(options as O),
|
||||
};
|
||||
const teamSupport = options?.teams?.enabled;
|
||||
const teamEndpoints = {
|
||||
|
||||
@@ -333,3 +333,100 @@ describe("updateMemberRole", async () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("activeMemberRole", async () => {
|
||||
const { auth, signInWithTestUser, cookieSetter } = await getTestInstance({
|
||||
plugins: [organization()],
|
||||
});
|
||||
const ctx = await auth.$context;
|
||||
const { headers } = await signInWithTestUser();
|
||||
const client = createAuthClient({
|
||||
plugins: [organizationClient()],
|
||||
baseURL: "http://localhost:3000/api/auth",
|
||||
fetchOptions: {
|
||||
customFetchImpl: async (url, init) => {
|
||||
return auth.handler(new Request(url, init));
|
||||
},
|
||||
},
|
||||
});
|
||||
const org = await client.organization.create({
|
||||
name: "test",
|
||||
slug: "test",
|
||||
metadata: {
|
||||
test: "test",
|
||||
},
|
||||
fetchOptions: {
|
||||
headers,
|
||||
},
|
||||
});
|
||||
const secondOrg = await client.organization.create({
|
||||
name: "test-second",
|
||||
slug: "test-second",
|
||||
metadata: {
|
||||
test: "second-org",
|
||||
},
|
||||
fetchOptions: {
|
||||
headers,
|
||||
},
|
||||
});
|
||||
|
||||
let selectedUserId = "";
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const user = await ctx.adapter.create({
|
||||
model: "user",
|
||||
data: {
|
||||
email: `test${i}@test.com`,
|
||||
name: `test${i}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (i == 0) {
|
||||
selectedUserId = user.id;
|
||||
}
|
||||
|
||||
await auth.api.addMember({
|
||||
body: {
|
||||
organizationId: org.data?.id as string,
|
||||
userId: user.id,
|
||||
role: "member",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
it("should return the active member role on active organization", async () => {
|
||||
await client.organization.setActive({
|
||||
organizationId: org.data?.id as string,
|
||||
fetchOptions: {
|
||||
headers,
|
||||
},
|
||||
});
|
||||
|
||||
const activeMember = await client.organization.getActiveMemberRole({
|
||||
fetchOptions: {
|
||||
headers,
|
||||
},
|
||||
});
|
||||
|
||||
expect(activeMember.data?.role).toBe("owner");
|
||||
});
|
||||
|
||||
it("should return active member role on organization", async () => {
|
||||
await client.organization.setActive({
|
||||
organizationId: org.data?.id as string,
|
||||
fetchOptions: {
|
||||
headers,
|
||||
},
|
||||
});
|
||||
|
||||
const activeMember = await client.organization.getActiveMemberRole({
|
||||
query: {
|
||||
userId: selectedUserId,
|
||||
},
|
||||
fetchOptions: {
|
||||
headers,
|
||||
},
|
||||
});
|
||||
|
||||
expect(activeMember.data?.role).toBe("member");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -904,3 +904,60 @@ export const listMembers = <O extends OrganizationOptions>(options: O) =>
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export const getActiveMemberRole = <O extends OrganizationOptions>(
|
||||
options: O,
|
||||
) =>
|
||||
createAuthEndpoint(
|
||||
"/organization/get-active-member-role",
|
||||
{
|
||||
method: "GET",
|
||||
query: z
|
||||
.object({
|
||||
userId: z
|
||||
.string()
|
||||
.meta({
|
||||
description:
|
||||
"The user ID to get the role for. If not provided, will default to the current user's",
|
||||
})
|
||||
.optional(),
|
||||
organizationId: z
|
||||
.string()
|
||||
.meta({
|
||||
description:
|
||||
'The organization ID to list members for. If not provided, will default to the user\'s active organization. Eg: "organization-id"',
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
.optional(),
|
||||
use: [orgMiddleware, orgSessionMiddleware],
|
||||
},
|
||||
async (ctx) => {
|
||||
const session = ctx.context.session;
|
||||
const organizationId =
|
||||
ctx.query?.organizationId || session.session.activeOrganizationId;
|
||||
if (!organizationId) {
|
||||
throw new APIError("BAD_REQUEST", {
|
||||
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION,
|
||||
});
|
||||
}
|
||||
const userId = ctx.query?.userId || session.user.id;
|
||||
|
||||
const adapter = getOrgAdapter<O>(ctx.context, options);
|
||||
|
||||
const member = await adapter.findMemberByOrgId({
|
||||
userId,
|
||||
organizationId,
|
||||
});
|
||||
if (!member) {
|
||||
throw new APIError("FORBIDDEN", {
|
||||
message:
|
||||
ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION,
|
||||
});
|
||||
}
|
||||
|
||||
return ctx.json({
|
||||
role: member?.role,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user