Skip to content
Open
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/strong-insects-brush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use minor instead of patch anymore for this project

---

Migrated users.getPreferences to OpenAPI pattern with AJV validation
56 changes: 43 additions & 13 deletions apps/meteor/app/api/server/v1/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { MeteorError, Team, api, Calendar } from '@rocket.chat/core-services';
import { type IExportOperation, type ILoginToken, type IPersonalAccessToken, type IUser, type UserStatus } from '@rocket.chat/core-typings';
import { Users, Subscriptions } from '@rocket.chat/models';
import {
ajv,
validateBadRequestErrorResponse,
validateUnauthorizedErrorResponse,
isUserCreateParamsPOST,
isUserSetActiveStatusParamsPOST,
isUserDeactivateIdleParamsPOST,
Expand Down Expand Up @@ -68,6 +71,7 @@ import { deleteUserOwnAccount } from '../../../lib/server/methods/deleteUserOwnA
import { settings } from '../../../settings/server';
import { isSMTPConfigured } from '../../../utils/server/functions/isSMTPConfigured';
import { getURL } from '../../../utils/server/getURL';
import type { ExtractRoutesFromAPI } from '../ApiClass';
import { API } from '../api';
import { getPaginationItems } from '../helpers/getPaginationItems';
import { getUserFromParams } from '../helpers/getUserFromParams';
Expand Down Expand Up @@ -764,25 +768,51 @@ API.v1.addRoute(
},
);

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

const isUserPreferencesResponse = ajv.compile(UserPreferencesResponseSchema);

const usersEndpoints = API.v1.get(
'users.getPreferences',
{ authRequired: true },
{
async get() {
const user = await Users.findOneById(this.userId);
if (user?.settings) {
const { preferences = {} } = user?.settings;
preferences.language = user?.language;

return API.v1.success({
preferences,
});
}
return API.v1.failure(i18n.t('Accounts_Default_User_Preferences_not_available').toUpperCase());
authRequired: true,
response: {
400: validateBadRequestErrorResponse,
401: validateUnauthorizedErrorResponse,
200: isUserPreferencesResponse,
},
},
async function action() {
const user = await Users.findOneById(this.userId);

if (user?.settings) {
const { preferences = {} } = user.settings;
preferences.language = user.language;

return API.v1.success({ preferences });
}

throw new Meteor.Error('error-preferences-not-found', i18n.t('Accounts_Default_User_Preferences_not_available').toUpperCase());
},
);

export type UsersEndpoints = ExtractRoutesFromAPI<typeof usersEndpoints>;

declare module '@rocket.chat/rest-typings' {
type Endpoints = UsersEndpoints;
}

API.v1.addRoute(
'users.forgotPassword',
{ authRequired: false },
Expand Down