jackson/npm/src/directory-sync/scim/Users.ts

232 lines
5.7 KiB
TypeScript

import type { User, DatabaseStore, PaginationParams, Response, Records } from '../../typings';
import { apiError, JacksonError } from '../../controller/error';
import { Base } from './Base';
import { keyFromParts } from '../../db/utils';
import { indexNames } from './utils';
/**
* @swagger
* definitions:
* User:
* type: object
* properties:
* id:
* type: string
* description: User ID
* first_name:
* type: string
* description: First name
* last_name:
* type: string
* description: Last name
* email:
* type: string
* description: Email address
* active:
* type: boolean
* description: Indicates whether the user is active or not
* raw:
* type: object
* description: Raw user attributes from the Identity Provider
*/
export class Users extends Base {
constructor({ db }: { db: DatabaseStore }) {
super({ db });
}
// Create a new user
public async create(user: User & { directoryId: string }): Promise<Response<User>> {
const { directoryId, id, email } = user;
try {
await this.store('users').put(
id,
user,
{
name: indexNames.directoryIdUsername,
value: keyFromParts(directoryId, email),
},
{
name: indexNames.directoryId,
value: directoryId,
}
);
return { data: user, error: null };
} catch (err: any) {
return apiError(err);
}
}
/**
* @swagger
* /api/v1/dsync/users/{userId}:
* get:
* summary: Get user by id from a directory
* parameters:
* - $ref: '#/parameters/tenant'
* - $ref: '#/parameters/product'
* - name: userId
* description: User ID
* in: path
* required: true
* type: string
* tags:
* - Directory Sync
* produces:
* - application/json
* responses:
* 200:
* description: Success
* schema:
* $ref: '#/definitions/User'
*/
public async get(id: string): Promise<Response<User>> {
try {
const user = await this.store('users').get(id);
if (user === null) {
throw new JacksonError('User not found', 404);
}
return { data: user, error: null };
} catch (err: any) {
return apiError(err);
}
}
// Update the user data
public async update(id: string, user: User): Promise<Response<User>> {
const { raw } = user;
raw['id'] = id;
const updatedUser = {
...user,
raw,
};
try {
await this.store('users').put(id, updatedUser);
return { data: updatedUser, error: null };
} catch (err: any) {
return apiError(err);
}
}
// Delete a user by id
public async delete(id: string): Promise<Response<null>> {
try {
const { data, error } = await this.get(id);
if (error || !data) {
throw error;
}
await this.store('users').delete(id);
return { data: null, error: null };
} catch (err: any) {
return apiError(err);
}
}
// Search users by userName
public async search(userName: string, directoryId: string): Promise<Response<User[]>> {
try {
const { data: users } = await this.store('users').getByIndex({
name: indexNames.directoryIdUsername,
value: keyFromParts(directoryId, userName),
});
return { data: users, error: null };
} catch (err: any) {
return apiError(err);
}
}
/**
* @swagger
* /api/v1/dsync/users:
* get:
* summary: Get users from a directory
* parameters:
* - $ref: '#/parameters/tenant'
* - $ref: '#/parameters/product'
* - $ref: '#/parameters/directoryId'
* - $ref: '#/parameters/pageOffset'
* - $ref: '#/parameters/pageLimit'
* - $ref: '#/parameters/pageToken'
* tags:
* - Directory Sync
* produces:
* - application/json
* responses:
* 200:
* description: Success
* content:
* application/json:
* schema:
* type: object
* properties:
* data:
* type: array
* items:
* $ref: '#/definitions/User'
* pageToken:
* type: string
* description: token for pagination
*/
public async getAll({
pageOffset,
pageLimit,
pageToken,
directoryId,
}: PaginationParams & {
directoryId?: string;
} = {}): Promise<Response<User[]>> {
try {
let result: Records;
// Filter by directoryId
if (directoryId) {
result = await this.store('users').getByIndex(
{
name: indexNames.directoryId,
value: directoryId,
},
pageOffset,
pageLimit,
pageToken
);
} else {
result = await this.store('users').getAll(pageOffset, pageLimit, pageToken);
}
return { data: result.data, error: null, pageToken: result.pageToken };
} catch (err: any) {
return apiError(err);
}
}
// Delete all users from a directory
async deleteAll(directoryId: string) {
// eslint-disable-next-line no-constant-condition
while (true) {
const { data: users } = await this.store('users').getByIndex(
{
name: indexNames.directoryId,
value: directoryId,
},
0,
this.bulkDeleteBatchSize
);
if (!users || users.length === 0) {
break;
}
await this.store('users').deleteMany(users.map((user) => user.id));
}
}
}