mirror of https://github.com/boxyhq/jackson.git
232 lines
5.7 KiB
TypeScript
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));
|
|
}
|
|
}
|
|
}
|