Skip to content

Commit 7485960

Browse files
authored
chore: Convert some apis to openAPI (RocketChat#39265)
1 parent a85f325 commit 7485960

32 files changed

Lines changed: 3729 additions & 1732 deletions

apps/meteor/app/api/server/definition.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export type ErrorStatusCodes = Exclude<Exclude<Range<511>, Range<500>>, 509>;
1818

1919
export type SuccessResult<T, TStatusCode extends SuccessStatusCodes = 200> = {
2020
statusCode: TStatusCode;
21-
body: T extends object ? { success: true } & T : T;
21+
body: T extends Record<string, unknown> ? { success: true } & T : T;
2222
};
2323

2424
export type FailureResult<T, TStack = undefined, TErrorType = undefined, TErrorDetails = undefined> = {
Lines changed: 82 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { Settings } from '@rocket.chat/models';
2-
import { isAssetsUnsetAssetProps } from '@rocket.chat/rest-typings';
2+
import {
3+
ajv,
4+
isAssetsUnsetAssetProps,
5+
validateUnauthorizedErrorResponse,
6+
validateForbiddenErrorResponse,
7+
validateBadRequestErrorResponse,
8+
} from '@rocket.chat/rest-typings';
39

410
import { updateAuditedByUser } from '../../../../server/settings/lib/auditedSettingUpdates';
511
import { RocketChatAssets, refreshClients } from '../../../assets/server';
@@ -8,87 +14,102 @@ import { settings } from '../../../settings/server';
814
import { API } from '../api';
915
import { getUploadFormData } from '../lib/getUploadFormData';
1016

11-
API.v1.addRoute(
17+
const successResponseSchema = ajv.compile<void>({
18+
type: 'object',
19+
properties: { success: { type: 'boolean', enum: [true] } },
20+
required: ['success'],
21+
additionalProperties: false,
22+
});
23+
24+
API.v1.post(
1225
'assets.setAsset',
1326
{
1427
authRequired: true,
1528
permissionsRequired: ['manage-assets'],
29+
response: {
30+
200: successResponseSchema,
31+
400: validateBadRequestErrorResponse,
32+
401: validateUnauthorizedErrorResponse,
33+
403: validateForbiddenErrorResponse,
34+
},
1635
},
17-
{
18-
async post() {
19-
const asset = await getUploadFormData(
20-
{
21-
request: this.request,
22-
},
23-
{ field: 'asset', sizeLimit: settings.get('FileUpload_MaxFileSize') },
24-
);
36+
async function action() {
37+
const asset = await getUploadFormData(
38+
{
39+
request: this.request,
40+
},
41+
{ field: 'asset', sizeLimit: settings.get('FileUpload_MaxFileSize') },
42+
);
2543

26-
const { fileBuffer, fields, filename, mimetype } = asset;
44+
const { fileBuffer, fields, filename, mimetype } = asset;
2745

28-
const { refreshAllClients, assetName: customName } = fields;
46+
const { refreshAllClients, assetName: customName } = fields;
2947

30-
const assetName = customName || filename;
31-
const assetsKeys = Object.keys(RocketChatAssets.assets);
48+
const assetName = customName || filename;
49+
const assetsKeys = Object.keys(RocketChatAssets.assets);
3250

33-
const isValidAsset = assetsKeys.includes(assetName);
34-
if (!isValidAsset) {
35-
throw new Error('Invalid asset');
36-
}
51+
const isValidAsset = assetsKeys.includes(assetName);
52+
if (!isValidAsset) {
53+
throw new Error('Invalid asset');
54+
}
3755

38-
const { key, value } = await RocketChatAssets.setAssetWithBuffer(fileBuffer, mimetype, assetName);
56+
const { key, value } = await RocketChatAssets.setAssetWithBuffer(fileBuffer, mimetype, assetName);
3957

40-
const { modifiedCount } = await updateAuditedByUser({
41-
_id: this.userId,
42-
username: this.user.username,
43-
ip: this.requestIp,
44-
useragent: this.request.headers.get('user-agent') || '',
45-
})(Settings.updateValueById, key, value);
58+
const { modifiedCount } = await updateAuditedByUser({
59+
_id: this.userId,
60+
username: this.user.username ?? '',
61+
ip: this.requestIp ?? '',
62+
useragent: this.request.headers.get('user-agent') ?? '',
63+
})(Settings.updateValueById, key, value);
4664

47-
if (modifiedCount) {
48-
void notifyOnSettingChangedById(key);
49-
}
65+
if (modifiedCount) {
66+
void notifyOnSettingChangedById(key);
67+
}
5068

51-
if (refreshAllClients) {
52-
await refreshClients(this.userId);
53-
}
69+
if (refreshAllClients) {
70+
await refreshClients(this.userId);
71+
}
5472

55-
return API.v1.success();
56-
},
73+
return API.v1.success();
5774
},
5875
);
5976

60-
API.v1.addRoute(
77+
API.v1.post(
6178
'assets.unsetAsset',
6279
{
6380
authRequired: true,
64-
validateParams: isAssetsUnsetAssetProps,
81+
body: isAssetsUnsetAssetProps,
6582
permissionsRequired: ['manage-assets'],
66-
},
67-
{
68-
async post() {
69-
const { assetName, refreshAllClients } = this.bodyParams;
70-
const isValidAsset = Object.keys(RocketChatAssets.assets).includes(assetName);
71-
if (!isValidAsset) {
72-
throw Error('Invalid asset');
73-
}
74-
75-
const { key, value } = await RocketChatAssets.unsetAsset(assetName);
76-
77-
const { modifiedCount } = await updateAuditedByUser({
78-
_id: this.userId,
79-
username: this.user.username,
80-
ip: this.requestIp,
81-
useragent: this.request.headers.get('user-agent') || '',
82-
})(Settings.updateValueById, key, value);
83-
84-
if (modifiedCount) {
85-
void notifyOnSettingChangedById(key);
86-
}
87-
88-
if (refreshAllClients) {
89-
await refreshClients(this.userId);
90-
}
91-
return API.v1.success();
83+
response: {
84+
200: successResponseSchema,
85+
400: validateBadRequestErrorResponse,
86+
401: validateUnauthorizedErrorResponse,
87+
403: validateForbiddenErrorResponse,
9288
},
9389
},
90+
async function action() {
91+
const { assetName, refreshAllClients } = this.bodyParams;
92+
const isValidAsset = Object.keys(RocketChatAssets.assets).includes(assetName);
93+
if (!isValidAsset) {
94+
throw Error('Invalid asset');
95+
}
96+
97+
const { key, value } = await RocketChatAssets.unsetAsset(assetName);
98+
99+
const { modifiedCount } = await updateAuditedByUser({
100+
_id: this.userId,
101+
username: this.user.username ?? '',
102+
ip: this.requestIp ?? '',
103+
useragent: this.request.headers.get('user-agent') ?? '',
104+
})(Settings.updateValueById, key, value);
105+
106+
if (modifiedCount) {
107+
void notifyOnSettingChangedById(key);
108+
}
109+
110+
if (refreshAllClients) {
111+
await refreshClients(this.userId);
112+
}
113+
return API.v1.success();
114+
},
94115
);

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

Lines changed: 101 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { IMessage } from '@rocket.chat/core-typings';
1+
import type { IMessage, ISupportedLanguage } from '@rocket.chat/core-typings';
22
import { Messages } from '@rocket.chat/models';
33
import {
44
ajv,
@@ -15,14 +15,51 @@ import { settings } from '../../../settings/server';
1515
import type { ExtractRoutesFromAPI } from '../ApiClass';
1616
import { API } from '../api';
1717

18-
API.v1.addRoute(
19-
'autotranslate.getSupportedLanguages',
20-
{
21-
authRequired: true,
22-
validateParams: isAutotranslateGetSupportedLanguagesParamsGET,
18+
type AutotranslateTranslateMessageParamsPOST = {
19+
messageId: string;
20+
targetLanguage?: string;
21+
};
22+
23+
const AutotranslateTranslateMessageParamsPostSchema = {
24+
type: 'object',
25+
properties: {
26+
messageId: {
27+
type: 'string',
28+
},
29+
targetLanguage: {
30+
type: 'string',
31+
nullable: true,
32+
},
2333
},
24-
{
25-
async get() {
34+
required: ['messageId'],
35+
additionalProperties: false,
36+
};
37+
38+
const isAutotranslateTranslateMessageParamsPOST = ajv.compile<AutotranslateTranslateMessageParamsPOST>(
39+
AutotranslateTranslateMessageParamsPostSchema,
40+
);
41+
42+
const autotranslateEndpoints = API.v1
43+
.get(
44+
'autotranslate.getSupportedLanguages',
45+
{
46+
authRequired: true,
47+
query: isAutotranslateGetSupportedLanguagesParamsGET,
48+
response: {
49+
200: ajv.compile<{ languages: ISupportedLanguage[] }>({
50+
type: 'object',
51+
properties: {
52+
languages: { type: 'array', items: { type: 'object' } },
53+
success: { type: 'boolean', enum: [true] },
54+
},
55+
required: ['languages', 'success'],
56+
additionalProperties: false,
57+
}),
58+
400: validateBadRequestErrorResponse,
59+
401: validateUnauthorizedErrorResponse,
60+
},
61+
},
62+
async function action() {
2663
if (!settings.get('AutoTranslate_Enabled')) {
2764
return API.v1.failure('AutoTranslate is disabled.');
2865
}
@@ -31,17 +68,24 @@ API.v1.addRoute(
3168

3269
return API.v1.success({ languages: languages || [] });
3370
},
34-
},
35-
);
36-
37-
API.v1.addRoute(
38-
'autotranslate.saveSettings',
39-
{
40-
authRequired: true,
41-
validateParams: isAutotranslateSaveSettingsParamsPOST,
42-
},
43-
{
44-
async post() {
71+
)
72+
.post(
73+
'autotranslate.saveSettings',
74+
{
75+
authRequired: true,
76+
body: isAutotranslateSaveSettingsParamsPOST,
77+
response: {
78+
200: ajv.compile<void>({
79+
type: 'object',
80+
properties: { success: { type: 'boolean', enum: [true] } },
81+
required: ['success'],
82+
additionalProperties: false,
83+
}),
84+
400: validateBadRequestErrorResponse,
85+
401: validateUnauthorizedErrorResponse,
86+
},
87+
},
88+
async function action() {
4589
const { roomId, field, value, defaultLanguage } = this.bodyParams;
4690
if (!settings.get('AutoTranslate_Enabled')) {
4791
return API.v1.failure('AutoTranslate is disabled.');
@@ -70,74 +114,48 @@ API.v1.addRoute(
70114

71115
return API.v1.success();
72116
},
73-
},
74-
);
75-
76-
type AutotranslateTranslateMessageParamsPOST = {
77-
messageId: string;
78-
targetLanguage?: string;
79-
};
80-
81-
const AutotranslateTranslateMessageParamsPostSchema = {
82-
type: 'object',
83-
properties: {
84-
messageId: {
85-
type: 'string',
86-
},
87-
targetLanguage: {
88-
type: 'string',
89-
nullable: true,
117+
)
118+
.post(
119+
'autotranslate.translateMessage',
120+
{
121+
authRequired: true,
122+
body: isAutotranslateTranslateMessageParamsPOST,
123+
response: {
124+
200: ajv.compile<{ message: IMessage }>({
125+
type: 'object',
126+
properties: {
127+
message: { $ref: '#/components/schemas/IMessage' },
128+
success: { type: 'boolean', enum: [true] },
129+
},
130+
required: ['message', 'success'],
131+
additionalProperties: false,
132+
}),
133+
400: validateBadRequestErrorResponse,
134+
401: validateUnauthorizedErrorResponse,
135+
},
90136
},
91-
},
92-
required: ['messageId'],
93-
additionalProperties: false,
94-
};
95-
96-
const isAutotranslateTranslateMessageParamsPOST = ajv.compile<AutotranslateTranslateMessageParamsPOST>(
97-
AutotranslateTranslateMessageParamsPostSchema,
98-
);
99-
100-
const autotranslateEndpoints = API.v1.post(
101-
'autotranslate.translateMessage',
102-
{
103-
authRequired: true,
104-
body: isAutotranslateTranslateMessageParamsPOST,
105-
response: {
106-
200: ajv.compile<{ message: IMessage }>({
107-
type: 'object',
108-
properties: {
109-
message: { $ref: '#/components/schemas/IMessage' },
110-
success: { type: 'boolean', enum: [true] },
111-
},
112-
required: ['message', 'success'],
113-
additionalProperties: false,
114-
}),
115-
400: validateBadRequestErrorResponse,
116-
401: validateUnauthorizedErrorResponse,
117-
},
118-
},
119-
async function action() {
120-
const { messageId, targetLanguage } = this.bodyParams;
121-
if (!settings.get('AutoTranslate_Enabled')) {
122-
return API.v1.failure('AutoTranslate is disabled.');
123-
}
124-
if (!messageId) {
125-
return API.v1.failure('The bodyParam "messageId" is required.');
126-
}
127-
const message = await Messages.findOneById(messageId);
128-
if (!message) {
129-
return API.v1.failure('Message not found.');
130-
}
137+
async function action() {
138+
const { messageId, targetLanguage } = this.bodyParams;
139+
if (!settings.get('AutoTranslate_Enabled')) {
140+
return API.v1.failure('AutoTranslate is disabled.');
141+
}
142+
if (!messageId) {
143+
return API.v1.failure('The bodyParam "messageId" is required.');
144+
}
145+
const message = await Messages.findOneById(messageId);
146+
if (!message) {
147+
return API.v1.failure('Message not found.');
148+
}
131149

132-
const translatedMessage = await translateMessage(targetLanguage, message);
150+
const translatedMessage = await translateMessage(targetLanguage, message);
133151

134-
if (!translatedMessage) {
135-
return API.v1.failure('Failed to translate message.');
136-
}
152+
if (!translatedMessage) {
153+
return API.v1.failure('Failed to translate message.');
154+
}
137155

138-
return API.v1.success({ message: translatedMessage });
139-
},
140-
);
156+
return API.v1.success({ message: translatedMessage });
157+
},
158+
);
141159

142160
type AutotranslateEndpoints = ExtractRoutesFromAPI<typeof autotranslateEndpoints>;
143161

0 commit comments

Comments
 (0)