Skip to content

Commit

Permalink
Add support for batch invite (#273)
Browse files Browse the repository at this point in the history
  • Loading branch information
dorsha authored Nov 2, 2023
1 parent 1a755d6 commit 3f3d66b
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 2 deletions.
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -531,9 +531,9 @@ await descopeClient.management.user.create(
[{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
);

// Alternatively, a user can be created and invited via an email message.
// Alternatively, a user can be created and invited via an email / text message.
// Make sure to configure the invite URL in the Descope console prior to using this function,
// and that an email address is provided in the information.
// and that an email address / phone number is provided in the information.
await descopeClient.management.user.invite(
'[email protected]',
'[email protected]',
Expand All @@ -543,6 +543,23 @@ await descopeClient.management.user.invite(
[{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
);

// You can invite batch of users via an email / text message.
// Make sure to configure the invite URL in the Descope console prior to using this function,
// and that an email address / phone number is provided in the information.
await descopeClient.management.user.inviteBatch(
users: [{
loginId: '[email protected]',
email: '[email protected]',
phone: '+123456789123',
displayName: 'Desmond Copeland',
userTenants: [{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
}
],
sendMail: true,
sendSMS: false,
inviteUrl: "<invite_url>",
);

// Update will override all fields as is. Use carefully.
await descopeClient.management.user.update(
'[email protected]',
Expand Down
1 change: 1 addition & 0 deletions lib/management/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
export default {
user: {
create: '/v1/mgmt/user/create',
createBatch: '/v1/mgmt/user/create/batch',
update: '/v1/mgmt/user/update',
delete: '/v1/mgmt/user/delete',
deleteAllTestUsers: '/v1/mgmt/user/test/delete/all',
Expand Down
26 changes: 26 additions & 0 deletions lib/management/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { UserResponse } from '@descope/core-js-sdk';

/** Represents a tenant association for a User or Access Key. The tenantId is required to denote
* which tenant the user or access key belongs to. The roleNames array is an optional list of
* roles for the user or access key in this specific tenant.
Expand Down Expand Up @@ -159,6 +161,20 @@ export type GenerateEmbeddedLinkResponse = {

export type AttributesTypes = string | boolean | number;

export type User = {
loginId: string;
email?: string;
phone?: string;
displayName?: string;
roles?: string[];
userTenants?: AssociatedTenant[];
customAttributes?: Record<string, AttributesTypes>;
picture?: string;
verifiedEmail?: boolean;
verifiedPhone?: boolean;
test?: boolean;
};

export type UserMapping = {
name: string;
email: string;
Expand Down Expand Up @@ -200,6 +216,16 @@ export type ProviderTokenResponse = {
scopes: string[];
};

export type UserFailedResponse = {
failure: string;
user: UserResponse;
};

export type InviteBatchResponse = {
createdUsers: UserResponse[];
failedUsers: UserFailedResponse[];
};

/**
* Search options to filter which audit records we should retrieve.
* All parameters are optional. `From` is currently limited to 30 days.
Expand Down
61 changes: 61 additions & 0 deletions lib/management/user.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ProviderTokenResponse,
UserStatus,
GenerateEmbeddedLinkResponse,
InviteBatchResponse,
} from './types';

const management = withManagement(mockCoreSdk, 'key');
Expand All @@ -25,6 +26,16 @@ const mockMgmtUsersResponse = {
users: [mockUserResponse],
};

const mockMgmtInviteBatchResponse = {
createdUsers: [{ loginId: 'one', email: 'one@one' }],
failedUsers: [
{
failure: 'some failure',
user: { loginId: 'two', email: 'two@two' },
},
],
};

describe('Management User', () => {
afterEach(() => {
jest.clearAllMocks();
Expand Down Expand Up @@ -225,6 +236,56 @@ describe('Management User', () => {
});
});

describe('invite batch', () => {
it('should send the correct request and receive correct response', async () => {
const httpResponse = {
ok: true,
json: () => mockMgmtInviteBatchResponse,
clone: () => ({
json: () => Promise.resolve(mockMgmtInviteBatchResponse),
}),
status: 200,
};
mockHttpClient.post.mockResolvedValue(httpResponse);

const resp: SdkResponse<InviteBatchResponse> = await management.user.inviteBatch(
[
{ loginId: 'one', email: 'one@one' },
{ loginId: 'two', email: 'two@two' },
],
'https://invite.me',
true,
);

expect(mockHttpClient.post).toHaveBeenCalledWith(
apiPaths.user.createBatch,
{
users: [
{
loginId: 'one',
email: 'one@one',
},
{
loginId: 'two',
email: 'two@two',
},
],
invite: true,
inviteUrl: 'https://invite.me',
sendMail: true,
},
{ token: 'key' },
);

expect(resp).toEqual({
code: 200,
data: mockMgmtInviteBatchResponse,
ok: true,
response: httpResponse,
});
});
});

describe('update', () => {
it('should send the correct request and receive correct response', async () => {
const httpResponse = {
Expand Down
22 changes: 22 additions & 0 deletions lib/management/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
GenerateEmbeddedLinkResponse,
AttributesTypes,
UserStatus,
User,
InviteBatchResponse,
} from './types';
import { CoreSdk } from '../types';
import apiPaths from './paths';
Expand Down Expand Up @@ -132,6 +134,26 @@ const withUser = (sdk: CoreSdk, managementKey?: string) => ({
),
(data) => data.user,
),
inviteBatch: (
users: User[],
inviteUrl?: string,
sendMail?: boolean, // send invite via mail, default is according to project settings
sendSMS?: boolean, // send invite via text message, default is according to project settings
): Promise<SdkResponse<InviteBatchResponse>> =>
transformResponse<InviteBatchResponse, InviteBatchResponse>(
sdk.httpClient.post(
apiPaths.user.createBatch,
{
users,
invite: true,
inviteUrl,
sendMail,
sendSMS,
},
{ token: managementKey },
),
(data) => data,
),
update: (
loginId: string,
email?: string,
Expand Down

0 comments on commit 3f3d66b

Please sign in to comment.