🚧 WIP: backend: beginnings of a transactional editing for plugins (#525)
This commit is contained in:
@@ -1025,6 +1025,80 @@ export class DocumentsService {
|
||||
CrudException.throwMe(error, new CrudException("Failed to begin editing Drive item", 500));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End editing session either by providing a URL to a new file to create a version,
|
||||
* or not, to just cancel the session.
|
||||
* @param editing_session_key Editing key of the DriveFile
|
||||
* @param newFileUrl Optional URL to a new version of the file to store
|
||||
* @param options Optional upload information from the request
|
||||
*/
|
||||
endEditing = async (
|
||||
editing_session_key: string,
|
||||
newFileUrl: string | null,
|
||||
context: DriveExecutionContext,
|
||||
) => {
|
||||
if (!context) {
|
||||
this.logger.error("invalid execution context");
|
||||
return null;
|
||||
}
|
||||
if (!editing_session_key) {
|
||||
this.logger.error("Invalid editing_session_key: " + JSON.stringify(editing_session_key));
|
||||
throw new CrudException("Invalid editing_session_key", 400);
|
||||
}
|
||||
|
||||
const driveFile = await this.repository.findOne({ editing_session_key }, {}, context);
|
||||
if (!driveFile) {
|
||||
this.logger.error("Drive item not found by editing session key");
|
||||
throw new CrudException("Item not found by editing session key", 404);
|
||||
}
|
||||
|
||||
const hasAccess = await checkAccess(driveFile.id, driveFile, "write", this.repository, context);
|
||||
if (!hasAccess) {
|
||||
logger.error("user does not have access drive item " + driveFile.id);
|
||||
CrudException.throwMe(
|
||||
new Error("user does not have access to the drive item"),
|
||||
new CrudException("user does not have access drive item", 401),
|
||||
);
|
||||
}
|
||||
|
||||
if (newFileUrl) {
|
||||
// const response = await axios.request({
|
||||
// url: domain + req.url,
|
||||
// method: req.method as any,
|
||||
// headers: _.omit(req.headers, "host", "content-length") as {
|
||||
// [key: string]: string;
|
||||
// },
|
||||
// data: req.body as any,
|
||||
// responseType: "stream",
|
||||
// maxRedirects: 0,
|
||||
// validateStatus: null,
|
||||
// });
|
||||
//TODO: save file into new version
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await this.repository.atomicCompareAndSet(
|
||||
driveFile,
|
||||
"editing_session_key",
|
||||
editing_session_key,
|
||||
null,
|
||||
);
|
||||
if (!result.didSet)
|
||||
throw new Error(
|
||||
`Couldn't set editing_session_key ${JSON.stringify(
|
||||
editing_session_key,
|
||||
)} on DriveFile ${JSON.stringify(driveFile.id)} because it is ${JSON.stringify(
|
||||
result.currentValue,
|
||||
)}`,
|
||||
);
|
||||
return { ok: true };
|
||||
} catch (error) {
|
||||
logger.error({ error: `${error}` }, "Failed to cancel editing Drive item");
|
||||
CrudException.throwMe(error, new CrudException("Failed to cancel editing Drive item", 500));
|
||||
}
|
||||
};
|
||||
|
||||
downloadGetToken = async (
|
||||
ids: string[],
|
||||
versionId: string | null,
|
||||
|
||||
@@ -372,6 +372,44 @@ export class DocumentsController {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Finish an editing session by cancelling it.
|
||||
*/
|
||||
cancelEditing = async (
|
||||
request: FastifyRequest<{
|
||||
Params: ItemRequestByEditingSessionKeyParams;
|
||||
Body: { editorApplicationId: string };
|
||||
}>,
|
||||
) => {
|
||||
try {
|
||||
const context = getDriveExecutionContext(request);
|
||||
const { editing_session_key } = request.params;
|
||||
|
||||
if (!editing_session_key) throw new CrudException("Missing editing_session_key", 400);
|
||||
|
||||
return await globalResolver.services.documents.documents.endEditing(
|
||||
editing_session_key,
|
||||
null,
|
||||
context,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error({ error: `${error}` }, "Failed to begin editing Drive item");
|
||||
CrudException.throwMe(error, new CrudException("Failed to begin editing Drive item", 500));
|
||||
}
|
||||
};
|
||||
//TODO: will need a save under session key, but without ending the edit (for force saves)
|
||||
/**
|
||||
* Finish an editing session for a given `editing_session_key` by uploading the new version of the File
|
||||
*/
|
||||
endEditing = async (
|
||||
request: FastifyRequest<{
|
||||
Params: ItemRequestByEditingSessionKeyParams;
|
||||
Body: { editorApplicationId: string };
|
||||
}>,
|
||||
) => {
|
||||
console.log(request); // make linter happy
|
||||
};
|
||||
|
||||
downloadGetToken = async (
|
||||
request: FastifyRequest<{
|
||||
Params: ItemRequestParams;
|
||||
|
||||
@@ -94,6 +94,20 @@ const routes: FastifyPluginCallback = (fastify: FastifyInstance, _options, next)
|
||||
handler: documentsController.getByEditingSessionKey.bind(documentsController),
|
||||
});
|
||||
|
||||
fastify.route({
|
||||
method: "POST",
|
||||
url: `${serviceUrl}/editing_session/:editing_session_key`,
|
||||
preValidation: [fastify.authenticateOptional],
|
||||
handler: documentsController.endEditing.bind(documentsController),
|
||||
});
|
||||
|
||||
fastify.route({
|
||||
method: "DELETE",
|
||||
url: `${serviceUrl}/editing_session/:editing_session_key`,
|
||||
preValidation: [fastify.authenticateOptional],
|
||||
handler: documentsController.endEditing.bind(documentsController),
|
||||
});
|
||||
|
||||
fastify.route({
|
||||
method: "GET",
|
||||
url: `${serviceUrl}/download/token`,
|
||||
|
||||
@@ -171,7 +171,10 @@ class OnlyOfficeService {
|
||||
constructor() {
|
||||
this.poller = new PolledThingieValue('Connect to Only Office', () => this.getVersion(), 10 * 1000 * 60);
|
||||
}
|
||||
/** Get the latest Only Office version */
|
||||
/** Get the latest Only Office version from polling. If the return is `undefined`
|
||||
* it probably means there is a connection issue contacting the OnlyOffice server
|
||||
* from the connector.
|
||||
*/
|
||||
public getLatestVersion() {
|
||||
return this.poller.latest();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user