Skip to content

Commit

Permalink
Add role to directory user (#1046)
Browse files Browse the repository at this point in the history
## Description
Introduce roles to directory sync users for a beta release.

## Documentation

Does this require changes to the WorkOS Docs? E.g. the [API
Reference](https://workos.com/docs/reference) or code snippets need
updates.

```
[ ] Yes
```

If yes, link a related docs PR and add a docs maintainer as a reviewer.
Their approval is required.
  • Loading branch information
tribble authored May 21, 2024
1 parent 84038cf commit 8b2f642
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/common/interfaces/event.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
import {
RoleEvent,
RoleEventResponse,
} from '../../user-management/interfaces/role.interface';
} from '../../roles/interfaces/role.interface';

export interface EventBase {
id: string;
Expand Down
68 changes: 68 additions & 0 deletions src/directory-sync/directory-sync.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,62 @@ describe('DirectorySync', () => {
updated_at: '2021-12-13 12:15:45.531847',
};

const userWithRole: DirectoryUserWithGroups = {
object: 'directory_user',
id: 'directory_user_456',
customAttributes: {
custom: true,
},
directoryId: 'dir_123',
organizationId: 'org_123',
emails: [
{
primary: true,
type: 'type',
value: '[email protected]',
},
],
firstName: 'Jon',
groups: [group],
idpId: 'idp_foo',
lastName: 'Snow',
jobTitle: 'Knight of the Watch',
rawAttributes: {},
state: 'active',
username: 'jonsnow',
role: { slug: 'super_admin' },
createdAt: '2021-10-27 15:21:50.640959',
updatedAt: '2021-12-13 12:15:45.531847',
};

const userWithRoleResponse: DirectoryUserWithGroupsResponse = {
object: 'directory_user',
id: 'directory_user_456',
custom_attributes: {
custom: true,
},
directory_id: 'dir_123',
organization_id: 'org_123',
emails: [
{
primary: true,
type: 'type',
value: '[email protected]',
},
],
first_name: 'Jon',
groups: [groupResponse],
idp_id: 'idp_foo',
last_name: 'Snow',
job_title: 'Knight of the Watch',
raw_attributes: {},
state: 'active',
username: 'jonsnow',
role: { slug: 'super_admin' },
created_at: '2021-10-27 15:21:50.640959',
updated_at: '2021-12-13 12:15:45.531847',
};

describe('listDirectories', () => {
describe('with options', () => {
it('requests Directories with query parameters', async () => {
Expand Down Expand Up @@ -404,5 +460,17 @@ describe('DirectorySync', () => {

expect(subject).toEqual(userWithGroup);
});

describe('with a Role', () => {
it(`requests a Directory User`, async () => {
fetchOnce(userWithRoleResponse);

const subject = await workos.directorySync.getUser(
'directory_user_456',
);

expect(subject).toEqual(userWithRole);
});
});
});
});
3 changes: 3 additions & 0 deletions src/directory-sync/interfaces/directory-user.interface.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { RoleResponse } from '../../roles/interfaces/';
import {
DirectoryGroup,
DirectoryGroupResponse,
Expand Down Expand Up @@ -26,6 +27,7 @@ export interface DirectoryUser<
lastName: string | null;
jobTitle: string | null;
state: 'active' | 'inactive';
role?: RoleResponse;
createdAt: string;
updatedAt: string;
}
Expand All @@ -51,6 +53,7 @@ export interface DirectoryUserResponse<
last_name: string | null;
job_title: string | null;
state: 'active' | 'inactive';
role?: RoleResponse;
created_at: string;
updated_at: string;
}
Expand Down
2 changes: 2 additions & 0 deletions src/directory-sync/serializers/directory-user.serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const deserializeDirectoryUser = <
lastName: directoryUser.last_name,
jobTitle: directoryUser.job_title,
state: directoryUser.state,
role: directoryUser.role,
createdAt: directoryUser.created_at,
updatedAt: directoryUser.updated_at,
});
Expand Down Expand Up @@ -56,6 +57,7 @@ export const deserializeUpdatedEventDirectoryUser = (
lastName: directoryUser.last_name,
jobTitle: directoryUser.job_title,
state: directoryUser.state,
role: directoryUser.role,
createdAt: directoryUser.created_at,
updatedAt: directoryUser.updated_at,
previousAttributes: directoryUser.previous_attributes,
Expand Down
100 changes: 99 additions & 1 deletion src/events/events.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import fetch from 'jest-fetch-mock';
import { fetchOnce, fetchSearchParams } from '../common/utils/test-utils';
import { Event, EventResponse, ListResponse } from '../common/interfaces';
import {
DsyncUserUpdatedEvent,
DsyncUserUpdatedEventResponse,
Event,
EventResponse,
ListResponse,
} from '../common/interfaces';
import { WorkOS } from '../workos';
import { ConnectionType } from '../sso/interfaces';

Expand Down Expand Up @@ -108,5 +114,97 @@ describe('Event', () => {
listMetadata: {},
});
});

describe('directory user updated events', () => {
describe('with a role', () => {
const directoryUserUpdated: DsyncUserUpdatedEvent = {
id: 'event_01234ABCD',
createdAt: '2020-05-06 04:21:48.649164',
event: 'dsync.user.updated',
data: {
object: 'directory_user',
id: 'directory_user_456',
customAttributes: {
custom: true,
},
directoryId: 'dir_123',
organizationId: 'org_123',
emails: [
{
primary: true,
type: 'type',
value: '[email protected]',
},
],
firstName: 'Jon',
idpId: 'idp_foo',
lastName: 'Snow',
jobTitle: 'Knight of the Watch',
rawAttributes: {},
state: 'active',
username: 'jonsnow',
role: { slug: 'super_admin' },
previousAttributes: {
role: { slug: 'member' },
},
createdAt: '2021-10-27 15:21:50.640959',
updatedAt: '2021-12-13 12:15:45.531847',
},
};

const directoryUserUpdatedResponse: DsyncUserUpdatedEventResponse = {
id: 'event_01234ABCD',
created_at: '2020-05-06 04:21:48.649164',
event: 'dsync.user.updated',
data: {
object: 'directory_user',
id: 'directory_user_456',
custom_attributes: {
custom: true,
},
directory_id: 'dir_123',
organization_id: 'org_123',
emails: [
{
primary: true,
type: 'type',
value: '[email protected]',
},
],
first_name: 'Jon',
idp_id: 'idp_foo',
last_name: 'Snow',
job_title: 'Knight of the Watch',
raw_attributes: {},
state: 'active',
username: 'jonsnow',
role: { slug: 'super_admin' },
previous_attributes: {
role: { slug: 'member' },
},
created_at: '2021-10-27 15:21:50.640959',
updated_at: '2021-12-13 12:15:45.531847',
},
};
const directoryUserEventsListResponse: ListResponse<EventResponse> = {
object: 'list',
data: [directoryUserUpdatedResponse],
list_metadata: {},
};
it(`returns the role`, async () => {
fetchOnce(directoryUserEventsListResponse);

const list = await workos.events.listEvents({
events: ['dsync.user.updated'],
});

expect(list).toEqual({
object: 'list',
data: [directoryUserUpdated],
listMetadata: {},
});
});
});
});
});
});
1 change: 1 addition & 0 deletions src/roles/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './role.interface';
File renamed without changes.
2 changes: 0 additions & 2 deletions src/user-management/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export * from './magic-auth.interface';
export * from './organization-membership.interface';
export * from './reset-password-options.interface';
export * from './revoke-session-options.interface';
export * from './role.interface';
export * from './send-invitation-options.interface';
export * from './send-magic-auth-code-options.interface';
export * from './send-password-reset-email-options.interface';
Expand All @@ -35,4 +34,3 @@ export * from './update-user-options.interface';
export * from './update-user-password-options.interface';
export * from './user.interface';
export * from './verify-email-options.interface';
export * from './role.interface';
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RoleResponse } from './role.interface';
import { RoleResponse } from '../../roles/interfaces/';

export type OrganizationMembershipStatus = 'active' | 'inactive' | 'pending';

Expand Down
2 changes: 1 addition & 1 deletion src/user-management/serializers/role.serializer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RoleEvent, RoleEventResponse } from '../interfaces';
import { RoleEvent, RoleEventResponse } from '../../roles/interfaces';

export const deserializeRole = (role: RoleEventResponse): RoleEvent => ({
object: 'role',
Expand Down

0 comments on commit 8b2f642

Please sign in to comment.