Skip to content

Commit e20d61a

Browse files
committed
feat(backend): Introduce OrganizationPermissionAPI (#2178)
1 parent e61df05 commit e20d61a

File tree

14 files changed

+124
-1
lines changed

14 files changed

+124
-1
lines changed

.changeset/swift-rocks-nail.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@clerk/clerk-sdk-node': patch
3+
'@clerk/backend': patch
4+
'@clerk/nextjs': patch
5+
---
6+
7+
Add OrganizationPermissionAPI for CRUD operations regarding instance level organization permissions.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { joinPaths } from '../../util/path';
2+
import type { DeletedObject, Permission } from '../resources';
3+
import { AbstractAPI } from './AbstractApi';
4+
5+
const basePath = '/organizations_permissions';
6+
7+
type GetOrganizationPermissionListParams = {
8+
limit?: number;
9+
offset?: number;
10+
query?: string;
11+
orderBy?: string;
12+
};
13+
14+
type CreateParams = {
15+
name: string;
16+
key: string;
17+
description: string;
18+
};
19+
20+
type GetOrganizationPermissionParams = { permissionId: string };
21+
22+
type UpdateParams = {
23+
name?: string;
24+
key?: string;
25+
description?: string;
26+
};
27+
28+
export class OrganizationPermissionAPI extends AbstractAPI {
29+
public async getOrganizationPermissionList(params?: GetOrganizationPermissionListParams) {
30+
return this.request<Permission[]>({
31+
method: 'GET',
32+
path: basePath,
33+
queryParams: params,
34+
});
35+
}
36+
37+
public async createOrganizationPermission(params: CreateParams) {
38+
return this.request<Permission>({
39+
method: 'POST',
40+
path: basePath,
41+
bodyParams: params,
42+
});
43+
}
44+
45+
public async getOrganizationPermission(params: GetOrganizationPermissionParams) {
46+
this.requireId(params.permissionId);
47+
48+
return this.request<Permission>({
49+
method: 'GET',
50+
path: joinPaths(basePath, params.permissionId),
51+
});
52+
}
53+
54+
public async updateOrganizationPermission(permissionId: string, params: UpdateParams) {
55+
this.requireId(permissionId);
56+
return this.request<Permission>({
57+
method: 'PATCH',
58+
path: joinPaths(basePath, permissionId),
59+
bodyParams: params,
60+
});
61+
}
62+
63+
public async deleteOrganizationPermission(permissionId: string) {
64+
return this.request<DeletedObject>({
65+
method: 'DELETE',
66+
path: joinPaths(basePath, permissionId),
67+
});
68+
}
69+
}

packages/backend/src/api/endpoints/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export * from './EmailApi';
77
export * from './InterstitialApi';
88
export * from './InvitationApi';
99
export * from './OrganizationApi';
10+
export * from './OrganizationPermissionApi';
1011
export * from './PhoneNumberApi';
1112
export * from './RedirectUrlApi';
1213
export * from './SessionApi';

packages/backend/src/api/factory.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
InterstitialAPI,
88
InvitationAPI,
99
OrganizationAPI,
10+
OrganizationPermissionAPI,
1011
PhoneNumberAPI,
1112
RedirectUrlAPI,
1213
SessionAPI,
@@ -41,7 +42,6 @@ export type ApiClient = ReturnType<typeof createBackendApiClient>;
4142

4243
export function createBackendApiClient(options: CreateBackendApiOptions) {
4344
const request = buildRequest(options);
44-
4545
return {
4646
allowlistIdentifiers: new AllowlistIdentifierAPI(request),
4747
clients: new ClientAPI(request),
@@ -50,6 +50,7 @@ export function createBackendApiClient(options: CreateBackendApiOptions) {
5050
interstitial: new InterstitialAPI(request),
5151
invitations: new InvitationAPI(request),
5252
organizations: new OrganizationAPI(request),
53+
organizationPermissions: new OrganizationPermissionAPI(request),
5354
phoneNumbers: new PhoneNumberAPI(request),
5455
redirectUrls: new RedirectUrlAPI(request),
5556
sessions: new SessionAPI(request),

packages/backend/src/api/resources/Enums.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ export type OAuthStrategy = `oauth_${OAuthProvider}`;
2020

2121
export type OrganizationInvitationStatus = 'pending' | 'accepted' | 'revoked';
2222

23+
export type PermissionType = 'system' | 'user';
24+
25+
/**
26+
* @deprecated In the next major release this type will change to string
27+
*/
2328
export type OrganizationMembershipRole = 'basic_member' | 'guest_member' | 'admin';
2429

2530
export type SignInStatus = 'needs_identifier' | 'needs_factor_one' | 'needs_factor_two' | 'complete';

packages/backend/src/api/resources/JSON.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {
22
InvitationStatus,
33
OrganizationInvitationStatus,
44
OrganizationMembershipRole,
5+
PermissionType,
56
SignInStatus,
67
SignUpAttributeRequirements,
78
SignUpStatus,
@@ -20,6 +21,7 @@ export enum ObjectType {
2021
Organization = 'organization',
2122
OrganizationInvitation = 'organization_invitation',
2223
OrganizationMembership = 'organization_membership',
24+
Permission = 'permission',
2325
PhoneNumber = 'phone_number',
2426
RedirectUrl = 'redirect_url',
2527
Session = 'session',
@@ -184,6 +186,17 @@ export interface OrganizationMembershipPublicUserDataJSON {
184186
user_id: string;
185187
}
186188

189+
export interface PermissionJSON extends ClerkResourceJSON {
190+
object: ObjectType.Permission;
191+
id: string;
192+
name: string;
193+
key: string;
194+
description: string;
195+
type: PermissionType;
196+
created_at: number;
197+
updated_at: number;
198+
}
199+
187200
export interface PhoneNumberJSON extends ClerkResourceJSON {
188201
object: ObjectType.PhoneNumber;
189202
phone_number: string;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { PermissionType } from './Enums';
2+
import type { PermissionJSON } from './JSON';
3+
4+
export class Permission {
5+
constructor(
6+
readonly id: string,
7+
readonly name: string,
8+
readonly key: string,
9+
readonly description: string,
10+
readonly type: PermissionType,
11+
readonly createdAt: number,
12+
readonly updatedAt: number,
13+
) {}
14+
15+
static fromJSON(data: PermissionJSON) {
16+
return new Permission(data.id, data.name, data.key, data.description, data.type, data.created_at, data.updated_at);
17+
}
18+
}

packages/backend/src/api/resources/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export * from './Invitation';
2222
export * from './JSON';
2323
export * from './OauthAccessToken';
2424
export * from './Organization';
25+
export * from './Permission';
2526
export * from './OrganizationInvitation';
2627
export * from './OrganizationMembership';
2728
export * from './PhoneNumber';

packages/backend/src/exports.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export default (QUnit: QUnit) => {
2424
'OrganizationInvitation',
2525
'OrganizationMembership',
2626
'OrganizationMembershipPublicUserData',
27+
'Permission',
2728
'PhoneNumber',
2829
'RedirectUrl',
2930
'SMSMessage',

packages/nextjs/src/api/__tests__/__snapshots__/exports.test.ts.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ exports[`/api public exports should not include a breaking change 1`] = `
1818
"OrganizationInvitation",
1919
"OrganizationMembership",
2020
"OrganizationMembershipPublicUserData",
21+
"Permission",
2122
"PhoneNumber",
2223
"RedirectUrl",
2324
"SMSMessage",

0 commit comments

Comments
 (0)