diff --git a/.changeset/add-tagalog-language.md b/.changeset/add-tagalog-language.md new file mode 100644 index 0000000000000..b36a3739fbca1 --- /dev/null +++ b/.changeset/add-tagalog-language.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/meteor': patch +'@rocket.chat/i18n': minor +--- + +Added Tagalog (`tl`) as a selectable interface language. It appears in the user's **Account → Preferences → Localization → Language** dropdown; interface strings fall back to English until translations are contributed (same approach as other not-yet-translated locales). diff --git a/.changeset/all-readers-reply.md b/.changeset/all-readers-reply.md new file mode 100644 index 0000000000000..a11015f20cd48 --- /dev/null +++ b/.changeset/all-readers-reply.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/i18n": minor +--- + +Shows a confirmation modal when switching attribute store setting diff --git a/.changeset/few-lies-drum.md b/.changeset/few-lies-drum.md new file mode 100644 index 0000000000000..9231c92914c72 --- /dev/null +++ b/.changeset/few-lies-drum.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixes an issue with embedded layout where users were able to receive VideoConf calls, causing the application to crash diff --git a/.changeset/tasty-deserts-doubt.md b/.changeset/tasty-deserts-doubt.md new file mode 100644 index 0000000000000..c754eddcd89e0 --- /dev/null +++ b/.changeset/tasty-deserts-doubt.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/core-typings': patch +'@rocket.chat/meteor': patch +--- + +Fixes an issue where ui crashes when message attachment fields contains non-string `value` field diff --git a/apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx b/apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx index d763362275959..e0c0bc636bd4e 100644 --- a/apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx +++ b/apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx @@ -91,7 +91,7 @@ const DefaultAttachment = (attachment: DefaultAttachmentProps) => { `${line} `)} /> ) : null, value: value ? ( - `${line} `)} /> + `${line} `)} /> ) : null, }; })} diff --git a/apps/meteor/client/hooks/useShowSettingAlerts.tsx b/apps/meteor/client/hooks/useShowSettingAlerts.tsx new file mode 100644 index 0000000000000..1957508df198d --- /dev/null +++ b/apps/meteor/client/hooks/useShowSettingAlerts.tsx @@ -0,0 +1,72 @@ +import type { ISetting } from '@rocket.chat/core-typings'; +import { Box, Callout } from '@rocket.chat/fuselage'; +import { GenericModal } from '@rocket.chat/ui-client'; +import { useSetModal } from '@rocket.chat/ui-contexts'; +import { useCallback } from 'react'; +import { Trans, useTranslation } from 'react-i18next'; + +export const useShowSettingAlerts = () => { + const { t, i18n } = useTranslation(); + const setModal = useSetModal(); + + const showAlerts = useCallback( + (persistedSettingsWithAlert: ISetting[]) => { + return new Promise((resolve) => { + setModal( + { + resolve(true); + setModal(null); + }} + onCancel={() => { + resolve(false); + return setModal(null); + }} + onClose={() => { + resolve(false); + return setModal(null); + }} + > + {persistedSettingsWithAlert.map(({ _id, i18nLabel, alert }) => { + if (!alert) { + return null; + } + + const labelText = (i18n.exists(i18nLabel) && t(i18nLabel)) || (i18n.exists(_id) && t(_id)) || i18nLabel || _id; + + return ( + + + {labelText} + + + , + strong: , + br:
, + ul:
    , + li:
  • , + }} + /> + + + ); + })} + , + ); + }); + }, + [t, i18n, setModal], + ); + + return showAlerts; +}; diff --git a/apps/meteor/client/lib/VideoConfManager.ts b/apps/meteor/client/lib/VideoConfManager.ts index 3fd883aa7e5d2..13d9f5d6b1ca3 100644 --- a/apps/meteor/client/lib/VideoConfManager.ts +++ b/apps/meteor/client/lib/VideoConfManager.ts @@ -301,6 +301,10 @@ export const VideoConfManager = new (class VideoConfManager extends Emitter ( - - - - - - - - - - - - + + + + + + + + + + + + @@ -56,18 +56,18 @@ const MeteorProvider = ({ children }: MeteorProviderProps) => ( - - - - - - - - - - - - + + + + + + + + + + + + ); diff --git a/apps/meteor/client/providers/SettingsProvider.tsx b/apps/meteor/client/providers/SettingsProvider.tsx index 9412bd1989c2d..3f0a2702ae6e2 100644 --- a/apps/meteor/client/providers/SettingsProvider.tsx +++ b/apps/meteor/client/providers/SettingsProvider.tsx @@ -1,5 +1,6 @@ import type { ISetting } from '@rocket.chat/core-typings'; import { createPredicateFromFilter } from '@rocket.chat/mongo-adapter'; +import { isTruthy } from '@rocket.chat/tools'; import type { SettingsContextQuery, SettingsContextValue } from '@rocket.chat/ui-contexts'; import { SettingsContext, useAtLeastOnePermission, useEndpoint } from '@rocket.chat/ui-contexts'; import { useQueryClient } from '@tanstack/react-query'; @@ -7,6 +8,7 @@ import type { ReactNode } from 'react'; import { useCallback, useMemo } from 'react'; import { PublicSettingsCachedStore, PrivateSettingsCachedStore } from '../cachedStores'; +import { useShowSettingAlerts } from '../hooks/useShowSettingAlerts'; import { PrivateCachedStore } from '../lib/cachedStores/CachedStore'; import { applyQueryOptions } from '../lib/cachedStores/applyQueryOptions'; @@ -96,9 +98,15 @@ const SettingsProvider = ({ children }: SettingsProviderProps) => { const queryClient = useQueryClient(); + const showAlerts = useShowSettingAlerts(); + const saveSettings = useEndpoint('POST', '/v1/settings'); const dispatch = useCallback( - async (changes: Partial[]) => { + async (changes: Partial[], onSaved?: () => void) => { + const changedSettingIds = changes.map((s) => s._id).filter(isTruthy); + const alerts = cachedCollection.store + .getState() + .filter((setting) => Boolean(setting.alert && changedSettingIds.includes(setting._id))); // FIXME: This is a temporary solution to invalidate queries when settings change changes.forEach((val) => { if (val._id === 'Enterprise_License') { @@ -106,9 +114,19 @@ const SettingsProvider = ({ children }: SettingsProviderProps) => { } }); + if (alerts.length) { + const accepted = await showAlerts(alerts); + + if (!accepted) { + return; + } + } + await saveSettings({ settings: changes as Pick[] }); + + onSaved?.(); }, - [queryClient, saveSettings], + [queryClient, saveSettings, showAlerts, cachedCollection.store], ); const contextValue = useMemo( diff --git a/apps/meteor/client/views/admin/ABAC/ABACSettingTab/SettingField.spec.tsx b/apps/meteor/client/views/admin/ABAC/ABACSettingTab/SettingField.spec.tsx index 77e52759a434b..5320ee7fecbfe 100644 --- a/apps/meteor/client/views/admin/ABAC/ABACSettingTab/SettingField.spec.tsx +++ b/apps/meteor/client/views/admin/ABAC/ABACSettingTab/SettingField.spec.tsx @@ -1,6 +1,6 @@ import type { ISetting } from '@rocket.chat/core-typings'; import { mockAppRoot } from '@rocket.chat/mock-providers'; -import { render, screen, waitFor } from '@testing-library/react'; +import { act, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import SettingField from './SettingField'; @@ -31,6 +31,7 @@ jest.mock('@rocket.chat/core-typings', () => ({ describe('SettingField', () => { beforeEach(() => { jest.useFakeTimers(); + dispatchMock.mockClear(); }); afterEach(() => { @@ -55,4 +56,23 @@ describe('SettingField', () => { expect(dispatchMock).toHaveBeenCalled(); }); }); + + it('should dispatch when the setting has an alert (confirmation is handled by the settings dispatch)', async () => { + const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime }); + + render(, { + wrapper: mockAppRoot() + .wrap((children) => {children}) + .withSetting('Test_Setting', false, { ...settingStructure, alert: 'Test_Setting_Alert' }) + .build(), + }); + + await user.click(screen.getByRole('checkbox')); + + await act(async () => { + jest.runOnlyPendingTimers(); + }); + + expect(dispatchMock).toHaveBeenCalledWith([{ _id: 'Test_Setting', value: true }]); + }); }); diff --git a/apps/meteor/client/views/admin/settings/SettingsGroupPage/SettingsGroupPage.tsx b/apps/meteor/client/views/admin/settings/SettingsGroupPage/SettingsGroupPage.tsx index f4b5da5304e44..afb70452445f6 100644 --- a/apps/meteor/client/views/admin/settings/SettingsGroupPage/SettingsGroupPage.tsx +++ b/apps/meteor/client/views/admin/settings/SettingsGroupPage/SettingsGroupPage.tsx @@ -78,8 +78,7 @@ const SettingsGroupPage = ({ } try { - await dispatch(changes); - dispatchToastMessage({ type: 'success', message: t('Settings_updated') }); + await dispatch(changes, () => dispatchToastMessage({ type: 'success', message: t('Settings_updated') })); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } diff --git a/apps/meteor/client/views/root/hooks/loggedIn/useUpdateVideoConfUser.ts b/apps/meteor/client/views/root/hooks/loggedIn/useUpdateVideoConfUser.ts index d4a5da320bc18..7cabee3638c28 100644 --- a/apps/meteor/client/views/root/hooks/loggedIn/useUpdateVideoConfUser.ts +++ b/apps/meteor/client/views/root/hooks/loggedIn/useUpdateVideoConfUser.ts @@ -1,3 +1,4 @@ +import { useEmbeddedLayout } from '@rocket.chat/ui-client'; import { useConnectionStatus, useIsLoggingIn } from '@rocket.chat/ui-contexts'; import { useEffect } from 'react'; @@ -6,8 +7,10 @@ import { VideoConfManager } from '../../../../lib/VideoConfManager'; export const useUpdateVideoConfUser = (userId: string) => { const { connected } = useConnectionStatus(); const isLoggingIn = useIsLoggingIn(); + const embeddedLayout = useEmbeddedLayout(); useEffect(() => { - VideoConfManager.updateUser(userId, isLoggingIn, connected); - }, [userId, isLoggingIn, connected]); + // Videconf should not be available in embedded layout + VideoConfManager.updateUser(embeddedLayout ? null : userId, isLoggingIn, connected); + }, [userId, isLoggingIn, connected, embeddedLayout]); }; diff --git a/apps/meteor/ee/server/hooks/abac/scopeAdminRoomsForAbac.ts b/apps/meteor/ee/server/hooks/abac/scopeAdminRoomsForAbac.ts index 9372a6620b039..6525f86483c5e 100644 --- a/apps/meteor/ee/server/hooks/abac/scopeAdminRoomsForAbac.ts +++ b/apps/meteor/ee/server/hooks/abac/scopeAdminRoomsForAbac.ts @@ -1,22 +1,30 @@ import { Abac } from '@rocket.chat/core-services'; +import type { IRoom, IRoomAbacRedaction } from '@rocket.chat/core-typings'; import { License } from '@rocket.chat/license'; import { Users } from '@rocket.chat/models'; import { scopeAdminRoomsForAbac } from '../../../../app/api/server/lib/scopeAdminRoomsForAbac'; import { isABACManagedRoom } from '../../../../app/authorization/server/lib/isABACManagedRoom'; +const redact = >(rooms: T[]): Array => + rooms.map((room) => (isABACManagedRoom(room) ? { ...room, abacAttributes: [], abacAttributesRedacted: true } : room)); + scopeAdminRoomsForAbac.patch(async (next, rooms, uid) => { const managed = License.hasModule('abac') ? rooms.filter(isABACManagedRoom) : []; if (!managed.length) { return next(rooms, uid); } - const user = await Users.findOneById(uid, { projection: { _id: 1, username: 1, name: 1 } }); - if (!user) { - return rooms.map((room) => (isABACManagedRoom(room) ? { ...room, abacAttributes: [], abacAttributesRedacted: true } : room)); - } + try { + const user = await Users.findOneById(uid, { projection: { _id: 1, username: 1, name: 1 } }); + if (!user) { + return redact(rooms); + } - const scoped = await Abac.scopeRoomsForAdmin(managed, user); - const scopedById = new Map(scoped.map((room) => [room._id, room])); - return rooms.map((room) => scopedById.get(room._id) ?? room); + const scoped = await Abac.scopeRoomsForAdmin(managed, user); + const scopedById = new Map(scoped.map((room) => [room._id, room])); + return rooms.map((room) => scopedById.get(room._id) ?? room); + } catch (err) { + return redact(rooms); + } }); diff --git a/apps/meteor/ee/server/services/package.json b/apps/meteor/ee/server/services/package.json index 0abac0e3128ff..5540f0293ac5c 100644 --- a/apps/meteor/ee/server/services/package.json +++ b/apps/meteor/ee/server/services/package.json @@ -47,7 +47,7 @@ "ws": "~8.21.0" }, "devDependencies": { - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@types/cookie": "^0.5.4", "@types/cookie-parser": "^1.4.10", "@types/ejson": "^2.2.2", diff --git a/apps/meteor/ee/server/settings/abac.ts b/apps/meteor/ee/server/settings/abac.ts index 39089d7998b84..63e5bec4e0fe4 100644 --- a/apps/meteor/ee/server/settings/abac.ts +++ b/apps/meteor/ee/server/settings/abac.ts @@ -27,6 +27,7 @@ export function addSettings(): Promise { { key: 'local', i18nLabel: 'ABAC_PDP_Type_Local' }, { key: 'virtru', i18nLabel: 'ABAC_PDP_Type_Virtru' }, ], + alert: 'ABAC_PDP_Type_Switch_Alert', enableQuery: abacEnabledQuery, }); await this.add('ABAC_Attribute_Store', 'local', { diff --git a/apps/meteor/package.json b/apps/meteor/package.json index 1f49713dc291a..d58a328f2182b 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -116,7 +116,7 @@ "@rocket.chat/gazzodown": "workspace:^", "@rocket.chat/http-router": "workspace:^", "@rocket.chat/i18n": "workspace:^", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/instance-status": "workspace:^", "@rocket.chat/jwt": "workspace:^", "@rocket.chat/layout": "^0.34.3", diff --git a/apps/meteor/server/lib/i18n.ts b/apps/meteor/server/lib/i18n.ts index 86265b8d378bf..330dfc3154180 100644 --- a/apps/meteor/server/lib/i18n.ts +++ b/apps/meteor/server/lib/i18n.ts @@ -67,6 +67,7 @@ if (false) { import('@rocket.chat/i18n/dist/resources/sv.i18n.json'); import('@rocket.chat/i18n/dist/resources/ta-IN.i18n.json'); import('@rocket.chat/i18n/dist/resources/th-TH.i18n.json'); + import('@rocket.chat/i18n/dist/resources/tl.i18n.json'); import('@rocket.chat/i18n/dist/resources/tr.i18n.json'); import('@rocket.chat/i18n/dist/resources/ug.i18n.json'); import('@rocket.chat/i18n/dist/resources/uk.i18n.json'); diff --git a/apps/meteor/tests/end-to-end/api/abac.ts b/apps/meteor/tests/end-to-end/api/abac.ts index 47f78fb6a3a43..36977818b9ebd 100644 --- a/apps/meteor/tests/end-to-end/api/abac.ts +++ b/apps/meteor/tests/end-to-end/api/abac.ts @@ -3154,7 +3154,7 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I before(async function () { this.timeout(15000); - user = await createUser(); + user = await createUser({ verified: true }); userCreds = await login(user.username, password); room = (await createRoom({ type: 'p', name: `extpdp-permit-${Date.now()}` })).body.group; @@ -3219,7 +3219,7 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I before(async function () { this.timeout(15000); - user = await createUser(); + user = await createUser({ verified: true }); userCreds = await login(user.username, password); room = (await createRoom({ type: 'p', name: `extpdp-access-${Date.now()}` })).body.group; @@ -3284,8 +3284,8 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I before(async function () { this.timeout(10000); - permitUser = await createUser(); - denyUser = await createUser(); + permitUser = await createUser({ verified: true }); + denyUser = await createUser({ verified: true }); room = (await createRoom({ type: 'p', name: `extpdp-invite-${Date.now()}` })).body.group; await mockServerReset(); @@ -3367,7 +3367,7 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I before(async function () { this.timeout(10000); - user = await createUser(); + user = await createUser({ verified: true }); userCredentials = await login(user.username, password); room = (await createRoom({ type: 'p', name: `extpdp-failclose-${Date.now()}` })).body.group; @@ -3415,7 +3415,7 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I await mockServerReset(); await mockServerSet('GET', '/healthz', { status: 'NOT_SERVING' }); - const newUser = await createUser(); + const newUser = await createUser({ verified: true }); await request .post('/api/v1/groups.invite') @@ -3452,7 +3452,7 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I before(async function () { this.timeout(15000); - user = await createUser(); + user = await createUser({ verified: true }); room = (await createRoom({ type: 'p', name: `extpdp-selective-${Date.now()}` })).body.group; await request .post('/api/v1/groups.invite') @@ -3495,7 +3495,7 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I before(async function () { this.timeout(15000); - user = await createUser(); + user = await createUser({ verified: true }); room = (await createRoom({ type: 'p', name: `extpdp-tighten-${Date.now()}` })).body.group; await request .post('/api/v1/groups.invite') @@ -3555,7 +3555,7 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I before(async function () { this.timeout(15000); - user = await createUser({ username, email }); + user = await createUser({ username, email, verified: true }); room = (await createRoom({ type: 'p', name: `extpdp-sync-deny-${Date.now()}` })).body.group; await request .post(api('groups.invite')) @@ -3616,7 +3616,7 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I before(async function () { this.timeout(15000); - user = await createUser({ username, email }); + user = await createUser({ username, email, verified: true }); room = (await createRoom({ type: 'p', name: `extpdp-sync-permit-${Date.now()}` })).body.group; await request .post(api('groups.invite')) @@ -3723,7 +3723,7 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I let userWithAttrs: IUser; before(async () => { - userWithAttrs = await createUser(); + userWithAttrs = await createUser({ verified: true }); await addAbacAttributesToUserDirectly(userWithAttrs._id, [{ key: attrKey, values: ['alpha'] }]); }); @@ -3749,7 +3749,11 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I let storeConnection: MongoClient; const makeAdmin = async (slug: string) => { - const u = await createUser({ roles: ['admin'], username: `vstore-${slug}-${Date.now()}-${Math.random().toString(36).slice(2, 7)}` }); + const u = await createUser({ + roles: ['admin'], + username: `vstore-${slug}-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, + verified: true, + }); const creds = await login(u.username, password); return { user: u, creds }; }; @@ -4272,7 +4276,7 @@ const addAbacAttributesToUserDirectly = async (userId: string, abacAttributes: I wipeRoom1 = (await createRoom({ type: 'p', name: `vstore-wipe-1-${Date.now()}` })).body.group; wipeRoom2 = (await createRoom({ type: 'p', name: `vstore-wipe-2-${Date.now()}` })).body.group; - memberUser = await createUser(); + memberUser = await createUser({ verified: true }); await request .post(`${v1}/groups.invite`) .set(credentials) diff --git a/apps/uikit-playground/package.json b/apps/uikit-playground/package.json index b34eeec54a393..f7d19e8ea5e1b 100644 --- a/apps/uikit-playground/package.json +++ b/apps/uikit-playground/package.json @@ -23,7 +23,7 @@ "@rocket.chat/fuselage-toastbar": "^0.35.2", "@rocket.chat/fuselage-tokens": "~0.33.2", "@rocket.chat/fuselage-ui-kit": "workspace:~", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/logo": "^0.32.5", "@rocket.chat/styled": "^0.33.0", "@rocket.chat/ui-avatar": "workspace:^", diff --git a/ee/packages/abac/src/clients/virtru/identity.spec.ts b/ee/packages/abac/src/clients/virtru/identity.spec.ts index 2e4c1f3b211d2..4923c7206eb35 100644 --- a/ee/packages/abac/src/clients/virtru/identity.spec.ts +++ b/ee/packages/abac/src/clients/virtru/identity.spec.ts @@ -14,6 +14,23 @@ describe('virtru/identity', () => { expect(getUserEntityKey('emailAddress', { _id: 'u', username: 'bob' })).toBeUndefined(); }); + it('getUserEntityKey never resolves to an unverified email address', () => { + expect( + getUserEntityKey('emailAddress', { _id: 'u', emails: [{ address: 'ceo@company.com', verified: false }], username: 'attacker' }), + ).toBeUndefined(); + expect(getUserEntityKey('emailAddress', { _id: 'u', emails: [{ address: 'ceo@company.com' }], username: 'attacker' })).toBeUndefined(); + expect( + getUserEntityKey('emailAddress', { + _id: 'u', + emails: [ + { address: 'ceo@company.com', verified: false }, + { address: 'real@attacker.com', verified: true }, + ], + username: 'attacker', + }), + ).toBe('real@attacker.com'); + }); + it('buildAttributeFqns round-trips with parseAttributeFqns', () => { const attrs = [{ key: 'clearance', values: ['secret', 'topsecret'] }]; const fqns = buildAttributeFqns('example.com', attrs); diff --git a/ee/packages/abac/src/clients/virtru/identity.ts b/ee/packages/abac/src/clients/virtru/identity.ts index dfdca907b3a3d..7aed5065bfaf8 100644 --- a/ee/packages/abac/src/clients/virtru/identity.ts +++ b/ee/packages/abac/src/clients/virtru/identity.ts @@ -14,7 +14,7 @@ export function buildEntityIdentifier(defaultEntityKey: EntityKeyType, entityKey export function getUserEntityKey(defaultEntityKey: EntityKeyType, user: Pick): string | undefined { switch (defaultEntityKey) { case 'emailAddress': - return user.emails?.[0]?.address; + return user.emails?.find((email) => email.verified)?.address; case 'oidcIdentifier': return user.username; } diff --git a/ee/packages/abac/src/pdp/VirtruPDP.spec.ts b/ee/packages/abac/src/pdp/VirtruPDP.spec.ts index 6ea93b7b1beef..ec53e8bb3d596 100644 --- a/ee/packages/abac/src/pdp/VirtruPDP.spec.ts +++ b/ee/packages/abac/src/pdp/VirtruPDP.spec.ts @@ -50,10 +50,12 @@ const asyncIterable = (items: T[]) => ({ }, }); -const user = (over: Partial<{ _id: string; username: string; emails: { address: string }[]; __rooms: string[] }> = {}) => ({ +const user = ( + over: Partial<{ _id: string; username: string; emails: { address: string; verified?: boolean }[]; __rooms: string[] }> = {}, +) => ({ _id: 'u1', username: 'bob', - emails: [{ address: 'bob@x.com' }], + emails: [{ address: 'bob@x.com', verified: true }], ...over, }); @@ -236,7 +238,9 @@ describe('VirtruPDP.checkUsernamesMatchAttributes', () => { }); it('resolves when all users get DECISION_PERMIT', async () => { - usersFindByUsernames.mockReturnValue(cursor([user(), user({ _id: 'u2', username: 'alice', emails: [{ address: 'a@x.com' }] })])); + usersFindByUsernames.mockReturnValue( + cursor([user(), user({ _id: 'u2', username: 'alice', emails: [{ address: 'a@x.com', verified: true }] })]), + ); const apiCall = jest.fn().mockResolvedValue({ decisionResponses: [ { resourceDecisions: [{ ephemeralResourceId: 'r1', decision: 'DECISION_PERMIT' }] }, @@ -248,7 +252,9 @@ describe('VirtruPDP.checkUsernamesMatchAttributes', () => { }); it('throws when any user is DENIED', async () => { - usersFindByUsernames.mockReturnValue(cursor([user(), user({ _id: 'u2', username: 'alice', emails: [{ address: 'a@x.com' }] })])); + usersFindByUsernames.mockReturnValue( + cursor([user(), user({ _id: 'u2', username: 'alice', emails: [{ address: 'a@x.com', verified: true }] })]), + ); const apiCall = jest.fn().mockResolvedValue({ decisionResponses: [ { resourceDecisions: [{ ephemeralResourceId: 'r1', decision: 'DECISION_PERMIT' }] }, @@ -301,7 +307,7 @@ describe('VirtruPDP.onRoomAttributesChanged', () => { it('returns users that are DENIED', async () => { const u1 = user(); - const u2 = user({ _id: 'u2', username: 'alice', emails: [{ address: 'a@x.com' }] }); + const u2 = user({ _id: 'u2', username: 'alice', emails: [{ address: 'a@x.com', verified: true }] }); usersFindActiveByRoomIds.mockReturnValue(asyncIterable([u1, u2])); const apiCall = jest.fn().mockResolvedValue({ decisionResponses: [ @@ -335,8 +341,8 @@ describe('VirtruPDP.onRoomAttributesChanged', () => { it('still evicts entity-keyless users alongside DENY-only filtering of decided users', async () => { const keyless = user({ _id: 'u0', emails: [] }); - const denied = user({ _id: 'u2', username: 'alice', emails: [{ address: 'a@x.com' }] }); - const unspecified = user({ _id: 'u3', username: 'carol', emails: [{ address: 'c@x.com' }] }); + const denied = user({ _id: 'u2', username: 'alice', emails: [{ address: 'a@x.com', verified: true }] }); + const unspecified = user({ _id: 'u3', username: 'carol', emails: [{ address: 'c@x.com', verified: true }] }); usersFindActiveByRoomIds.mockReturnValue(asyncIterable([keyless, denied, unspecified])); const apiCall = jest.fn().mockResolvedValue({ decisionResponses: [ diff --git a/ee/packages/abac/src/store/VirtruAttributeStore.spec.ts b/ee/packages/abac/src/store/VirtruAttributeStore.spec.ts index ae68656d91a7b..1a95d1541eb51 100644 --- a/ee/packages/abac/src/store/VirtruAttributeStore.spec.ts +++ b/ee/packages/abac/src/store/VirtruAttributeStore.spec.ts @@ -20,7 +20,9 @@ const mkClient = (over: Partial usersFindOneById.mockReset().mockResolvedValue({ _id: 'u1', emails: [{ address: 'bob@x.com' }], username: 'bob' })); +beforeEach(() => + usersFindOneById.mockReset().mockResolvedValue({ _id: 'u1', emails: [{ address: 'bob@x.com', verified: true }], username: 'bob' }), +); describe('VirtruAttributeStore.entitlementsOf / list', () => { it('parses FQN map keys into grouped {key,values}', async () => { @@ -87,7 +89,7 @@ describe('VirtruAttributeStore.entitlementsOf / list', () => { const apiCall = jest.fn().mockResolvedValue({ entitlements: [{ actionsPerAttributeValueFqn: {} }] }); const store = new VirtruAttributeStore(mkClient({ apiCall })); await store.entitlementsOf(actor); - usersFindOneById.mockResolvedValue({ _id: 'u2', emails: [{ address: 'alice@x.com' }], username: 'alice' }); + usersFindOneById.mockResolvedValue({ _id: 'u2', emails: [{ address: 'alice@x.com', verified: true }], username: 'alice' }); await store.entitlementsOf({ _id: 'u2', username: 'alice', name: 'A' }); expect(apiCall).toHaveBeenCalledTimes(2); }); @@ -172,11 +174,11 @@ describe('VirtruAttributeStore.entitlementsOf / list', () => { expect(apiCall).toHaveBeenCalledTimes(1); apiCall.mockRejectedValueOnce(new Error('pdp blip')); - usersFindOneById.mockResolvedValue({ _id: 'u2', emails: [{ address: 'alice@x.com' }], username: 'alice' }); + usersFindOneById.mockResolvedValue({ _id: 'u2', emails: [{ address: 'alice@x.com', verified: true }], username: 'alice' }); await expect(store.entitlementsOf({ _id: 'u2', username: 'alice', name: 'A' })).rejects.toThrow('pdp blip'); expect(apiCall).toHaveBeenCalledTimes(2); - usersFindOneById.mockResolvedValue({ _id: 'u1', emails: [{ address: 'bob@x.com' }], username: 'bob' }); + usersFindOneById.mockResolvedValue({ _id: 'u1', emails: [{ address: 'bob@x.com', verified: true }], username: 'bob' }); const result = await store.entitlementsOf(actor); expect(result.get('clearance')).toEqual(new Set(['secret'])); expect(apiCall).toHaveBeenCalledTimes(2); diff --git a/packages/core-services/package.json b/packages/core-services/package.json index ec6e43c19aecb..dc226bf883c2c 100644 --- a/packages/core-services/package.json +++ b/packages/core-services/package.json @@ -20,7 +20,7 @@ "@rocket.chat/core-typings": "workspace:^", "@rocket.chat/federation-sdk": "0.6.3", "@rocket.chat/http-router": "workspace:^", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/media-signaling": "workspace:^", "@rocket.chat/message-parser": "workspace:^", "@rocket.chat/models": "workspace:^", diff --git a/packages/core-typings/package.json b/packages/core-typings/package.json index fc809f6655081..87027787b95fb 100644 --- a/packages/core-typings/package.json +++ b/packages/core-typings/package.json @@ -18,7 +18,7 @@ "test": "echo \"no tests\" && exit 1" }, "dependencies": { - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/message-parser": "workspace:^", "@rocket.chat/ui-kit": "workspace:~", "typia": "patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch", diff --git a/packages/core-typings/src/IMessage/MessageAttachment/MessageAttachmentDefault.ts b/packages/core-typings/src/IMessage/MessageAttachment/MessageAttachmentDefault.ts index 5c9f4cda338ee..b9396f55fbc4c 100644 --- a/packages/core-typings/src/IMessage/MessageAttachment/MessageAttachmentDefault.ts +++ b/packages/core-typings/src/IMessage/MessageAttachment/MessageAttachmentDefault.ts @@ -13,7 +13,7 @@ export type MessageAttachmentDefault = { fields?: { short?: boolean; title: string; - value: string; + value: string | number | boolean; }[]; // footer diff --git a/packages/fuselage-ui-kit/package.json b/packages/fuselage-ui-kit/package.json index c3a469e0bf620..b55f2dd3e8e25 100644 --- a/packages/fuselage-ui-kit/package.json +++ b/packages/fuselage-ui-kit/package.json @@ -49,7 +49,7 @@ "@rocket.chat/fuselage": "^0.79.0", "@rocket.chat/fuselage-hooks": "^0.41.0", "@rocket.chat/fuselage-tokens": "~0.33.2", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/jest-presets": "workspace:~", "@rocket.chat/mock-providers": "workspace:^", "@rocket.chat/storybook-config": "workspace:~", diff --git a/packages/gazzodown/package.json b/packages/gazzodown/package.json index 3c08b66e83ade..74f6452c2e739 100644 --- a/packages/gazzodown/package.json +++ b/packages/gazzodown/package.json @@ -34,7 +34,7 @@ "@rocket.chat/fuselage": "^0.79.0", "@rocket.chat/fuselage-hooks": "^0.41.0", "@rocket.chat/fuselage-tokens": "~0.33.2", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/jest-presets": "workspace:~", "@rocket.chat/message-parser": "workspace:^", "@rocket.chat/storybook-config": "workspace:~", diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 91e07ed476b09..2ab8263d4e6fb 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -26,6 +26,7 @@ "ABAC_PDP_Type_Description": "Select the Policy Decision Point engine to use for access control decisions.", "ABAC_PDP_Type_Local": "Local", "ABAC_PDP_Type_Virtru": "Virtru", + "ABAC_PDP_Type_Switch_Alert": "Changing the Policy Decision Point changes how room access is evaluated and may unexpectedly remove users from rooms.
    Switching back to local also sets the Attribute store back to local to ensure compatibility.", "ABAC_Attribute_Store": "Attribute store", "ABAC_Attribute_Store_Description": "Where assignable room attributes come from. With Virtru, attributes are managed externally and limited to those the acting admin possesses; the Room Attributes tab is hidden.", "ABAC_Attribute_Store_Local": "Local", @@ -1279,6 +1280,7 @@ "Confirm_your_password": "Confirm your password", "Confirm_contact_removal": "Confirm Contact Removal", "Confirmation": "Confirmation", + "Confirm_settings_change": "Confirm settings change", "Conflicts_found": "Conflicts found", "Connect": "Connect", "ConnectWorkspace_Button": "Connect workspace", diff --git a/packages/i18n/src/locales/tl.i18n.json b/packages/i18n/src/locales/tl.i18n.json new file mode 100644 index 0000000000000..6f31cf5a2e622 --- /dev/null +++ b/packages/i18n/src/locales/tl.i18n.json @@ -0,0 +1 @@ +{ } \ No newline at end of file diff --git a/packages/storybook-config/package.json b/packages/storybook-config/package.json index 217f670a6fddb..d4a9993f7a306 100644 --- a/packages/storybook-config/package.json +++ b/packages/storybook-config/package.json @@ -34,7 +34,7 @@ }, "devDependencies": { "@rocket.chat/fuselage": "^0.79.0", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/tsconfig": "workspace:*", "@storybook/react": "^9.1.13", "eslint": "~9.39.4", diff --git a/packages/ui-avatar/package.json b/packages/ui-avatar/package.json index a5f489be1459f..3536b38bd5bfc 100644 --- a/packages/ui-avatar/package.json +++ b/packages/ui-avatar/package.json @@ -20,7 +20,7 @@ "@rocket.chat/fuselage": "^0.79.0", "@rocket.chat/fuselage-hooks": "^0.41.0", "@rocket.chat/fuselage-tokens": "~0.33.2", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/ui-contexts": "workspace:^", "@types/react": "~18.3.28", "@types/react-dom": "~18.3.7", diff --git a/packages/ui-client/package.json b/packages/ui-client/package.json index 50aafd0fc6ed1..7a260ad226f87 100644 --- a/packages/ui-client/package.json +++ b/packages/ui-client/package.json @@ -29,7 +29,7 @@ "@rocket.chat/fuselage": "^0.79.0", "@rocket.chat/fuselage-hooks": "^0.41.0", "@rocket.chat/fuselage-tokens": "~0.33.2", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/jest-presets": "workspace:~", "@rocket.chat/layout": "^0.34.3", "@rocket.chat/logo": "^0.32.5", diff --git a/packages/ui-composer/package.json b/packages/ui-composer/package.json index 2e04f9e22cbb1..25566e297555a 100644 --- a/packages/ui-composer/package.json +++ b/packages/ui-composer/package.json @@ -25,7 +25,7 @@ "@rocket.chat/fuselage": "^0.79.0", "@rocket.chat/fuselage-hooks": "^0.41.0", "@rocket.chat/fuselage-tokens": "~0.33.2", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/jest-presets": "workspace:~", "@rocket.chat/mock-providers": "workspace:~", "@rocket.chat/storybook-config": "workspace:~", diff --git a/packages/ui-contexts/package.json b/packages/ui-contexts/package.json index a236535e89314..480c6150d7849 100644 --- a/packages/ui-contexts/package.json +++ b/packages/ui-contexts/package.json @@ -27,7 +27,7 @@ "@rocket.chat/fuselage-hooks": "^0.41.0", "@rocket.chat/fuselage-tokens": "~0.33.2", "@rocket.chat/i18n": "workspace:~", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/jest-presets": "workspace:~", "@rocket.chat/rest-typings": "workspace:^", "@rocket.chat/tools": "workspace:~", diff --git a/packages/ui-contexts/src/SettingsContext.ts b/packages/ui-contexts/src/SettingsContext.ts index 95e364de2c748..4e408a209c8ee 100644 --- a/packages/ui-contexts/src/SettingsContext.ts +++ b/packages/ui-contexts/src/SettingsContext.ts @@ -18,7 +18,7 @@ export type SettingsContextValue = { readonly querySettings: ( query: SettingsContextQuery, ) => [subscribe: (onStoreChange: () => void) => () => void, getSnapshot: () => ISetting[]]; - readonly dispatch: (changes: Partial[]) => Promise; + readonly dispatch: (changes: Partial[], onSaved?: () => void) => Promise; }; export const SettingsContext = createContext({ diff --git a/packages/ui-contexts/src/hooks/useSettingsDispatch.ts b/packages/ui-contexts/src/hooks/useSettingsDispatch.ts index 2994ea05fc942..3ea37e96c9730 100644 --- a/packages/ui-contexts/src/hooks/useSettingsDispatch.ts +++ b/packages/ui-contexts/src/hooks/useSettingsDispatch.ts @@ -1,6 +1,6 @@ -import type { ISetting } from '@rocket.chat/core-typings'; import { useContext } from 'react'; +import type { SettingsContextValue } from '../SettingsContext'; import { SettingsContext } from '../SettingsContext'; -export const useSettingsDispatch = (): ((changes: Partial[]) => Promise) => useContext(SettingsContext).dispatch; +export const useSettingsDispatch = (): SettingsContextValue['dispatch'] => useContext(SettingsContext).dispatch; diff --git a/packages/ui-kit/package.json b/packages/ui-kit/package.json index 47680ff77d5a0..5f3e130078cff 100644 --- a/packages/ui-kit/package.json +++ b/packages/ui-kit/package.json @@ -34,7 +34,7 @@ "typia": "patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch" }, "devDependencies": { - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/jest-presets": "workspace:~", "@rocket.chat/tsconfig": "workspace:*", "@types/jest": "~30.0.0", diff --git a/packages/ui-video-conf/package.json b/packages/ui-video-conf/package.json index a1412b95275c4..151ab756c85dc 100644 --- a/packages/ui-video-conf/package.json +++ b/packages/ui-video-conf/package.json @@ -25,7 +25,7 @@ "@rocket.chat/fuselage": "^0.79.0", "@rocket.chat/fuselage-hooks": "^0.41.0", "@rocket.chat/fuselage-tokens": "~0.33.2", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/jest-presets": "workspace:~", "@rocket.chat/storybook-config": "workspace:~", "@rocket.chat/styled": "^0.33.0", diff --git a/packages/ui-voip/package.json b/packages/ui-voip/package.json index 6643c47f812c1..cae9475f57e75 100644 --- a/packages/ui-voip/package.json +++ b/packages/ui-voip/package.json @@ -34,7 +34,7 @@ "@rocket.chat/fuselage-hooks": "^0.41.0", "@rocket.chat/fuselage-tokens": "~0.33.2", "@rocket.chat/fuselage-ui-kit": "workspace:^", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/jest-presets": "workspace:~", "@rocket.chat/mock-providers": "workspace:~", "@rocket.chat/storybook-config": "workspace:~", diff --git a/packages/web-ui-registration/package.json b/packages/web-ui-registration/package.json index c6a275ea8aa70..d9b19676a74e1 100644 --- a/packages/web-ui-registration/package.json +++ b/packages/web-ui-registration/package.json @@ -27,7 +27,7 @@ "@rocket.chat/fuselage-hooks": "^0.41.0", "@rocket.chat/fuselage-tokens": "~0.33.2", "@rocket.chat/i18n": "workspace:~", - "@rocket.chat/icons": "~0.47.0", + "@rocket.chat/icons": "^0.48.0", "@rocket.chat/layout": "^0.34.3", "@rocket.chat/mock-providers": "workspace:~", "@rocket.chat/rest-typings": "workspace:~", diff --git a/yarn.lock b/yarn.lock index c8dd5bd7f617a..116ec22ea0813 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9089,7 +9089,7 @@ __metadata: "@rocket.chat/core-typings": "workspace:^" "@rocket.chat/federation-sdk": "npm:0.6.3" "@rocket.chat/http-router": "workspace:^" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/jest-presets": "workspace:~" "@rocket.chat/media-signaling": "workspace:^" "@rocket.chat/message-parser": "workspace:^" @@ -9112,7 +9112,7 @@ __metadata: resolution: "@rocket.chat/core-typings@workspace:packages/core-typings" dependencies: "@rocket.chat/apps-engine": "workspace:^" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/message-parser": "workspace:^" "@rocket.chat/ui-kit": "workspace:~" "@types/express": "npm:^4.17.25" @@ -9407,7 +9407,7 @@ __metadata: "@rocket.chat/fuselage-hooks": "npm:^0.41.0" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" "@rocket.chat/gazzodown": "workspace:^" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/jest-presets": "workspace:~" "@rocket.chat/mock-providers": "workspace:^" "@rocket.chat/storybook-config": "workspace:~" @@ -9490,7 +9490,7 @@ __metadata: "@rocket.chat/fuselage": "npm:^0.79.0" "@rocket.chat/fuselage-hooks": "npm:^0.41.0" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/jest-presets": "workspace:~" "@rocket.chat/message-parser": "workspace:^" "@rocket.chat/storybook-config": "workspace:~" @@ -9581,10 +9581,10 @@ __metadata: languageName: unknown linkType: soft -"@rocket.chat/icons@npm:~0.47.0": - version: 0.47.0 - resolution: "@rocket.chat/icons@npm:0.47.0" - checksum: 10/1a7a99a4bd7227f81225dc79bd966057dae1200c461320e7627ebfe2e2cee3a4d62e2577fb0892a9c1d79d57cb38cb69bd523ea1741587203a063c68b7f508d4 +"@rocket.chat/icons@npm:^0.48.0": + version: 0.48.0 + resolution: "@rocket.chat/icons@npm:0.48.0" + checksum: 10/29a8367a541c2dc0ee4d17b6601336aff4a22b84ccd1c743fd85a3d59185695d98bda1703271383142eec966af981b611fdf6f302cc2ba5040c431eeeb7a9536 languageName: node linkType: hard @@ -9941,7 +9941,7 @@ __metadata: "@rocket.chat/gazzodown": "workspace:^" "@rocket.chat/http-router": "workspace:^" "@rocket.chat/i18n": "workspace:^" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/instance-status": "workspace:^" "@rocket.chat/jest-presets": "workspace:~" "@rocket.chat/jwt": "workspace:^" @@ -10818,7 +10818,7 @@ __metadata: "@rocket.chat/fuselage": "npm:^0.79.0" "@rocket.chat/fuselage-hooks": "npm:^0.41.0" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/tsconfig": "workspace:*" "@storybook/addon-a11y": "npm:^9.1.13" "@storybook/addon-docs": "npm:^9.1.13" @@ -10913,7 +10913,7 @@ __metadata: "@rocket.chat/fuselage": "npm:^0.79.0" "@rocket.chat/fuselage-hooks": "npm:^0.41.0" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/ui-contexts": "workspace:^" "@types/react": "npm:~18.3.28" "@types/react-dom": "npm:~18.3.7" @@ -10940,7 +10940,7 @@ __metadata: "@rocket.chat/fuselage": "npm:^0.79.0" "@rocket.chat/fuselage-hooks": "npm:^0.41.0" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/jest-presets": "workspace:~" "@rocket.chat/layout": "npm:^0.34.3" "@rocket.chat/logo": "npm:^0.32.5" @@ -10997,7 +10997,7 @@ __metadata: "@rocket.chat/fuselage": "npm:^0.79.0" "@rocket.chat/fuselage-hooks": "npm:^0.41.0" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/jest-presets": "workspace:~" "@rocket.chat/mock-providers": "workspace:~" "@rocket.chat/storybook-config": "workspace:~" @@ -11038,7 +11038,7 @@ __metadata: "@rocket.chat/fuselage-hooks": "npm:^0.41.0" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" "@rocket.chat/i18n": "workspace:~" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/jest-presets": "workspace:~" "@rocket.chat/password-policies": "workspace:^" "@rocket.chat/rest-typings": "workspace:^" @@ -11069,7 +11069,7 @@ __metadata: version: 0.0.0-use.local resolution: "@rocket.chat/ui-kit@workspace:packages/ui-kit" dependencies: - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/jest-presets": "workspace:~" "@rocket.chat/tsconfig": "workspace:*" "@types/jest": "npm:~30.0.0" @@ -11096,7 +11096,7 @@ __metadata: "@rocket.chat/fuselage": "npm:^0.79.0" "@rocket.chat/fuselage-hooks": "npm:^0.41.0" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/jest-presets": "workspace:~" "@rocket.chat/storybook-config": "workspace:~" "@rocket.chat/styled": "npm:^0.33.0" @@ -11144,7 +11144,7 @@ __metadata: "@rocket.chat/fuselage-hooks": "npm:^0.41.0" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" "@rocket.chat/fuselage-ui-kit": "workspace:^" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/jest-presets": "workspace:~" "@rocket.chat/media-signaling": "workspace:~" "@rocket.chat/mock-providers": "workspace:~" @@ -11209,7 +11209,7 @@ __metadata: "@rocket.chat/fuselage-toastbar": "npm:^0.35.2" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" "@rocket.chat/fuselage-ui-kit": "workspace:~" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/logo": "npm:^0.32.5" "@rocket.chat/styled": "npm:^0.33.0" "@rocket.chat/tsconfig": "workspace:*" @@ -11246,7 +11246,7 @@ __metadata: "@rocket.chat/fuselage-hooks": "npm:^0.41.0" "@rocket.chat/fuselage-tokens": "npm:~0.33.2" "@rocket.chat/i18n": "workspace:~" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/layout": "npm:^0.34.3" "@rocket.chat/mock-providers": "workspace:~" "@rocket.chat/rest-typings": "workspace:~" @@ -33041,7 +33041,7 @@ __metadata: "@rocket.chat/core-services": "workspace:^" "@rocket.chat/core-typings": "workspace:^" "@rocket.chat/emitter": "npm:^0.32.0" - "@rocket.chat/icons": "npm:~0.47.0" + "@rocket.chat/icons": "npm:^0.48.0" "@rocket.chat/message-parser": "workspace:^" "@rocket.chat/model-typings": "workspace:^" "@rocket.chat/models": "workspace:^"