Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
62 changes: 47 additions & 15 deletions apps/meteor/app/api/server/v1/users.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,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 {
import {ajv,
validateBadRequestErrorResponse,
validateUnauthorizedErrorResponse,
isUserCreateParamsPOST,
isUserSetActiveStatusParamsPOST,
isUserDeactivateIdleParamsPOST,
Expand All @@ -24,7 +26,7 @@ import { Accounts } from 'meteor/accounts-base';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import type { Filter } from 'mongodb';

import type { ExtractRoutesFromAPI } from '../ApiClass';
import { generatePersonalAccessTokenOfUser } from '../../../../imports/personal-access-tokens/server/api/methods/generateToken';
import { regeneratePersonalAccessTokenOfUser } from '../../../../imports/personal-access-tokens/server/api/methods/regenerateToken';
import { removePersonalAccessTokenOfUser } from '../../../../imports/personal-access-tokens/server/api/methods/removeToken';
Expand Down Expand Up @@ -764,25 +766,55 @@ 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' {
interface Endpoints extends UsersEndpoints {}
}


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