Skip to content

Commit

Permalink
fix: deleteUsers - add pruning to options enums (#1206)
Browse files Browse the repository at this point in the history
  • Loading branch information
arnautov-anton authored Jan 9, 2024
1 parent 30df2c2 commit c9af1bb
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 15 deletions.
14 changes: 7 additions & 7 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3052,16 +3052,16 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
*
* @return {TaskResponse} A task ID
*/
async deleteUsers(user_ids: string[], options: DeleteUserOptions) {
if (options?.user !== 'soft' && options?.user !== 'hard') {
throw new Error('Invalid delete user options. user must be one of [soft hard]');
async deleteUsers(user_ids: string[], options: DeleteUserOptions = {}) {
if (typeof options.user !== 'undefined' && !['soft', 'hard', 'pruning'].includes(options.user)) {
throw new Error('Invalid delete user options. user must be one of [soft hard pruning]');
}
if (options.messages !== undefined && options.messages !== 'soft' && options.messages !== 'hard') {
throw new Error('Invalid delete user options. messages must be one of [soft hard]');
}
if (options.conversations !== undefined && options.conversations !== 'soft' && options.conversations !== 'hard') {
if (typeof options.conversations !== 'undefined' && !['soft', 'hard'].includes(options.conversations)) {
throw new Error('Invalid delete user options. conversations must be one of [soft hard]');
}
if (typeof options.messages !== 'undefined' && !['soft', 'hard', 'pruning'].includes(options.messages)) {
throw new Error('Invalid delete user options. messages must be one of [soft hard pruning]');
}
return await this.post<APIResponse & TaskResponse>(this.baseURL + `/users/delete`, {
user_ids,
...options,
Expand Down
23 changes: 15 additions & 8 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2365,22 +2365,29 @@ export type DeleteChannelsResponse = {
result: Record<string, string>;
} & Partial<TaskResponse>;

export type DeleteType = 'soft' | 'hard';
export type DeleteType = 'soft' | 'hard' | 'pruning';

/*
DeleteUserOptions specifies a collection of one or more `user_ids` to be deleted.
`user` soft|hard determines if the user needs to be hard- or soft-deleted, where hard-delete
implies that all related objects (messages, flags, etc) will be hard-deleted as well.
`conversations` soft|hard will delete any 1to1 channels that the user was a member of.
`messages` soft-hard will delete any messages that the user has sent.
`new_channel_owner_id` any channels owned by the hard-deleted user will be transferred to this user ID
`user`:
- soft: marks user as deleted and retains all user data
- pruning: marks user as deleted and nullifies user information
- hard: deletes user completely - this requires hard option for messages and conversation as well
`conversations`:
- soft: marks all conversation channels as deleted (same effect as Delete Channels with 'hard' option disabled)
- hard: deletes channel and all its data completely including messages (same effect as Delete Channels with 'hard' option enabled)
`messages`:
- soft: marks all user messages as deleted without removing any related message data
- pruning: marks all user messages as deleted, nullifies message information and removes some message data such as reactions and flags
- hard: deletes messages completely with all related information
`new_channel_owner_id`: any channels owned by the hard-deleted user will be transferred to this user ID
*/
export type DeleteUserOptions = {
user: DeleteType;
conversations?: DeleteType;
conversations?: Exclude<DeleteType, 'pruning'>;
messages?: DeleteType;
new_channel_owner_id?: string;
user?: DeleteType;
};

export type SegmentData = {
Expand Down
43 changes: 43 additions & 0 deletions test/unit/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,49 @@ describe('Detect node environment', () => {
});
});

describe('Client deleteUsers', () => {
it('should allow completely optional options', async () => {
const client = await getClientWithUser();

client.post = () => Promise.resolve();

await expect(client.deleteUsers(['_'])).to.eventually.equal();
});

it('delete types - options.conversations', async () => {
const client = await getClientWithUser();

client.post = () => Promise.resolve();

await expect(client.deleteUsers(['_'], { conversations: 'hard' })).to.eventually.equal();
await expect(client.deleteUsers(['_'], { conversations: 'soft' })).to.eventually.equal();
await expect(client.deleteUsers(['_'], { conversations: 'pruning' })).to.be.rejectedWith();
await expect(client.deleteUsers(['_'], { conversations: '' })).to.be.rejectedWith();
});

it('delete types - options.messages', async () => {
const client = await getClientWithUser();

client.post = () => Promise.resolve();

await expect(client.deleteUsers(['_'], { messages: 'hard' })).to.eventually.equal();
await expect(client.deleteUsers(['_'], { messages: 'soft' })).to.eventually.equal();
await expect(client.deleteUsers(['_'], { messages: 'pruning' })).to.eventually.equal();
await expect(client.deleteUsers(['_'], { messages: '' })).to.be.rejectedWith();
});

it('delete types - options.user', async () => {
const client = await getClientWithUser();

client.post = () => Promise.resolve();

await expect(client.deleteUsers(['_'], { user: 'hard' })).to.eventually.equal();
await expect(client.deleteUsers(['_'], { user: 'soft' })).to.eventually.equal();
await expect(client.deleteUsers(['_'], { user: 'pruning' })).to.eventually.equal();
await expect(client.deleteUsers(['_'], { user: '' })).to.be.rejectedWith();
});
});

describe('updateMessage should ensure sanity of `mentioned_users`', () => {
it('should convert mentioned_users from array of user objects to array of userIds', async () => {
const client = await getClientWithUser();
Expand Down

0 comments on commit c9af1bb

Please sign in to comment.