Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
5 changes: 5 additions & 0 deletions .changeset/refactor-ldap-api-chained-pattern.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Migrated `ldap.testConnection` and `ldap.testSearch` REST API endpoints from legacy `addRoute` pattern to the new chained `.post()` API pattern with typed response schemas and AJV body validation (replacing Meteor `check()`).
110 changes: 67 additions & 43 deletions apps/meteor/app/api/server/v1/ldap.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,86 @@
import { LDAP } from '@rocket.chat/core-services';
import { Match, check } from 'meteor/check';
import { ajv, isLdapTestSearch, validateUnauthorizedErrorResponse, validateForbiddenErrorResponse } from '@rocket.chat/rest-typings';

import { SystemLogger } from '../../../../server/lib/logger/system';
import { settings } from '../../../settings/server';
import { API } from '../api';

API.v1.addRoute(
const messageResponseSchema = {
type: 'object' as const,
properties: {
message: { type: 'string' as const },
success: {
type: 'boolean' as const,
enum: [true] as const,
},
},
required: ['message', 'success'] as const,
additionalProperties: false,
};

API.v1.post(
'ldap.testConnection',
{ authRequired: true, permissionsRequired: ['test-admin-options'] },
{
async post() {
if (!this.userId) {
throw new Error('error-invalid-user');
}

if (settings.get<boolean>('LDAP_Enable') !== true) {
throw new Error('LDAP_disabled');
}

try {
await LDAP.testConnection();
} catch (err) {
SystemLogger.error({ err });
throw new Error('Connection_failed');
}

return API.v1.success({
message: 'LDAP_Connection_successful' as const,
});
authRequired: true,
permissionsRequired: ['test-admin-options'],
response: {
200: ajv.compile<{ message: string; success: true }>(messageResponseSchema),
401: validateUnauthorizedErrorResponse,
403: validateForbiddenErrorResponse,
},
},
async function action() {
if (!this.userId) {
throw new Error('error-invalid-user');
}

if (settings.get<boolean>('LDAP_Enable') !== true) {
throw new Error('LDAP_disabled');
}

try {
await LDAP.testConnection();
} catch (err) {
SystemLogger.error({ err });
throw new Error('Connection_failed');
}

return API.v1.success({
message: 'LDAP_Connection_successful' as const,
});
},
);

API.v1.addRoute(
API.v1.post(
'ldap.testSearch',
{ authRequired: true, permissionsRequired: ['test-admin-options'] },
{
async post() {
check(
this.bodyParams,
Match.ObjectIncluding({
username: String,
}),
);

if (!this.userId) {
throw new Error('error-invalid-user');
}

if (settings.get('LDAP_Enable') !== true) {
throw new Error('LDAP_disabled');
}
authRequired: true,
permissionsRequired: ['test-admin-options'],
body: isLdapTestSearch,
response: {
200: ajv.compile<{ message: string; success: true }>(messageResponseSchema),
401: validateUnauthorizedErrorResponse,
403: validateForbiddenErrorResponse,
},
},
async function action() {
if (!this.userId) {
throw new Error('error-invalid-user');
}

if (settings.get<boolean>('LDAP_Enable') !== true) {
throw new Error('LDAP_disabled');
}

try {
await LDAP.testSearch(this.bodyParams.username);
} catch (err) {
SystemLogger.error({ err });
throw new Error('LDAP_search_failed');
}

return API.v1.success({
message: 'LDAP_User_Found' as const,
});
},
return API.v1.success({
message: 'LDAP_User_Found' as const,
});
},
);
1 change: 1 addition & 0 deletions packages/rest-typings/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ export * from './helpers/ReplacePlaceholders';
export * from './helpers/WithItemCount';
export * from './v1/emojiCustom';
export * from './v1/instances';
export * from './v1/ldap';
export * from './v1/users';
export * from './v1/users/UsersSetAvatarParamsPOST';
export * from './v1/users/UsersSetPreferenceParamsPOST';
Expand Down
Loading