Skip to content

Commit 1ca92c3

Browse files
feat: Add OpenAPI Support to dm.delete/im.delete API (#36677)
1 parent 7a68627 commit 1ca92c3

File tree

6 files changed

+86
-63
lines changed

6 files changed

+86
-63
lines changed

.changeset/shy-vans-juggle.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@rocket.chat/meteor": patch
3+
"@rocket.chat/rest-typings": patch
4+
---
5+
6+
Add OpenAPI support for the Rocket.Chat dm.delete/im.delete API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation.

apps/meteor/app/api/server/v1/im.ts

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import type { IMessage, IRoom, ISubscription, IUser } from '@rocket.chat/core-typings';
55
import { Subscriptions, Uploads, Messages, Rooms, Users } from '@rocket.chat/models';
66
import {
7-
isDmDeleteProps,
7+
ajv,
8+
validateUnauthorizedErrorResponse,
9+
validateBadRequestErrorResponse,
810
isDmFileProps,
911
isDmMemberProps,
1012
isDmMessagesProps,
@@ -26,7 +28,9 @@ import { getRoomByNameOrIdWithOptionToJoin } from '../../../lib/server/functions
2628
import { getChannelHistory } from '../../../lib/server/methods/getChannelHistory';
2729
import { settings } from '../../../settings/server';
2830
import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser';
31+
import type { ExtractRoutesFromAPI } from '../ApiClass';
2932
import { API } from '../api';
33+
import type { TypedAction } from '../definition';
3034
import { addUserToFileObj } from '../helpers/addUserToFileObj';
3135
import { composeRoomWithLastMessage } from '../helpers/composeRoomWithLastMessage';
3236
import { getPaginationItems } from '../helpers/getPaginationItems';
@@ -87,28 +91,78 @@ API.v1.addRoute(
8791
},
8892
);
8993

90-
API.v1.addRoute(
91-
['dm.delete', 'im.delete'],
92-
{
93-
authRequired: true,
94-
validateParams: isDmDeleteProps,
94+
type DmDeleteProps =
95+
| {
96+
roomId: string;
97+
}
98+
| {
99+
username: string;
100+
};
101+
102+
const isDmDeleteProps = ajv.compile<DmDeleteProps>({
103+
oneOf: [
104+
{
105+
type: 'object',
106+
properties: {
107+
roomId: {
108+
type: 'string',
109+
},
110+
},
111+
required: ['roomId'],
112+
additionalProperties: false,
113+
},
114+
{
115+
type: 'object',
116+
properties: {
117+
username: {
118+
type: 'string',
119+
},
120+
},
121+
required: ['username'],
122+
additionalProperties: false,
123+
},
124+
],
125+
});
126+
127+
const dmDeleteEndpointsProps = {
128+
authRequired: true,
129+
body: isDmDeleteProps,
130+
response: {
131+
400: validateBadRequestErrorResponse,
132+
401: validateUnauthorizedErrorResponse,
133+
200: ajv.compile<void>({
134+
type: 'object',
135+
properties: {
136+
success: {
137+
type: 'boolean',
138+
enum: [true],
139+
},
140+
},
141+
required: ['success'],
142+
additionalProperties: false,
143+
}),
95144
},
96-
{
97-
async post() {
98-
const { room } = await findDirectMessageRoom(this.bodyParams, this.userId);
145+
} as const;
99146

100-
const canAccess =
101-
(await canAccessRoomIdAsync(room._id, this.userId)) || (await hasPermissionAsync(this.userId, 'view-room-administration'));
102-
if (!canAccess) {
103-
throw new Meteor.Error('error-not-allowed', 'Not allowed');
104-
}
147+
const dmDeleteAction = <Path extends string>(_path: Path): TypedAction<typeof dmDeleteEndpointsProps, Path> =>
148+
async function action() {
149+
const { room } = await findDirectMessageRoom(this.bodyParams, this.userId);
105150

106-
await eraseRoom(room._id, this.userId);
151+
const canAccess =
152+
(await canAccessRoomIdAsync(room._id, this.userId)) || (await hasPermissionAsync(this.userId, 'view-room-administration'));
107153

108-
return API.v1.success();
109-
},
110-
},
111-
);
154+
if (!canAccess) {
155+
throw new Meteor.Error('error-not-allowed', 'Not allowed');
156+
}
157+
158+
await eraseRoom(room._id, this.userId);
159+
160+
return API.v1.success();
161+
};
162+
163+
const dmEndpoints = API.v1
164+
.post('im.delete', dmDeleteEndpointsProps, dmDeleteAction('im.delete'))
165+
.post('dm.delete', dmDeleteEndpointsProps, dmDeleteAction('dm.delete'));
112166

113167
API.v1.addRoute(
114168
['dm.close', 'im.close'],
@@ -589,3 +643,10 @@ API.v1.addRoute(
589643
},
590644
},
591645
);
646+
647+
export type DmEndpoints = ExtractRoutesFromAPI<typeof dmEndpoints>;
648+
649+
declare module '@rocket.chat/rest-typings' {
650+
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface
651+
interface Endpoints extends DmEndpoints {}
652+
}

packages/rest-typings/src/v1/dm/DmDeleteProps.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.

packages/rest-typings/src/v1/dm/dm.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import type { ImEndpoints } from './im';
22

33
export type DmEndpoints = {
44
'/v1/dm.create': ImEndpoints['/v1/im.create'];
5-
'/v1/dm.delete': ImEndpoints['/v1/im.delete'];
65
'/v1/dm.close': ImEndpoints['/v1/im.close'];
76
'/v1/dm.counters': ImEndpoints['/v1/im.counters'];
87
'/v1/dm.files': ImEndpoints['/v1/im.files'];

packages/rest-typings/src/v1/dm/im.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import type { IMessage, IRoom, IUser, IUploadWithUser } from '@rocket.chat/core-
22

33
import type { DmCloseProps } from './DmCloseProps';
44
import type { DmCreateProps } from './DmCreateProps';
5-
import type { DmDeleteProps } from './DmDeleteProps';
65
import type { DmFileProps } from './DmFileProps';
76
import type { DmHistoryProps } from './DmHistoryProps';
87
import type { DmLeaveProps } from './DmLeaveProps';
@@ -17,9 +16,6 @@ export type ImEndpoints = {
1716
room: IRoom & { rid: IRoom['_id'] };
1817
};
1918
};
20-
'/v1/im.delete': {
21-
POST: (params: DmDeleteProps) => void;
22-
};
2319
'/v1/im.close': {
2420
POST: (params: DmCloseProps) => void;
2521
};
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
export * from './dm';
22
export * from './im';
33
export * from './DmCreateProps';
4-
export * from './DmDeleteProps';
54
export * from './DmFileProps';
65
export * from './DmMembersProps';
76
export * from './DmMessagesProps';

0 commit comments

Comments
 (0)