diff --git a/app/gen-server/ApiServer.ts b/app/gen-server/ApiServer.ts index 69c3e43b55..bbe71e8dc2 100644 --- a/app/gen-server/ApiServer.ts +++ b/app/gen-server/ApiServer.ts @@ -8,7 +8,11 @@ import pick from 'lodash/pick'; import {ApiError} from 'app/common/ApiError'; import {FullUser} from 'app/common/LoginSessionAPI'; import {BasicRole} from 'app/common/roles'; -import {OrganizationProperties, PermissionDelta} from 'app/common/UserAPI'; +import {DOCTYPE_NORMAL, + DOCTYPE_TEMPLATE, + DOCTYPE_TUTORIAL, + OrganizationProperties, + PermissionDelta} from 'app/common/UserAPI'; import {Document} from "app/gen-server/entity/Document"; import {Organization} from 'app/gen-server/entity/Organization'; import {User} from 'app/gen-server/entity/User'; @@ -295,7 +299,20 @@ export class ApiServer { // PATCH /api/docs/:did // Update the specified doc. this._app.patch('/api/docs/:did', expressWrap(async (req, res) => { + const validDocTypes = [ + DOCTYPE_NORMAL, + DOCTYPE_TEMPLATE, + DOCTYPE_TUTORIAL + ]; + + if ('type' in req.body && ! validDocTypes.includes(req.body.type)){ + const errMsg = "Bad Request. 'type' key authorized values : " + + `'${DOCTYPE_TEMPLATE}', '${DOCTYPE_TUTORIAL}' or ${DOCTYPE_NORMAL}`; + return res.status(400).send({error: errMsg}); + } + const {data, ...result} = await this._dbManager.updateDocument(getDocScope(req), req.body); + if (data && 'name' in req.body) { this._logRenameDocumentEvents(req, data); } return sendReply(req, res, {...result, data: data?.current.id}); })); diff --git a/test/gen-server/ApiServer.ts b/test/gen-server/ApiServer.ts index 7be5a268df..6455484e65 100644 --- a/test/gen-server/ApiServer.ts +++ b/test/gen-server/ApiServer.ts @@ -5,7 +5,7 @@ import {configForUser, configWithPermit, getRowCounts as getRowCountsForDb} from import * as testUtils from 'test/server/testUtils'; import {createEmptyOrgUsageSummary, OrgUsageSummary} from 'app/common/DocUsage'; -import {Document, Workspace} from 'app/common/UserAPI'; +import {DOCTYPE_NORMAL, DOCTYPE_TEMPLATE, DOCTYPE_TUTORIAL, Document, Workspace} from 'app/common/UserAPI'; import {Organization} from 'app/gen-server/entity/Organization'; import {Product} from 'app/gen-server/entity/Product'; import {HomeDBManager, UserChange} from 'app/gen-server/lib/homedb/HomeDBManager'; @@ -1274,6 +1274,21 @@ describe('ApiServer', function() { assert.deepEqual(resp.data?.options, undefined); }); + it('PATCH /api/docs/{did} supports proper values for type key', async function() { + const did = await dbManager.testGetId('Surprise2'); + // Check setting null for normal document type + let resp = await axios.patch(`${homeUrl}/api/docs/${did}`, {type: DOCTYPE_NORMAL}, chimpy); + assert.equal(resp.status, 200); + + // check setting template as document type + resp = await axios.patch(`${homeUrl}/api/docs/${did}`, {type: DOCTYPE_TEMPLATE}, chimpy); + assert.equal(resp.status, 200); + + // check setting tutorial as document type + resp = await axios.patch(`${homeUrl}/api/docs/${did}`, {type: DOCTYPE_TUTORIAL}, chimpy); + assert.equal(resp.status, 200); + }); + it('PATCH /api/docs/{did} returns 404 appropriately', async function() { // Attempt to rename a doc that doesn't exist. const resp = await axios.patch(`${homeUrl}/api/docs/9999`, { @@ -1298,6 +1313,13 @@ describe('ApiServer', function() { assert.equal(resp.status, 400); }); + it('PATCH /api/docs/{did} returns 400 on wrong type values', async function() { + // Use an unavailable property and check that the operation fails with 400. + const did = await dbManager.testGetId('Surprise2'); + const resp = await axios.patch(`${homeUrl}/api/docs/${did}`, {"type": "invalid"}, chimpy); + assert.equal(resp.status, 400); + }); + it('DELETE /api/docs/{did} is operational', async function() { const oid = await dbManager.testGetId('NASA'); const wid = await dbManager.testGetId('Rovers');