chore: Adds deprecation warning on `livechat:removeCustomField` with new endpoint replacing it (#36933)

pull/36940/head^2
Lucas Pelegrino 9 months ago committed by GitHub
parent 89c1a6ae40
commit 8d2ad40c46
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      .changeset/cool-pets-switch.md
  2. 43
      apps/meteor/app/livechat/server/api/v1/customField.ts
  3. 2
      apps/meteor/app/livechat/server/methods/removeCustomField.ts
  4. 6
      apps/meteor/client/views/omnichannel/customFields/useRemoveCustomField.tsx
  5. 11
      apps/meteor/tests/data/livechat/custom-fields.ts
  6. 20
      apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center.spec.ts
  7. 30
      packages/rest-typings/src/v1/omnichannel.ts

@ -0,0 +1,6 @@
---
"@rocket.chat/meteor": patch
"@rocket.chat/rest-typings": patch
---
Adds deprecation warning on `livechat:removeCustomField` with new endpoint replacing it; `livechat/custom-fields.delete`

@ -1,6 +1,16 @@
import { isLivechatCustomFieldsProps, isPOSTLivechatCustomFieldParams, isPOSTLivechatCustomFieldsParams } from '@rocket.chat/rest-typings';
import { LivechatCustomField } from '@rocket.chat/models';
import {
isLivechatCustomFieldsProps,
isPOSTLivechatCustomFieldParams,
isPOSTLivechatCustomFieldsParams,
isPOSTLivechatRemoveCustomFields,
POSTLivechatRemoveCustomFieldSuccess,
validateBadRequestErrorResponse,
validateUnauthorizedErrorResponse,
} from '@rocket.chat/rest-typings';
import { API } from '../../../../api/server';
import type { ExtractRoutesFromAPI } from '../../../../api/server/ApiClass';
import { getPaginationItems } from '../../../../api/server/helpers/getPaginationItems';
import { setCustomFields, setMultipleCustomFields } from '../../lib/custom-fields';
import { findLivechatCustomFields, findCustomFieldById } from '../lib/customFields';
@ -80,3 +90,34 @@ API.v1.addRoute(
},
},
);
const livechatCustomFieldsEndpoints = API.v1.post(
'livechat/custom-fields.delete',
{
response: {
200: POSTLivechatRemoveCustomFieldSuccess,
400: validateBadRequestErrorResponse,
401: validateUnauthorizedErrorResponse,
},
authRequired: true,
permissionsRequired: ['view-livechat-manager'], // is this permission appropriate for the targeted action?
body: isPOSTLivechatRemoveCustomFields,
},
async function action() {
const { customFieldId } = this.bodyParams;
const result = await LivechatCustomField.removeById(customFieldId);
if (result.deletedCount === 0) {
return API.v1.failure('Custom field not found');
}
return API.v1.success();
},
);
type LivechatCustomFieldsEndpoints = ExtractRoutesFromAPI<typeof livechatCustomFieldsEndpoints>;
declare module '@rocket.chat/rest-typings' {
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface
interface Endpoints extends LivechatCustomFieldsEndpoints {}
}

@ -5,6 +5,7 @@ import { Meteor } from 'meteor/meteor';
import type { DeleteResult } from 'mongodb';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
@ -15,6 +16,7 @@ declare module '@rocket.chat/ddp-client' {
Meteor.methods<ServerMethods>({
async 'livechat:removeCustomField'(_id) {
methodDeprecationLogger.method('livechat:removeCustomField', '8.0.0', '/v1/livechat/custom-fields.delete');
const uid = Meteor.userId();
if (!uid || !(await hasPermissionAsync(uid, 'view-livechat-manager'))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', {

@ -1,6 +1,6 @@
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
import { GenericModal } from '@rocket.chat/ui-client';
import { useSetModal, useToastMessageDispatch, useMethod } from '@rocket.chat/ui-contexts';
import { useSetModal, useToastMessageDispatch, useEndpoint } from '@rocket.chat/ui-contexts';
import { useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
@ -8,13 +8,13 @@ export const useRemoveCustomField = () => {
const { t } = useTranslation();
const setModal = useSetModal();
const dispatchToastMessage = useToastMessageDispatch();
const removeCustomField = useMethod('livechat:removeCustomField');
const removeCustomField = useEndpoint('POST', '/v1/livechat/custom-fields.delete');
const queryClient = useQueryClient();
const handleDelete = useEffectEvent((id: string) => {
const onDeleteAgent = async () => {
try {
await removeCustomField(id);
await removeCustomField({ customFieldId: id });
dispatchToastMessage({ type: 'success', message: t('Custom_Field_Removed') });
queryClient.invalidateQueries({
queryKey: ['livechat-customFields'],

@ -42,16 +42,11 @@ export const createCustomField = (customField: ExtendedCustomField): Promise<Ext
export const deleteCustomField = (customFieldID: string) =>
new Promise((resolve, reject) => {
void request
.post(methodCall('livechat:removeCustomField'))
.post(api('livechat/custom-fields.delete'))
.set(credentials)
.send({
message: JSON.stringify({
method: 'livechat:removeCustomField',
params: [customFieldID],
id: 'id',
msg: 'method',
}),
customFieldId: customFieldID,
})
.set(credentials)
.end((err: Error, res: Response): void => {
if (err) {
return reject(err);

@ -1,7 +1,6 @@
import { faker } from '@faker-js/faker';
import { createToken } from '../../../client/lib/utils/createToken';
import { IS_EE } from '../config/constants';
import { Users } from '../fixtures/userStates';
import { OmnichannelContacts } from '../page-objects/omnichannel-contacts-list';
import { OmnichannelSection } from '../page-objects/omnichannel-section';
@ -32,17 +31,6 @@ const DELETE_CONTACT = {
phones: [faker.phone.number('+############')],
};
const NEW_CUSTOM_FIELD = {
searchable: true,
field: 'hiddenCustomField',
label: 'hiddenCustomField',
defaultValue: 'test_contact_center_hidden_customField',
scope: 'visitor',
visibility: 'hidden',
required: true,
regexp: '',
};
const URL = {
contactCenter: '/omnichannel-directory/contacts',
newContact: '/omnichannel-directory/contacts/new',
@ -72,19 +60,11 @@ test.describe('Omnichannel Contact Center', () => {
test.beforeAll(async ({ api }) => {
// Add contacts
await Promise.all([api.post('/omnichannel/contacts', EXISTING_CONTACT), api.post('/omnichannel/contacts', DELETE_CONTACT)]);
if (IS_EE) {
await api.post('/livechat/custom.field', NEW_CUSTOM_FIELD);
}
});
test.afterAll(async ({ api }) => {
// Remove added contacts
await Promise.all([api.delete(`/livechat/visitor/${NEW_CONTACT.token}`), api.delete(`/livechat/visitor/${EXISTING_CONTACT.token}`)]);
if (IS_EE) {
await api.post('method.call/livechat:removeCustomField', { message: NEW_CUSTOM_FIELD.field });
}
});
test.beforeEach(async ({ page }) => {

@ -3989,6 +3989,36 @@ export const isPOSTLivechatRoomsCloseAllSuccessResponse = ajv.compile<{ removedR
POSTLivechatRoomsCloseAllSuccessResponseSchema,
);
type POSTLivechatRemoveCustomFields = {
customFieldId: string;
};
const POSTLivechatRemoveCustomFieldsSchema = {
type: 'object',
properties: {
customFieldId: {
type: 'string',
},
},
required: ['customFieldId'],
additionalProperties: false,
};
export const isPOSTLivechatRemoveCustomFields = ajv.compile<POSTLivechatRemoveCustomFields>(POSTLivechatRemoveCustomFieldsSchema);
const POSTLivechatRemoveCustomFieldSuccessSchema = {
type: 'object',
properties: {
success: {
type: 'boolean',
enum: [true],
},
},
additionalProperties: false,
};
export const POSTLivechatRemoveCustomFieldSuccess = ajv.compile<void>(POSTLivechatRemoveCustomFieldSuccessSchema);
export type ILivechatContactWithManagerData = Omit<ILivechatContact, 'contactManager'> & {
contactManager?: Pick<IUser, '_id' | 'name' | 'username'>;
};

Loading…
Cancel
Save