Skip to content

Commit

Permalink
chore!: make custom sounds page stop to use query param (#33499)
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcosSpessatto authored and ggazzo committed Oct 17, 2024
1 parent 9662e1a commit 7da9ec6
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 84 deletions.
2 changes: 1 addition & 1 deletion apps/meteor/app/api/server/helpers/parseJsonQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export async function parseJsonQuery(api: PartialThis): Promise<{
'/api/v1/channels.files',
'/api/v1/integrations.list',
'/api/v1/custom-user-status.list',
'/api/v1/custom-sounds.list',
].includes(route);

const isUnsafeQueryParamsAllowed = process.env.ALLOW_UNSAFE_QUERY_AND_FIELDS_API_PARAMS?.toUpperCase() === 'TRUE';
Expand All @@ -70,7 +71,6 @@ export async function parseJsonQuery(api: PartialThis): Promise<{
try {
apiDeprecationLogger.parameter(route, 'fields', '8.0.0', response, messageGenerator);
fields = JSON.parse(params.fields) as Record<string, 0 | 1>;

Object.entries(fields).forEach(([key, value]) => {
if (value !== 1 && value !== 0) {
throw new Meteor.Error('error-invalid-sort-parameter', `Invalid fields parameter: ${key}`, {
Expand Down
16 changes: 13 additions & 3 deletions apps/meteor/app/api/server/v1/custom-sounds.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import { CustomSounds } from '@rocket.chat/models';
import { isCustomSoundsListProps } from '@rocket.chat/rest-typings';
import { escapeRegExp } from '@rocket.chat/string-helpers';

import { API } from '../api';
import { getPaginationItems } from '../helpers/getPaginationItems';

API.v1.addRoute(
'custom-sounds.list',
{ authRequired: true },
{ authRequired: true, validateParams: isCustomSoundsListProps },
{
async get() {
const { offset, count } = await getPaginationItems(this.queryParams);
const { offset, count } = await getPaginationItems(this.queryParams as Record<string, string | number | null | undefined>);
const { sort, query } = await this.parseJsonQuery();
const { cursor, totalCount } = CustomSounds.findPaginated(query, {

const { name } = this.queryParams;

const filter = {
...query,
...(name ? { name: { $regex: escapeRegExp(name as string), $options: 'i' } } : {}),
};

const { cursor, totalCount } = CustomSounds.findPaginated(filter, {
sort: sort || { name: 1 },
skip: offset,
limit: count,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Pagination, States, StatesIcon, StatesActions, StatesAction, StatesTitle } from '@rocket.chat/fuselage';
import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
import { escapeRegExp } from '@rocket.chat/string-helpers';
import { useTranslation, useEndpoint } from '@rocket.chat/ui-contexts';
import { useQuery } from '@tanstack/react-query';
import type { MutableRefObject } from 'react';
Expand Down Expand Up @@ -34,7 +33,7 @@ const CustomSoundsTable = ({ reload, onClick }: CustomSoundsTableProps) => {
const query = useDebouncedValue(
useMemo(
() => ({
query: JSON.stringify({ name: { $regex: escapeRegExp(text), $options: 'i' } }),
name: text,
sort: `{ "${sortBy}": ${sortDirection === 'asc' ? 1 : -1} }`,
...(itemsPerPage && { count: itemsPerPage }),
...(current && { offset: current }),
Expand Down
130 changes: 83 additions & 47 deletions apps/meteor/tests/end-to-end/api/custom-sounds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,76 @@ import { before, describe, it, after } from 'mocha';

import { getCredentials, api, request, credentials } from '../../data/api-data';

async function insertOrUpdateSound(fileName: string, fileId?: string): Promise<string> {
fileId = fileId ?? '';

await request
.post(api('method.call/insertOrUpdateSound'))
.set(credentials)
.send({
message: JSON.stringify({
msg: 'method',
id: '1',
method: 'insertOrUpdateSound',
params: [{ name: fileName, extension: 'mp3', newFile: true }],
}),
})
.expect(200)
.expect((res) => {
fileId = JSON.parse(res.body.message).result;
});

return fileId;
}

async function uploadCustomSound(binary: string, fileName: string, fileId: string) {
await request
.post(api('method.call/uploadCustomSound'))
.set(credentials)
.send({
message: JSON.stringify({
msg: 'method',
id: '2',
method: 'uploadCustomSound',
params: [binary, 'audio/wav', { name: fileName, extension: 'wav', newFile: true, _id: fileId }],
}),
})
.expect(200);
}

describe('[CustomSounds]', () => {
const fileName = `test-file-${randomUUID()}`;
let fileId: string;
let fileId2: string;
let uploadDate: unknown;

before((done) => getCredentials(done));

before(async () => {
const data = readFileSync(path.resolve(__dirname, '../../mocks/files/audio_mock.wav'));
const binary = data.toString('binary');

fileId = await insertOrUpdateSound(fileName);
fileId2 = await insertOrUpdateSound(`${fileName}-2`);

await uploadCustomSound(binary, fileName, fileId);
await uploadCustomSound(binary, `${fileName}-2`, fileId2);
});

after(() =>
request
.post(api('method.call/deleteCustomSound'))
.set(credentials)
.send({
message: JSON.stringify({
msg: 'method',
id: '33',
method: 'deleteCustomSound',
params: [fileId],
}),
}),
);

describe('[/custom-sounds.list]', () => {
it('should return custom sounds', (done) => {
void request
Expand Down Expand Up @@ -41,59 +108,28 @@ describe('[CustomSounds]', () => {
})
.end(done);
});
});

describe('Accessing custom sounds', () => {
let fileId: string;
const fileName = `test-file-${randomUUID()}`;
let uploadDate: unknown;

before(async () => {
const data = readFileSync(path.resolve(__dirname, '../../mocks/files/audio_mock.wav'));
const binary = data.toString('binary');
await request
.post(api('method.call/insertOrUpdateSound'))
it('should return custom sounds filtering it using the `name` parameter', (done) => {
void request
.get(api('custom-sounds.list'))
.set(credentials)
.send({
message: JSON.stringify({
msg: 'method',
id: '1',
method: 'insertOrUpdateSound',
params: [{ name: fileName, extension: 'mp3', newFile: true }],
}),
})
.expect(200)
.query({
name: `${fileName}-2`,
count: 5,
offset: 0,
})
.expect((res) => {
fileId = JSON.parse(res.body.message).result;
});
await request
.post(api('method.call/uploadCustomSound'))
.set(credentials)
.send({
message: JSON.stringify({
msg: 'method',
id: '2',
method: 'uploadCustomSound',
params: [binary, 'audio/wav', { name: fileName, extension: 'wav', newFile: true, _id: fileId }],
}),
expect(res.body).to.have.property('sounds').and.to.be.an('array');
expect(res.body).to.have.property('total').to.equal(1);
expect(res.body).to.have.property('offset').to.equal(0);
expect(res.body).to.have.property('count').to.equal(1);
expect(res.body.sounds[0]._id).to.be.equal(fileId2);
})
.expect(200);
.end(done);
});
});

after(() =>
request
.post(api('method.call/deleteCustomSound'))
.set(credentials)
.send({
message: JSON.stringify({
msg: 'method',
id: '33',
method: 'deleteCustomSound',
params: [fileId],
}),
}),
);

describe('Accessing custom sounds', () => {
it('should return forbidden if the there is no fileId on the url', (done) => {
void request
.get('/custom-sounds/')
Expand Down
1 change: 1 addition & 0 deletions packages/rest-typings/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ export * from './v1/videoConference';
export * from './v1/assets';
export * from './v1/channels';
export * from './v1/customUserStatus';
export * from './v1/customSounds';
export * from './v1/subscriptionsEndpoints';
export * from './v1/mailer';
export * from './v1/mailer/MailerParamsPOST';
Expand Down
9 changes: 7 additions & 2 deletions packages/rest-typings/src/v1/customSounds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const ajv = new Ajv({
coerceTypes: true,
});

type CustomSoundsList = PaginatedRequest<{ query: string }>;
type CustomSoundsList = PaginatedRequest<{ name?: string }>;

const CustomSoundsListSchema = {
type: 'object',
Expand All @@ -25,11 +25,16 @@ const CustomSoundsListSchema = {
type: 'string',
nullable: true,
},
name: {
type: 'string',
nullable: true,
},
query: {
type: 'string',
nullable: true,
},
},
required: ['query'],
required: [],
additionalProperties: false,
};

Expand Down
29 changes: 0 additions & 29 deletions packages/rest-typings/src/v1/voip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,6 @@ const ajv = new Ajv({
coerceTypes: true,
});

/** *************************************************/
type CustomSoundsList = PaginatedRequest<{ query: string }>;

const CustomSoundsListSchema = {
type: 'object',
properties: {
count: {
type: 'number',
nullable: true,
},
offset: {
type: 'number',
nullable: true,
},
sort: {
type: 'string',
nullable: true,
},
query: {
type: 'string',
nullable: true,
},
},
required: [],
additionalProperties: false,
};

export const isCustomSoundsListProps = ajv.compile<CustomSoundsList>(CustomSoundsListSchema);

type ConnectorExtensionGetRegistrationInfoByUserId = { id: string };

const ConnectorExtensionGetRegistrationInfoByUserIdSchema: JSONSchemaType<ConnectorExtensionGetRegistrationInfoByUserId> = {
Expand Down

0 comments on commit 7da9ec6

Please sign in to comment.