Skip to content

Commit

Permalink
Merge pull request #43 from agiledigital-labs/IE-19/list-all-users
Browse files Browse the repository at this point in the history
IE-19/list-all-users + add all flag to list users
  • Loading branch information
dspasojevic authored Nov 29, 2023
2 parents ca2ac64 + 7a96d03 commit 5eccc67
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 30 deletions.
16 changes: 10 additions & 6 deletions src/scripts/list-users.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('Listing all users', () => {
};

// When we attempt to list the users from the client
const result = await users(userService)();
const result = await users(userService, false)();

// Then we should have a right
expect(result).toBeRight();
Expand All @@ -44,7 +44,7 @@ describe('Listing all users', () => {
};

// When we attempt to list the users from the client
const result = await users(userService)();
const result = await users(userService, false)();

// Then we should have a left
expect(result).toEqualLeft(new Error('expected error'));
Expand All @@ -71,7 +71,8 @@ describe('Listing users within groups', () => {
const result = await usersInGroup(
userService,
groupService,
test.group.id
test.group.id,
false
)();

// Then we should have a right
Expand Down Expand Up @@ -108,7 +109,8 @@ describe('Listing users within groups', () => {
const result = await usersInGroup(
userService,
groupService,
test.group.id
test.group.id,
false
)();

// Then we should have a left
Expand Down Expand Up @@ -137,7 +139,8 @@ describe('Listing users within groups', () => {
const result = await usersInGroup(
userService,
groupService,
test.group.id
test.group.id,
false
)();

// Then we should have a left
Expand Down Expand Up @@ -166,7 +169,8 @@ describe('Listing users within groups', () => {
const result = await usersInGroup(
userService,
groupService,
test.group.id
test.group.id,
false
)();

// Then we should have a left
Expand Down
46 changes: 29 additions & 17 deletions src/scripts/list-users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { RootCommand } from '..';
import { table } from 'table';
import { OktaUserService, User, UserService } from './services/user-service';
import { oktaReadOnlyClient } from './services/client-service';
import * as okta from '@okta/okta-sdk-nodejs';

import * as TE from 'fp-ts/lib/TaskEither';
import * as E from 'fp-ts/lib/Either';
Expand Down Expand Up @@ -41,17 +42,18 @@ const usersTable = (users: readonly User[]): string => {
);
};

export const users = (service: UserService) =>
export const users = (service: UserService, listAll: boolean) =>
pipe(
service.listUsers(),
service.listUsers(listAll),
TE.map((users) => usersTable(users)),
TE.chainFirstIOK(Console.info)
);

export const usersInGroup = (
userService: UserService,
groupService: GroupService,
groupId: string
groupId: string,
listAll: boolean
) =>
pipe(
groupService.getGroup(groupId),
Expand All @@ -62,7 +64,7 @@ export const usersInGroup = (
(group: Group) => TE.right(group)
)
),
TE.chain(userService.listUsersInGroup),
TE.chain((group) => userService.listUsersInGroup(group, listAll)),
TE.map((users) => usersTable(users)),
TE.chainFirstIOK(Console.info)
);
Expand All @@ -74,40 +76,50 @@ export default (
readonly clientId: string;
readonly privateKey: string;
readonly organisationUrl: string;
readonly all: boolean;
readonly groupId?: string;
}> =>
rootCommand.command(
'list-users',
// eslint-disable-next-line quotes
"Provides a list of all users' ID's, email addresses, display names, and statuses. Allows a specification of a group to list from.",
`Provides a list of all users' ID's, email addresses, display names, and statuses, except for ${okta.UserStatus.DEPROVISIONED} users. Allows a specification of a group to list from.`,
// eslint-disable-next-line functional/no-return-void, @typescript-eslint/prefer-readonly-parameter-types
(yargs) => {
// eslint-disable-next-line functional/no-expression-statement
yargs.positional('group', {
type: 'string',
alias: ['group-id'],
// eslint-disable-next-line quotes
describe: "The group's ID",
});
yargs
.positional('group', {
type: 'string',
alias: ['group-id'],
// eslint-disable-next-line quotes
describe: "The group's ID",
})
.option('all', {
alias: 'all',
type: 'boolean',
describe: `if true, will list all users, including ${okta.UserStatus.DEPROVISIONED} ones`,
demandOption: false,
default: false,
});
},
async (args: {
readonly clientId: string;
readonly privateKey: string;
readonly organisationUrl: string;
readonly all: boolean;
readonly groupId?: string;
}) => {
const { groupId, all } = args;
const client = oktaReadOnlyClient(
{ ...args },
args.groupId === undefined ? ['users'] : ['groups']
groupId === undefined ? ['users'] : ['groups']
);
const userService = new OktaUserService(client);
const groupService = new OktaGroupService(client);

// eslint-disable-next-line functional/no-expression-statement
Console.info(args.groupId);
const result: E.Either<Error, string> = await (args.groupId === undefined
? users(userService)
: usersInGroup(userService, groupService, args.groupId))();
Console.info(groupId);
const result: E.Either<Error, string> = await (groupId === undefined
? users(userService, all)
: usersInGroup(userService, groupService, groupId, all))();

// eslint-disable-next-line functional/no-conditional-statement
if (E.isLeft(result)) {
Expand Down
32 changes: 25 additions & 7 deletions src/scripts/services/user-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,15 @@ export class OktaUserService {
);
};

// eslint-disable-next-line functional/functional-parameters
readonly listUsers = (): TE.TaskEither<Error, readonly User[]> =>
readonly listUsers = (
listAll: boolean
): TE.TaskEither<Error, readonly User[]> =>
// eslint-disable-next-line functional/no-this-expression
this.privateListUsers(TE.right(this.client));
this.privateListUsers(TE.right(this.client), listAll);

readonly listUsersInGroup = (
group: Group
group: Group,
listAll: boolean
): TE.TaskEither<Error, readonly User[]> =>
pipe(
group,
Expand All @@ -129,11 +131,19 @@ export class OktaUserService {
})
),
// eslint-disable-next-line functional/no-this-expression
this.privateListUsers
(group) => this.privateListUsers(group, listAll)
);

/**
* Lists all users in a group or client.
* @param groupOrClient - Either a group or a client
* @param listAl - Whether to list all users or just non-deprovisioned users
* @link https://developer.okta.com/docs/reference/api/users/#list-all-users
* @returns a list of users
*/
readonly privateListUsers = (
groupOrClient: TE.TaskEither<Error, okta.Group | okta.Client>
groupOrClient: TE.TaskEither<Error, okta.Group | okta.Client>,
listAll: boolean
) =>
// We need to populate users with all of the client data so it can be
// returned. Okta's listUsers() function returns a custom collection that
Expand All @@ -146,7 +156,15 @@ export class OktaUserService {
const users: User[] = [];
return (
maybeGroupOrClient
.listUsers()
.listUsers({
// Without this filter, Okta will only return non-deprovisioned users.
// link: https://developer.okta.com/docs/reference/api/users/#list-all-users
filter: listAll
? Object.keys(okta.UserStatus)
.map((status) => `status eq "${status}"`)
.join(' or ')
: undefined,
})
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
.each((oktaUser) => {
// eslint-disable-next-line functional/immutable-data
Expand Down

0 comments on commit 5eccc67

Please sign in to comment.