mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
Add ws id and doc name params to POST /docs (#655)
This commit is contained in:
@@ -440,9 +440,9 @@ export class DocWorkerApi {
|
||||
// Responds with attachment contents, with suitable Content-Type and Content-Disposition.
|
||||
this._app.get('/api/docs/:docId/attachments/:attId/download', canView, withDoc(async (activeDoc, req, res) => {
|
||||
const attId = integerParam(req.params.attId, 'attId');
|
||||
const tableId = optStringParam(req.params.tableId);
|
||||
const colId = optStringParam(req.params.colId);
|
||||
const rowId = optIntegerParam(req.params.rowId);
|
||||
const tableId = optStringParam(req.params.tableId, 'tableId');
|
||||
const colId = optStringParam(req.params.colId, 'colId');
|
||||
const rowId = optIntegerParam(req.params.rowId, 'rowId');
|
||||
if ((tableId || colId || rowId) && !(tableId && colId && rowId)) {
|
||||
throw new ApiError('define all of tableId, colId and rowId, or none.', 400);
|
||||
}
|
||||
@@ -720,8 +720,9 @@ export class DocWorkerApi {
|
||||
const options = {
|
||||
add: !isAffirmative(req.query.noadd),
|
||||
update: !isAffirmative(req.query.noupdate),
|
||||
onMany: stringParam(req.query.onmany || "first", "onmany",
|
||||
["first", "none", "all"]) as 'first'|'none'|'all'|undefined,
|
||||
onMany: stringParam(req.query.onmany || "first", "onmany", {
|
||||
allowed: ["first", "none", "all"],
|
||||
}) as 'first'|'none'|'all'|undefined,
|
||||
allowEmptyRequire: isAffirmative(req.query.allow_empty_require),
|
||||
};
|
||||
await ops.upsert(body.records, options);
|
||||
@@ -982,7 +983,7 @@ export class DocWorkerApi {
|
||||
// (Requires a special permit.)
|
||||
this._app.post('/api/docs/:docId/assign', canEdit, throttled(async (req, res) => {
|
||||
const docId = getDocId(req);
|
||||
const group = optStringParam(req.query.group);
|
||||
const group = optStringParam(req.query.group, 'group');
|
||||
if (group !== undefined && req.specialPermit?.action === 'assign-doc') {
|
||||
if (group.trim() === '') {
|
||||
await this._docWorkerMap.removeDocGroup(docId);
|
||||
@@ -1148,7 +1149,12 @@ export class DocWorkerApi {
|
||||
const userId = getUserId(req);
|
||||
const wsId = integerParam(req.params.wid, 'wid');
|
||||
const uploadId = integerParam(req.body.uploadId, 'uploadId');
|
||||
const result = await this._docManager.importDocToWorkspace(userId, uploadId, wsId, req.body.browserSettings);
|
||||
const result = await this._docManager.importDocToWorkspace({
|
||||
userId,
|
||||
uploadId,
|
||||
workspaceId: wsId,
|
||||
browserSettings: req.body.browserSettings,
|
||||
});
|
||||
res.json(result);
|
||||
}));
|
||||
|
||||
@@ -1215,16 +1221,22 @@ export class DocWorkerApi {
|
||||
})
|
||||
);
|
||||
|
||||
// Create a document. When an upload is included, it is imported as the initial
|
||||
// state of the document. Otherwise a fresh empty document is created.
|
||||
// A "timezone" option can be supplied.
|
||||
// Documents are created "unsaved".
|
||||
// TODO: support workspaceId option for creating regular documents, at which point
|
||||
// existing import endpoint and doc creation endpoint can share implementation
|
||||
// with this.
|
||||
// Returns the id of the created document.
|
||||
/**
|
||||
* Create a document.
|
||||
*
|
||||
* When an upload is included, it is imported as the initial state of the document.
|
||||
* Otherwise, the document is left empty.
|
||||
*
|
||||
* If a workspace id is included, the document will be saved there instead of
|
||||
* being left "unsaved".
|
||||
*
|
||||
* Returns the id of the created document.
|
||||
*
|
||||
* TODO: unify this with the other document creation and import endpoints.
|
||||
*/
|
||||
this._app.post('/api/docs', expressWrap(async (req, res) => {
|
||||
const userId = getUserId(req);
|
||||
|
||||
let uploadId: number|undefined;
|
||||
let parameters: {[key: string]: any};
|
||||
if (req.is('multipart/form-data')) {
|
||||
@@ -1236,22 +1248,52 @@ export class DocWorkerApi {
|
||||
} else {
|
||||
parameters = req.body;
|
||||
}
|
||||
if (parameters.workspaceId) { throw new Error('workspaceId not supported'); }
|
||||
|
||||
const documentName = optStringParam(parameters.documentName, 'documentName', {
|
||||
allowEmpty: false,
|
||||
});
|
||||
const workspaceId = optIntegerParam(parameters.workspaceId, 'workspaceId');
|
||||
const browserSettings: BrowserSettings = {};
|
||||
if (parameters.timezone) { browserSettings.timezone = parameters.timezone; }
|
||||
browserSettings.locale = localeFromRequest(req);
|
||||
|
||||
let docId: string;
|
||||
if (uploadId !== undefined) {
|
||||
const result = await this._docManager.importDocToWorkspace(userId, uploadId, null,
|
||||
browserSettings);
|
||||
return res.json(result.id);
|
||||
const result = await this._docManager.importDocToWorkspace({
|
||||
userId,
|
||||
uploadId,
|
||||
documentName,
|
||||
workspaceId,
|
||||
browserSettings,
|
||||
});
|
||||
docId = result.id;
|
||||
} else if (workspaceId !== undefined) {
|
||||
const {status, data, errMessage} = await this._dbManager.addDocument(getScope(req), workspaceId, {
|
||||
name: documentName ?? 'Untitled document',
|
||||
});
|
||||
if (status !== 200) {
|
||||
throw new ApiError(errMessage || 'unable to create document', status);
|
||||
}
|
||||
|
||||
docId = data!;
|
||||
} else {
|
||||
const isAnonymous = isAnonymousUser(req);
|
||||
const result = makeForkIds({
|
||||
userId,
|
||||
isAnonymous,
|
||||
trunkDocId: NEW_DOCUMENT_CODE,
|
||||
trunkUrlId: NEW_DOCUMENT_CODE,
|
||||
});
|
||||
docId = result.docId;
|
||||
await this._docManager.createNamedDoc(
|
||||
makeExceptionalDocSession('nascent', {
|
||||
req: req as RequestWithLogin,
|
||||
browserSettings,
|
||||
}),
|
||||
docId
|
||||
);
|
||||
}
|
||||
const isAnonymous = isAnonymousUser(req);
|
||||
const {docId} = makeForkIds({userId, isAnonymous, trunkDocId: NEW_DOCUMENT_CODE,
|
||||
trunkUrlId: NEW_DOCUMENT_CODE});
|
||||
await this._docManager.createNamedDoc(makeExceptionalDocSession('nascent', {
|
||||
req: req as RequestWithLogin,
|
||||
browserSettings
|
||||
}), docId);
|
||||
|
||||
return res.status(200).json(docId);
|
||||
}));
|
||||
}
|
||||
@@ -1556,7 +1598,7 @@ export class DocWorkerApi {
|
||||
}
|
||||
const timeout =
|
||||
Math.max(0, Math.min(MAX_CUSTOM_SQL_MSEC,
|
||||
optIntegerParam(options.timeout) || MAX_CUSTOM_SQL_MSEC));
|
||||
optIntegerParam(options.timeout, 'timeout') || MAX_CUSTOM_SQL_MSEC));
|
||||
// Wrap in a select to commit to the SELECT branch of SQLite
|
||||
// grammar. Note ; isn't a problem.
|
||||
//
|
||||
@@ -1639,7 +1681,7 @@ export interface QueryParameters {
|
||||
* as a header.
|
||||
*/
|
||||
function getSortParameter(req: Request): string[]|undefined {
|
||||
const sortString: string|undefined = optStringParam(req.query.sort) || req.get('X-Sort');
|
||||
const sortString: string|undefined = optStringParam(req.query.sort, 'sort') || req.get('X-Sort');
|
||||
if (!sortString) { return undefined; }
|
||||
return sortString.split(',');
|
||||
}
|
||||
@@ -1650,7 +1692,7 @@ function getSortParameter(req: Request): string[]|undefined {
|
||||
* parameter, or as a header.
|
||||
*/
|
||||
function getLimitParameter(req: Request): number|undefined {
|
||||
const limitString: string|undefined = optStringParam(req.query.limit) || req.get('X-Limit');
|
||||
const limitString: string|undefined = optStringParam(req.query.limit, 'limit') || req.get('X-Limit');
|
||||
if (!limitString) { return undefined; }
|
||||
const limit = parseInt(limitString, 10);
|
||||
if (isNaN(limit)) { throw new Error('limit is not a number'); }
|
||||
|
||||
Reference in New Issue
Block a user