Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: deleteUsers - add pruning to options enums #1206

Merged
merged 1 commit into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
arnautov-anton marked this conversation as resolved.
Show resolved Hide resolved
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
Loading