diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 2b5043c9..00000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "repo/src/main/resources/newdocs"] - path = repo/src/main/resources/newdocs - url = https://github.com/ONLYOFFICE/document-templates - branch = main/new diff --git a/CHANGELOG.md b/CHANGELOG.md index c3524300..60ac7729 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## ## Added +- core of the plugin has been moved to com.onlyoffice.docs-integration-sdk (https://github.com/ONLYOFFICE/docs-integration-sdk-java) - document server v6.4 and earlier is no longer supported - ## 6.1.0 diff --git a/pom.xml b/pom.xml index 1efe3f7e..0c7eeef9 100644 --- a/pom.xml +++ b/pom.xml @@ -113,6 +113,11 @@ jackson-databind 2.13.3 + + com.onlyoffice + docs-integration-sdk + 1.0.0 + diff --git a/repo/pom.xml b/repo/pom.xml index 12e16ccb..a30b6bee 100644 --- a/repo/pom.xml +++ b/repo/pom.xml @@ -25,6 +25,11 @@ com.fasterxml.jackson.core jackson-databind + + + com.onlyoffice + docs-integration-sdk + diff --git a/repo/src/main/java/com/parashift/onlyoffice/actions/ConvertAction.java b/repo/src/main/java/com/parashift/onlyoffice/actions/ConvertAction.java index dff064ab..160ff4df 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/actions/ConvertAction.java +++ b/repo/src/main/java/com/parashift/onlyoffice/actions/ConvertAction.java @@ -1,16 +1,22 @@ package com.parashift.onlyoffice.actions; +import java.io.IOException; import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Map; -import com.parashift.onlyoffice.util.ConfigManager; -import com.parashift.onlyoffice.util.ConvertManager; +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.request.RequestManager; +import com.onlyoffice.manager.settings.SettingsManager; +import com.onlyoffice.model.convertservice.ConvertRequest; +import com.onlyoffice.model.convertservice.ConvertResponse; +import com.onlyoffice.service.convert.ConvertService; import com.parashift.onlyoffice.util.Util; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; +import org.alfresco.repo.i18n.MessageService; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.coci.CheckOutCheckInService; @@ -24,6 +30,7 @@ import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.apache.http.HttpEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -37,9 +44,6 @@ public class ConvertAction extends ActionExecuterAbstractBase { private Logger logger = LoggerFactory.getLogger(this.getClass()); - @Autowired - ConvertManager converterService; - @Autowired NodeService nodeService; @@ -56,10 +60,22 @@ public class ConvertAction extends ActionExecuterAbstractBase { Util util; @Autowired - ConfigManager configManager; + CheckOutCheckInService checkOutCheckInService; + + @Autowired + DocumentManager documentManager; @Autowired - CheckOutCheckInService checkOutCheckInService; + SettingsManager settingsManager; + + @Autowired + ConvertService convertService; + + @Autowired + MessageService mesService; + + @Autowired + RequestManager requestManager; @Override protected void executeImpl(Action action, NodeRef actionedUponNodeRef) { @@ -67,11 +83,12 @@ protected void executeImpl(Action action, NodeRef actionedUponNodeRef) { if (permissionService.hasPermission(actionedUponNodeRef, PermissionService.READ) == AccessStatus.ALLOWED) { if (!checkOutCheckInService.isCheckedOut(actionedUponNodeRef) && !checkOutCheckInService.isWorkingCopy(actionedUponNodeRef)) { - String title = util.getTitleWithoutExtension(actionedUponNodeRef); - String srcExt = util.getExtension(actionedUponNodeRef); + String fileName = documentManager.getDocumentName(actionedUponNodeRef.toString()); - String targetExt = converterService.getTargetExt(srcExt); + String title = documentManager.getBaseName(fileName); + String srcExt = documentManager.getExtension(fileName); + String targetExt = documentManager.getDefaultConvertExtension(fileName); if (targetExt == null) { logger.debug("Files of " + srcExt + " format cannot be converted"); return; @@ -90,7 +107,7 @@ protected void executeImpl(Action action, NodeRef actionedUponNodeRef) { Boolean deleteNode = false; Boolean checkoutNode = false; - if (configManager.getAsBoolean("convertOriginal", "false") && !targetExt.equals("oform")) { + if (settingsManager.getSettingBoolean("convertOriginal", false) && !targetExt.equals("oform")) { logger.debug("Updating node"); if (permissionService.hasPermission(actionedUponNodeRef, PermissionService.WRITE) == AccessStatus.ALLOWED) { util.ensureVersioningEnabled(actionedUponNodeRef); @@ -122,7 +139,31 @@ protected void executeImpl(Action action, NodeRef actionedUponNodeRef) { logger.debug("Invoking .transform()"); writer = this.contentService.getWriter(writeNode, ContentModel.PROP_CONTENT, true); writer.setMimetype(mimetypeService.getMimetype(targetExt)); - converterService.transform(actionedUponNodeRef, srcExt, targetExt, writer); + + ConvertRequest convertRequest = ConvertRequest.builder() + .region(mesService.getLocale().toLanguageTag()) + .build(); + + ConvertResponse convertResponse = convertService.processConvert(convertRequest, + actionedUponNodeRef.toString()); + + if (convertResponse.getError() != null && convertResponse.getError().equals(ConvertResponse.Error.TOKEN)) { + throw new SecurityException(); + } + + if (convertResponse.getEndConvert() == null || !convertResponse.getEndConvert() + || convertResponse.getFileUrl() == null || convertResponse.getFileUrl().isEmpty()) { + throw new Exception("'endConvert' is false or 'fileUrl' is empty"); + } + + final ContentWriter finalWriter = writer; + requestManager.executeGetRequest(convertResponse.getFileUrl(), new RequestManager.Callback() { + public Void doWork(Object response) throws IOException { + finalWriter.putContent(((HttpEntity)response).getContent()); + return null; + } + }); + if (checkoutNode) { logger.debug("Checking in node"); checkOutCheckInService.checkin(writeNode, null); diff --git a/repo/src/main/java/com/parashift/onlyoffice/constants/Format.java b/repo/src/main/java/com/parashift/onlyoffice/constants/Format.java deleted file mode 100644 index 2acaaa83..00000000 --- a/repo/src/main/java/com/parashift/onlyoffice/constants/Format.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.parashift.onlyoffice.constants; - -import java.util.List; - -/* - Copyright (c) Ascensio System SIA 2023. All rights reserved. - http://www.onlyoffice.com -*/ - -public class Format { - public String name; - public Type type; - public boolean edit; - public List convertTo; - - public Format(String name, Type type, List convertTo) { - this.name = name; - this.type = type; - this.edit = false; - this.convertTo = convertTo; - } - - public Format(String name, Type type, boolean edit, List convertTo) { - this.name = name; - this.type = type; - this.edit = edit; - this.convertTo = convertTo; - } - - public String getName() { - return name; - } - - public Type getType() { return type; } - - public boolean isEdit() { return edit; } - - public List getConvertTo() { - return convertTo; - } - - public void setName(String name) { - this.name = name; - } - - public void setType(Type type) { this.type = type; } - - public void setConvertTo(List convertTo) { - this.convertTo = convertTo; - } - - public void setEdit(boolean edit) { this.edit = edit; } -} \ No newline at end of file diff --git a/repo/src/main/java/com/parashift/onlyoffice/constants/Formats.java b/repo/src/main/java/com/parashift/onlyoffice/constants/Formats.java deleted file mode 100644 index b98ab64b..00000000 --- a/repo/src/main/java/com/parashift/onlyoffice/constants/Formats.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.parashift.onlyoffice.constants; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.*; - -/* - Copyright (c) Ascensio System SIA 2023. All rights reserved. - http://www.onlyoffice.com -*/ - -public class Formats { - public static final List formats = new ArrayList() {{ - add(new Format("djvu", Type.WORD, new ArrayList())); - add(new Format("doc", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "epub", "fb2", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("docm", Type.WORD, Arrays.asList("docx", "docxf", "dotx", "dotm", "epub", "fb2", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("docx", Type.WORD, true, Arrays.asList("docm", "dotx", "dotm", "docxf", "epub", "fb2", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("docxf", Type.FORM, true, Arrays.asList("docm", "docx", "oform", "dotx", "dotm", "epub", "fb2", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("oform", Type.WORD, true, Arrays.asList( "pdf"))); - add(new Format("dot", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "epub", "fb2", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("dotm", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "epub", "fb2", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("dotx", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotm", "epub", "fb2", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("epub", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "fb2", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("fb2", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "epub", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("fodt", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "epub", "fb2", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("html", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "epub", "fb2", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("mht", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "epub", "fb2", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("odt", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "epub", "fb2", "html", "ott", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("ott", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "epub", "fb2", "html", "odt", "pdf", "pdfa", "rtf", "txt"))); - add(new Format("pdf", Type.WORD, new ArrayList())); - add(new Format("rtf", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "epub", "fb2", "html", "odt", "ott", "pdf", "pdfa", "txt"))); - add(new Format("txt", Type.WORD, new ArrayList())); - add(new Format("xps", Type.WORD, Arrays.asList("pdf", "pdfa"))); - add(new Format("oxps", Type.WORD, Arrays.asList("pdf", "pdfa"))); - add(new Format("xml", Type.WORD, Arrays.asList("docm", "docx", "docxf", "dotx", "dotm", "epub", "fb2", "html", "odt", "ott", "pdf", "pdfa", "rtf", "txt"))); - - add(new Format("csv", Type.CELL, new ArrayList())); - add(new Format("fods", Type.CELL, Arrays.asList("csv", "ods", "ots", "pdf", "pdfa", "xlsx", "xltx", "xlsm", "xltm"))); - add(new Format("ods", Type.CELL, Arrays.asList("csv", "ots", "pdf", "pdfa", "xlsx", "xltx", "xlsm", "xltm"))); - add(new Format("ots", Type.CELL, Arrays.asList("csv", "ods", "pdf", "pdfa", "xlsx", "xltx", "xlsm", "xltm"))); - add(new Format("xls", Type.CELL, Arrays.asList("csv", "ods", "ots", "pdf", "pdfa", "xlsx", "xltx", "xlsm", "xltm"))); - add(new Format("xlsm", Type.CELL, Arrays.asList("csv", "ods", "ots", "pdf", "pdfa", "xlsx", "xltx", "xltm"))); - add(new Format("xlsx", Type.CELL, true, Arrays.asList("csv", "ods", "ots", "pdf", "pdfa", "xltx", "xlsm", "xltm"))); - add(new Format("xlt", Type.CELL, Arrays.asList("csv", "ods", "ots", "pdf", "pdfa", "xlsx", "xltx", "xlsm", "xltm"))); - add(new Format("xltm", Type.CELL, Arrays.asList("csv", "ods", "ots", "pdf", "pdfa", "xlsx", "xltx", "xlsm"))); - add(new Format("xltx", Type.CELL, Arrays.asList("csv", "ods", "ots", "pdf", "pdfa", "xlsx", "xlsm", "xltm"))); - - add(new Format("fodp", Type.SLIDE, Arrays.asList("odp", "otp", "pdf", "pdfa", "potx", "pptx", "pptm", "potm"))); - add(new Format("odp", Type.SLIDE, Arrays.asList("otp", "pdf", "pdfa", "potx", "pptx", "pptm", "potm"))); - add(new Format("otp", Type.SLIDE, Arrays.asList("odp", "pdf", "pdfa", "potx", "pptx", "pptm", "potm"))); - add(new Format("pot", Type.SLIDE, Arrays.asList("odp", "otp", "pdf", "pdfa", "potx", "pptx", "pptm", "potm"))); - add(new Format("potm", Type.SLIDE, Arrays.asList("odp", "otp", "pdf", "pdfa", "potx", "pptx", "pptm"))); - add(new Format("potx", Type.SLIDE, Arrays.asList("odp", "otp", "pdf", "pdfa", "pptx", "pptm", "potm"))); - add(new Format("pps", Type.SLIDE, Arrays.asList("odp", "otp", "pdf", "pdfa", "potx", "pptx", "pptm", "potm"))); - add(new Format("ppsm", Type.SLIDE, Arrays.asList("odp", "otp", "pdf", "pdfa", "potx", "pptx", "pptm", "potm"))); - add(new Format("ppsx", Type.SLIDE, Arrays.asList("odp", "otp", "pdf", "pdfa", "potx", "pptx", "pptm", "potm"))); - add(new Format("ppt", Type.SLIDE, Arrays.asList("odp", "otp", "pdf", "pdfa", "potx", "pptx", "pptm", "potm"))); - add(new Format("pptm", Type.SLIDE, Arrays.asList("odp", "otp", "pdf", "pdfa", "potx", "pptx", "potm"))); - add(new Format("pptx", Type.SLIDE, true, Arrays.asList( "odp", "otp", "pdf", "pdfa", "potx", "pptm", "potm"))); - }}; - - public static List getSupportedFormats() { - return formats; - } - - public static JSONArray getSupportedFormatsAsJson() throws JSONException { - JSONArray array = new JSONArray(); - for (Format format : formats) { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("name", format.name); - jsonObject.put("type", format.type); - jsonObject.put("edit", format.edit); - jsonObject.put("convertTo", new JSONArray(format.convertTo)); - array.put(jsonObject); - } - return array; - } -} diff --git a/repo/src/main/java/com/parashift/onlyoffice/constants/Type.java b/repo/src/main/java/com/parashift/onlyoffice/constants/Type.java deleted file mode 100644 index ff3edb1c..00000000 --- a/repo/src/main/java/com/parashift/onlyoffice/constants/Type.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.parashift.onlyoffice.constants; - -/* - Copyright (c) Ascensio System SIA 2023. All rights reserved. - http://www.onlyoffice.com -*/ - -public enum Type { - WORD, - CELL, - SLIDE, - FORM -} diff --git a/repo/src/main/java/com/parashift/onlyoffice/scripts/CallBack.java b/repo/src/main/java/com/parashift/onlyoffice/scripts/CallBack.java index 1dd0ea2c..9cdb6ef2 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/scripts/CallBack.java +++ b/repo/src/main/java/com/parashift/onlyoffice/scripts/CallBack.java @@ -1,18 +1,17 @@ package com.parashift.onlyoffice.scripts; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.onlyoffice.manager.settings.SettingsManager; +import com.onlyoffice.model.documenteditor.Callback; +import com.onlyoffice.model.documenteditor.callback.Action; +import com.onlyoffice.service.documenteditor.callback.CallbackService; import com.parashift.onlyoffice.util.*; -import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.tenant.TenantContextHolder; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.repo.version.VersionModel; import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.repository.*; -import org.alfresco.service.cmr.version.VersionType; import org.alfresco.service.transaction.TransactionService; -import org.apache.http.HttpEntity; -import org.json.JSONArray; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -23,9 +22,7 @@ import org.springframework.stereotype.Component; import java.io.IOException; -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; +import java.util.List; /** * Created by cetra on 20/10/15. @@ -41,38 +38,19 @@ public class CallBack extends AbstractWebScript { @Qualifier("checkOutCheckInService") CheckOutCheckInService cociService; - @Autowired - ContentService contentService; - - @Autowired - ConfigManager configManager; - - @Autowired - JwtManager jwtManager; - @Autowired NodeService nodeService; - @Autowired - MimetypeService mimetypeService; - - @Autowired - ConvertManager converterService; - @Autowired TransactionService transactionService; @Autowired - HistoryManager historyManager; + SettingsManager settingsManager; @Autowired - Util util; + CallbackService callbackService; - @Autowired - UrlManager urlManager; - - @Autowired - RequestManager requestManager; + ObjectMapper objectMapper = new ObjectMapper(); private Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -84,53 +62,24 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws logger.debug("Received JSON Callback"); try { - JSONObject callBackJSon = new JSONObject(request.getContent().getContent()); - logger.debug(callBackJSon.toString(3)); + Callback callback = objectMapper.readValue(request.getContent().getContent(), Callback.class); + String authorizationHeader = request.getHeader(settingsManager.getSecurityHeader()); - if (jwtManager.jwtEnabled()) { - String token = callBackJSon.optString("token"); - String payload = null; - Boolean inBody = true; - - if (token == null || token == "") { - String jwth = jwtManager.getJwtHeader(); - String header = request.getHeader(jwth); - token = (header != null && header.startsWith("Bearer ")) ? header.substring(7) : header; - inBody = false; - } - - if (token == null || token == "") { - throw new SecurityException("Expected JWT"); - } - - try { - payload = jwtManager.verify(token); - } catch (Exception e) { - throw new SecurityException("JWT verification failed"); - } - - JSONObject bodyFromToken = new JSONObject(payload); - - if (inBody) { - callBackJSon = bodyFromToken; - } else { - callBackJSon = bodyFromToken.getJSONObject("payload"); - } - } + callback = callbackService.verifyCallback(callback, authorizationHeader); String username = null; - if (callBackJSon.has("users")) { - JSONArray array = callBackJSon.getJSONArray("users"); - if (array.length() > 0) { - username = (String) array.get(0); + if (callback.getUsers() != null) { + List users = callback.getUsers(); + if (users.size() > 0) { + username = users.get(0); } } - if (username == null && callBackJSon.has("actions")) { - JSONArray array = callBackJSon.getJSONArray("actions"); - if (array.length() > 0) { - username = ((JSONObject) array.get(0)).getString("userid"); + if (username == null && callback.getActions() != null) { + List actions = callback.getActions(); + if (actions.size() > 0) { + username = actions.get(0).getUserid(); } } @@ -155,7 +104,7 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws Boolean reqNew = transactionService.isReadOnly(); transactionService.getRetryingTransactionHelper() - .doInTransaction(new ProccessRequestCallback(callBackJSon, nodeRef), reqNew, reqNew); + .doInTransaction(new ProccessRequestCallback(callback, nodeRef), reqNew, reqNew); AuthenticationUtil.clearCurrentSecurityContext(); } catch (SecurityException ex) { @@ -177,136 +126,19 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws } private class ProccessRequestCallback implements RetryingTransactionCallback { - - private JSONObject callBackJSon; + private Callback callback; private NodeRef nodeRef; - private Boolean forcesave; - - public ProccessRequestCallback(JSONObject json, NodeRef node) { - callBackJSon = json; - nodeRef = node; - forcesave = configManager.getAsBoolean("forcesave", "false"); + public ProccessRequestCallback(Callback callback, NodeRef node) { + this.callback = callback; + this.nodeRef = node; } @Override public Object execute() throws Throwable { - NodeRef wc = cociService.getWorkingCopy(nodeRef); - Map versionProperties = new HashMap(); - - //Status codes from here: https://api.onlyoffice.com/editors/editor - switch(callBackJSon.getInt("status")) { - case 0: - logger.error("ONLYOFFICE has reported that no doc with the specified key can be found"); - AuthenticationUtil.setRunAsUser(AuthenticationUtil.getSystemUserName()); - cociService.cancelCheckout(wc); - break; - case 1: - logger.debug("User has entered/exited ONLYOFFICE"); - break; - case 2: - logger.debug("Document Updated, changing content"); - updateNode(wc, callBackJSon.getString("url"), callBackJSon.getString("filetype")); - - logger.info("removing prop"); - nodeService.removeProperty(wc, Util.EditingHashAspect); - nodeService.removeProperty(wc, Util.EditingKeyAspect); - - versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR); - cociService.checkin(wc, versionProperties, null); - - if (callBackJSon.has("history")) { - try { - historyManager.saveHistory(nodeRef, callBackJSon.getJSONObject("history"), callBackJSon.getString("changesurl")); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - } - - util.postActivity(nodeRef, false); - - logger.debug("Save complete"); - break; - case 3: - logger.error("ONLYOFFICE has reported that saving the document has failed"); - AuthenticationUtil.setRunAsUser(AuthenticationUtil.getSystemUserName()); - cociService.cancelCheckout(wc); - break; - case 4: - logger.debug("No document updates, unlocking node"); - AuthenticationUtil.setRunAsUser(AuthenticationUtil.getSystemUserName()); - cociService.cancelCheckout(wc); - break; - case 6: - if (!forcesave) { - logger.debug("Forcesave is disabled, ignoring forcesave request"); - return null; - } - - logger.debug("Forcesave request (type: " + callBackJSon.getInt("forcesavetype") + ")"); - updateNode(wc, callBackJSon.getString("url"), callBackJSon.getString("filetype")); - - String hash = (String) nodeService.getProperty(wc, Util.EditingHashAspect); - String key = (String) nodeService.getProperty(wc, Util.EditingKeyAspect); - - nodeService.removeProperty(wc, Util.EditingHashAspect); - nodeService.removeProperty(wc, Util.EditingKeyAspect); - - versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR); - cociService.checkin(wc, versionProperties, null, true); - - nodeService.setProperty(wc, Util.EditingHashAspect, hash); - nodeService.setProperty(wc, Util.EditingKeyAspect, key); - - if (callBackJSon.has("history")) { - try { - historyManager.saveHistory(nodeRef, callBackJSon.getJSONObject("history"), callBackJSon.getString("changesurl")); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - } - - util.postActivity(nodeRef, false); - - logger.debug("Forcesave complete"); - break; - } + callbackService.processCallback(callback, nodeRef.toString()); return null; } } - - private void updateNode(final NodeRef nodeRef, String url, String fileType) throws Exception { - logger.debug("Retrieving URL:" + url); - - final String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); - - AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() { - public Void doWork() { - NodeRef sourcesNodeRef = cociService.getCheckedOut(nodeRef); - nodeService.setProperty(sourcesNodeRef, ContentModel.PROP_LOCK_OWNER, currentUser); - nodeService.setProperty(nodeRef, ContentModel.PROP_WORKING_COPY_OWNER, currentUser); - return null; - } - }, AuthenticationUtil.getSystemUserName()); - - ContentData contentData = (ContentData) nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT); - String mimeType = contentData.getMimetype(); - - if (converterService.shouldConvertBack(mimeType)) { - try { - logger.debug("Should convert back"); - url = converterService.convert(util.getKey(nodeRef), fileType, mimetypeService.getExtension(mimeType), url, null); - } catch (Exception e) { - throw new Exception("Error while converting document back to original format: " + e.getMessage(), e); - } - } - - requestManager.executeRequestToDocumentServer(url, new RequestManager.Callback() { - public Void doWork(HttpEntity httpEntity) throws IOException { - contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true).putContent(httpEntity.getContent()); - return null; - } - }); - } } diff --git a/repo/src/main/java/com/parashift/onlyoffice/scripts/Config.java b/repo/src/main/java/com/parashift/onlyoffice/scripts/Config.java index 6a2034e0..abcf173c 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/scripts/Config.java +++ b/repo/src/main/java/com/parashift/onlyoffice/scripts/Config.java @@ -1,6 +1,8 @@ package com.parashift.onlyoffice.scripts; -import com.parashift.onlyoffice.util.ConfigManager; +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.settings.SettingsManager; +import com.onlyoffice.model.settings.SettingsConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.extensions.webscripts.DeclarativeWebScript; import org.springframework.extensions.webscripts.WebScriptRequest; @@ -8,6 +10,8 @@ import org.springframework.extensions.webscripts.Cache; import org.springframework.stereotype.Component; +import java.beans.IntrospectionException; +import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; @@ -17,44 +21,56 @@ */ @Component(value = "webscript.onlyoffice.onlyoffice-config.get") public class Config extends DeclarativeWebScript { + @Autowired + SettingsManager settingsManager; @Autowired - ConfigManager configManager; + DocumentManager documentManager; @Override protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) { Map model = new HashMap(); - model.put("docurl", configManager.getOrDefault("url", "http://127.0.0.1/")); - model.put("docinnerurl", configManager.getOrDefault("innerurl", "")); - model.put("alfurl", configManager.getOrDefault("alfurl", "")); - - model.put("cert", getBoolAsAttribute("cert", "false")); - model.put("forcesave", getBoolAsAttribute("forcesave", "false")); - model.put("webpreview", getBoolAsAttribute("webpreview", "false")); - model.put("convertOriginal", getBoolAsAttribute("convertOriginal", "false")); - - model.put("chat", getBoolAsAttribute("chat", "true")); - model.put("help", getBoolAsAttribute("help", "true")); - model.put("compactHeader", getBoolAsAttribute("compactHeader", "false")); - model.put("toolbarNoTabs", getBoolAsAttribute("toolbarNoTabs", "false")); - model.put("feedback", getBoolAsAttribute("feedback", "false")); - model.put("reviewDisplay", configManager.getOrDefault("reviewDisplay", "original")); - - model.put("jwtsecret", configManager.getOrDefault("jwtsecret", "")); - model.put("demo", getBoolAsAttribute("demo", "false")); - model.put("demoAvailable", configManager.demoAvailable(true)); - - model.put("formatODT", getBoolAsAttribute("formatODT", "false")); - model.put("formatODS", getBoolAsAttribute("formatODS", "false")); - model.put("formatODP", getBoolAsAttribute("formatODP", "false")); - model.put("formatCSV", getBoolAsAttribute("formatCSV", "true")); - model.put("formatTXT", getBoolAsAttribute("formatTXT", "true")); - model.put("formatRTF", getBoolAsAttribute("formatRTF", "false")); - return model; - } - private String getBoolAsAttribute(String key, Object defaultValue) { - return configManager.getAsBoolean(key, defaultValue) ? "checked=\"\"" : ""; + model.put("demoAvailable", settingsManager.isDemoAvailable()); + model.put("webpreview", settingsManager.getSettingBoolean("webpreview", false)); + model.put("convertOriginal", settingsManager.getSettingBoolean("convertOriginal", false)); + + Map lossyEditable = documentManager.getLossyEditableMap(); + + if (settingsManager.getSetting(SettingsConstants.LOSSY_EDIT) == null + || settingsManager.getSetting(SettingsConstants.LOSSY_EDIT).isEmpty()) { + lossyEditable.put("txt", true); + lossyEditable.put("csv", true); + } + + model.put("lossyEditable", lossyEditable); + + try { + Map settings = settingsManager.getSettings(); + + if (settings.get("customization.review.reviewDisplay") == null || settings.get("customization.review.reviewDisplay").isEmpty()) { + settings.put("customization.review.reviewDisplay", "ORIGINAL"); + } + + if (settings.get("customization.help") == null || settings.get("customization.help").isEmpty()) { + settings.put("customization.help", "true"); + } + + if (settings.get("customization.chat") == null || settings.get("customization.chat").isEmpty()) { + settings.put("customization.chat", "true"); + } + + model.put("settings", settings); + + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + + return model; } } diff --git a/repo/src/main/java/com/parashift/onlyoffice/scripts/ConfigCallback.java b/repo/src/main/java/com/parashift/onlyoffice/scripts/ConfigCallback.java index 3a92f5ba..392a9784 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/scripts/ConfigCallback.java +++ b/repo/src/main/java/com/parashift/onlyoffice/scripts/ConfigCallback.java @@ -1,24 +1,24 @@ package com.parashift.onlyoffice.scripts; -import com.parashift.onlyoffice.util.*; -import org.alfresco.repo.i18n.MessageService; -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpEntity; -import org.json.JSONException; -import org.json.JSONObject; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.onlyoffice.manager.settings.SettingsManager; +import com.onlyoffice.model.settings.Settings; +import com.onlyoffice.model.settings.security.Security; +import com.onlyoffice.model.settings.validation.ValidationResult; +import com.parashift.onlyoffice.sdk.service.SettingsValidationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.extensions.webscripts.AbstractWebScript; import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptResponse; import org.springframework.stereotype.Component; +import java.beans.IntrospectionException; import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Properties; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; /* Copyright (c) Ascensio System SIA 2023. All rights reserved. @@ -26,25 +26,13 @@ */ @Component(value = "webscript.onlyoffice.onlyoffice-config.post") public class ConfigCallback extends AbstractWebScript { - - @Autowired - ConfigManager configManager; - @Autowired - @Qualifier("global-properties") - Properties globalProp; + SettingsManager settingsManager; @Autowired - ConvertManager converter; + SettingsValidationService settingsValidationService; - @Autowired - UrlManager urlManager; - - @Autowired - MessageService mesService; - - @Autowired - RequestManager requestManager; + ObjectMapper objectMapper = new ObjectMapper(); private Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -52,159 +40,47 @@ public class ConfigCallback extends AbstractWebScript { public void execute(WebScriptRequest request, WebScriptResponse response) throws IOException { logger.debug("Received new configuration"); - try { - JSONObject data = new JSONObject(request.getContent().getContent()); - - logger.debug(data.toString(3)); - - String docUrl = AppendSlash(data.getString("url").trim()); - String docInnerUrl = AppendSlash(data.getString("innerurl").trim()); - String alfUrl = AppendSlash(data.getString("alfurl").trim()); - String jwtSecret = data.getString("jwtsecret").trim(); - - configManager.selectDemo(data.getBoolean("demo")); - - if (configManager.demoActive()) { - docUrl = configManager.getDemo("url"); - } else { - configManager.set("url", docUrl); - configManager.set("innerurl", docInnerUrl); - configManager.set("jwtsecret", jwtSecret); - } - - configManager.set("alfurl", alfUrl); - configManager.set("cert", data.getString("cert")); - configManager.set("forcesave", data.getString("forcesave")); - configManager.set("webpreview", data.getString("webpreview")); - configManager.set("convertOriginal", data.getString("convertOriginal")); - - configManager.set("chat", data.getString("chat")); - configManager.set("help", data.getString("help")); - configManager.set("compactHeader", data.getString("compactHeader")); - configManager.set("toolbarNoTabs", data.getString("toolbarNoTabs")); - configManager.set("feedback", data.getString("feedback")); - configManager.set("reviewDisplay", data.getString("reviewDisplay")); - - JSONObject formats = (JSONObject) data.get("formats"); - configManager.set("formatODT", formats.getString("odt")); - configManager.set("formatODS", formats.getString("ods")); - configManager.set("formatODP", formats.getString("odp")); - configManager.set("formatCSV", formats.getString("csv")); - configManager.set("formatTXT", formats.getString("txt")); - configManager.set("formatRTF", formats.getString("rtf")); - - logger.debug("Checking docserv url"); - if (!CheckDocServUrl()) { - response.getWriter().write("{\"success\": false, \"message\": \"docservunreachable\"}"); - return; - } - - try { - logger.debug("Checking docserv commandservice"); - if (!CheckDocServCommandService()) { - response.getWriter().write("{\"success\": false, \"message\": \"docservcommand\"}"); - return; - } - - logger.debug("Checking docserv convert"); - if (!CheckDocServConvert()) { - response.getWriter().write("{\"success\": false, \"message\": \"docservconvert\"}"); - return; - } - } catch (SecurityException e) { - response.getWriter().write("{\"success\": false, \"message\": \"jwterror\"}"); - return; - } - - response.getWriter().write("{\"success\": true}"); - } catch (JSONException ex) { - String msg = "Unable to deserialize JSON: " + ex.getMessage(); - logger.debug(msg); - response.getWriter().write("{\"success\": false, \"message\": \"jsonparse\"}"); - } - } - private String AppendSlash(String url) { - if (!url.isEmpty() && !url.endsWith("/")) { - url = url + "/"; - } - return url; - } - - private Boolean CheckDocServUrl() { - String url = urlManager.getEditorInnerUrl() + "healthcheck"; + Settings settings = objectMapper.readValue(request.getContent().getContent(), Settings.class); + Map extraSettings = settings.getExtra(); - logger.debug("Sending GET to Document Server healthcheck"); + settingsManager.setSetting("convertOriginal", (String) extraSettings.get("convertOriginal")); + settingsManager.setSetting("webpreview", (String) extraSettings.get("webpreview")); - try { - return requestManager.executeRequestToDocumentServer(url, new RequestManager.Callback() { - public Boolean doWork(HttpEntity httpEntity) throws IOException { - String content = IOUtils.toString(httpEntity.getContent(), "utf-8").trim(); - return content.equalsIgnoreCase("true"); - } - }); - } catch (Exception e) { - logger.error(e.getMessage(), e); - return false; + if (settings.getDemo() != null && settings.getDemo()) { + settingsManager.enableDemo(); + } else { + settingsManager.disableDemo(); } - } - private Boolean CheckDocServCommandService() throws SecurityException, JSONException { - JSONObject body = new JSONObject(); - body.put("c", "version"); + if (settingsManager.isDemoActive()) { + Security security = settings.getSecurity(); + security.setKey(null); + security.setHeader(null); - logger.debug("Sending POST to Command Service: " + body.toString()); - try { - return requestManager.executeRequestToCommandService(body, new RequestManager.Callback() { - public Boolean doWork(HttpEntity httpEntity) throws IOException, JSONException { - String content = IOUtils.toString(httpEntity.getContent(), "utf-8"); - - logger.debug("/CommandService content: " + content); - - JSONObject callBackJson = new JSONObject(content); - - if (callBackJson.isNull("error")) { - return false; - } - - Integer errorCode = callBackJson.getInt("error"); - - if (errorCode == 6) { - throw new SecurityException(); - } else if (errorCode != 0) { - return false; - } else { - return true; - } - } - }); - } catch (SecurityException e) { - throw e; - } catch (Exception e) { - logger.error(e.getMessage(), e); - return false; + settings.setUrl(null); + settings.setInnerUrl(null); + settings.setSecurity(security); } - } - - private Boolean CheckDocServConvert() throws SecurityException { - String key = new SimpleDateFormat("MMddyyyyHHmmss").format(new Date()); try { - String newFileUrl = converter.convert(key, "txt", "docx", urlManager.getTestConversionUrl(), mesService.getLocale().toLanguageTag()); - logger.debug("/ConvertService url: " + newFileUrl); - - if (newFileUrl == null || newFileUrl.isEmpty()) { - return false; - } - } catch (Exception e) { - if (e instanceof SecurityException) { - throw (SecurityException)e; - } - logger.debug("/ConvertService error: " + e.getMessage()); - return false; + settingsManager.setSettings(settings); + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); } - return true; + Map validationResults = settingsValidationService.validateSettings(); + + Map responseMap = new HashMap<>(); + responseMap.put("validationResults", validationResults); + + response.setContentType("application/json; charset=utf-8"); + response.setContentEncoding("UTF-8"); + response.getWriter().write(objectMapper.writeValueAsString(responseMap)); } } diff --git a/repo/src/main/java/com/parashift/onlyoffice/scripts/Download.java b/repo/src/main/java/com/parashift/onlyoffice/scripts/Download.java index 7320acbe..cec718e7 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/scripts/Download.java +++ b/repo/src/main/java/com/parashift/onlyoffice/scripts/Download.java @@ -1,9 +1,10 @@ package com.parashift.onlyoffice.scripts; +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.security.JwtManager; +import com.onlyoffice.manager.settings.SettingsManager; +import com.parashift.onlyoffice.sdk.manager.url.UrlManager; import com.parashift.onlyoffice.util.HistoryManager; -import com.parashift.onlyoffice.util.JwtManager; -import com.parashift.onlyoffice.util.UrlManager; -import com.parashift.onlyoffice.util.Util; import org.alfresco.model.ContentModel; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.service.cmr.repository.*; @@ -40,10 +41,13 @@ public class Download extends AbstractWebScript { HistoryManager historyManager; @Autowired - Util util; + UrlManager urlManager; @Autowired - UrlManager urlManager; + SettingsManager settingsManager; + + @Autowired + DocumentManager documentManager; @Override public void execute(WebScriptRequest request, WebScriptResponse response) throws IOException { @@ -58,10 +62,12 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not find required 'nodeRef' parameter!"); } - if (jwtManager.jwtEnabled() ) { - String jwth = jwtManager.getJwtHeader(); + if (settingsManager.isSecurityEnabled() ) { + String jwth = settingsManager.getSecurityHeader(); String header = request.getHeader(jwth); - String token = (header != null && header.startsWith("Bearer ")) ? header.substring(7) : header; + String authorizationPrefix = settingsManager.getSecurityPrefix(); + String token = (header != null && header.startsWith(authorizationPrefix)) + ? header.substring(authorizationPrefix.length()) : header; if (token == null || token == "") { throw new SecurityException("Expected JWT"); @@ -90,7 +96,7 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws throw new WebScriptException(Status.STATUS_NOT_FOUND, "Not found diff.zip for version: " + nodeRefString); } - String editorUrl = urlManager.getEditorUrl(); + String editorUrl = urlManager.getDocumentServerUrl(); if (editorUrl.endsWith("/")) { editorUrl = editorUrl.substring(0, editorUrl.length() - 1); } @@ -101,8 +107,8 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws throw new WebScriptException(404, "Unknown parameter 'type': '" + type + "'!"); } - String title = util.getTitle(nodeRef); - String fileType = util.getExtension(nodeRef); + String title = documentManager.getDocumentName(nodeRef.toString()); + String fileType = documentManager.getExtension(title); ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT); response.setHeader("Content-Length", String.valueOf(reader.getSize())); diff --git a/repo/src/main/java/com/parashift/onlyoffice/scripts/DownloadAs.java b/repo/src/main/java/com/parashift/onlyoffice/scripts/DownloadAs.java index a3cf9440..bb882f8c 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/scripts/DownloadAs.java +++ b/repo/src/main/java/com/parashift/onlyoffice/scripts/DownloadAs.java @@ -1,6 +1,10 @@ package com.parashift.onlyoffice.scripts; -import com.parashift.onlyoffice.util.*; +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.request.RequestManager; +import com.onlyoffice.model.convertservice.ConvertRequest; +import com.onlyoffice.model.convertservice.ConvertResponse; +import com.onlyoffice.service.convert.ConvertService; import org.alfresco.model.ContentModel; import org.alfresco.repo.download.DownloadModel; import org.alfresco.repo.download.DownloadStatusUpdateService; @@ -42,12 +46,6 @@ public class DownloadAs extends AbstractWebScript { private static final String ZIP_EXTENSION = ".zip"; private final static String CONTENT_DOWNLOAD_API_URL = "slingshot/node/content/{0}/{1}/{2}/{3}"; - @Autowired - ConvertManager converterService; - - @Autowired - Util util; - @Autowired PermissionService permissionService; @@ -70,10 +68,13 @@ public class DownloadAs extends AbstractWebScript { MessageService mesService; @Autowired - UrlManager urlManager; + RequestManager requestManager; @Autowired - RequestManager requestManager; + ConvertService convertService; + + @Autowired + DocumentManager documentManager; @Override public void execute(WebScriptRequest request, WebScriptResponse response) throws IOException { @@ -92,22 +93,37 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws throw new AccessDeniedException("Access denied. You do not have the appropriate permissions to perform this operation. NodeRef= " + node.toString()); } - String currentExt = util.getExtension(node); + String docTitle = documentManager.getDocumentName(node.toString()); + String currentExt = documentManager.getExtension(docTitle); if (currentExt.equals(outputType)) { - String docTitle = util.getTitle(node); - contentURL = getDownloadAPIUrl(node, docTitle); } else { - String downloadUrl = converterService.convert(util.getKey(node), currentExt, outputType, urlManager.getContentUrl(node), region); - final String docTitle = util.getTitleWithoutExtension(node) + "." + outputType; + ConvertRequest convertRequest = ConvertRequest.builder() + .outputtype(outputType) + .region(region) + .build(); - contentURL = requestManager.executeRequestToDocumentServer(downloadUrl, new RequestManager.Callback() { - public String doWork(HttpEntity httpEntity) throws IOException { - byte[] bytes = EntityUtils.toByteArray(httpEntity); + ConvertResponse convertResponse = convertService.processConvert(convertRequest, node.toString()); + + if (convertResponse.getError() != null && convertResponse.getError().equals(ConvertResponse.Error.TOKEN)) { + throw new SecurityException(); + } + + if (!convertResponse.getEndConvert() + || convertResponse.getFileUrl().isEmpty()) { + throw new Exception("'endConvert' is false or 'fileUrl' is empty"); + } + + String downloadUrl = convertResponse.getFileUrl(); + final String newTitle = documentManager.getBaseName(docTitle) + "." + outputType; + + contentURL = requestManager.executeGetRequest(downloadUrl, new RequestManager.Callback() { + public String doWork(Object response) throws IOException { + byte[] bytes = EntityUtils.toByteArray((HttpEntity) response); InputStream inputStream = new ByteArrayInputStream(bytes); - return createDownloadNode(docTitle, mimetypeService.getMimetype(outputType), inputStream, bytes.length, 1); + return createDownloadNode(newTitle, mimetypeService.getMimetype(outputType), inputStream, bytes.length, 1); } }); } @@ -132,24 +148,40 @@ public String doWork(HttpEntity httpEntity) throws IOException { throw new AccessDeniedException("Access denied. You do not have the appropriate permissions to perform this operation. NodeRef= " + node.toString()); } - String currentExt = util.getExtension(node); + String docTitle = documentManager.getDocumentName(node.toString()); + String currentExt = documentManager.getExtension(docTitle); if (currentExt.equals(outputType)) { - String docTitle = util.getTitle(node); ContentReader reader = contentService.getReader(node, ContentModel.PROP_CONTENT); try (InputStream inputStream = reader.getContentInputStream()) { out.putArchiveEntry(new ZipArchiveEntry(docTitle)); totalSize = totalSize + IOUtils.copyLarge(inputStream, out); } } else { - String downloadUrl = converterService.convert(util.getKey(node), currentExt, outputType, urlManager.getContentUrl(node), region); - String docTitle = util.getTitleWithoutExtension(node) + "." + outputType; + ConvertRequest convertRequest = ConvertRequest.builder() + .outputtype(outputType) + .region(region) + .build(); + + ConvertResponse convertResponse = convertService.processConvert(convertRequest, node.toString()); + + if (convertResponse.getError() != null && convertResponse.getError().equals(ConvertResponse.Error.TOKEN)) { + throw new SecurityException(); + } + + if (convertResponse.getEndConvert() == null || !convertResponse.getEndConvert() + || convertResponse.getFileUrl() == null || convertResponse.getFileUrl().isEmpty()) { + throw new Exception("'endConvert' is false or 'fileUrl' is empty"); + } + + String downloadUrl = convertResponse.getFileUrl(); + String newTitle = documentManager.getBaseName(docTitle) + "." + outputType; - out.putArchiveEntry(new ZipArchiveEntry(docTitle)); + out.putArchiveEntry(new ZipArchiveEntry(newTitle)); - totalSize += requestManager.executeRequestToDocumentServer(downloadUrl, new RequestManager.Callback() { - public Long doWork(HttpEntity httpEntity) throws IOException { - return IOUtils.copyLarge(httpEntity.getContent(), out); + totalSize += requestManager.executeGetRequest(downloadUrl, new RequestManager.Callback() { + public Long doWork(Object response) throws IOException { + return IOUtils.copyLarge(((HttpEntity)response).getContent(), out); } }); } diff --git a/repo/src/main/java/com/parashift/onlyoffice/scripts/EditorApi.java b/repo/src/main/java/com/parashift/onlyoffice/scripts/EditorApi.java index e0c8ace4..484f3a0e 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/scripts/EditorApi.java +++ b/repo/src/main/java/com/parashift/onlyoffice/scripts/EditorApi.java @@ -1,5 +1,14 @@ package com.parashift.onlyoffice.scripts; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.request.RequestManager; +import com.onlyoffice.manager.security.JwtManager; +import com.onlyoffice.manager.settings.SettingsManager; +import com.onlyoffice.model.convertservice.ConvertRequest; +import com.onlyoffice.model.convertservice.ConvertResponse; +import com.onlyoffice.service.convert.ConvertService; +import com.parashift.onlyoffice.sdk.manager.url.UrlManager; import com.parashift.onlyoffice.util.*; import org.alfresco.error.AlfrescoRuntimeException; @@ -27,6 +36,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -58,9 +68,6 @@ public class EditorApi extends AbstractWebScript { @Autowired JwtManager jwtManager; - @Autowired - ConvertManager converterService; - @Autowired MessageService mesService; @@ -70,6 +77,16 @@ public class EditorApi extends AbstractWebScript { @Autowired RequestManager requestManager; + @Autowired + ConvertService convertService; + + @Autowired + SettingsManager settingsManager; + + @Autowired + DocumentManager documentManager; + + private final ObjectMapper objectMapper = new ObjectMapper(); private Logger logger = LoggerFactory.getLogger(this.getClass()); @Override @@ -98,22 +115,23 @@ private void insert(WebScriptRequest request, WebScriptResponse response) throws try { JSONObject requestData = new JSONObject(request.getContent().getContent()); JSONArray nodes = requestData.getJSONArray("nodes"); - List responseJson = new ArrayList<>(); + List> responseJson = new ArrayList<>(); for (int i = 0; i < nodes.length(); i++) { - JSONObject data = new JSONObject(); + Map data = new HashMap<>(); NodeRef node = new NodeRef(nodes.getString(i)); if (permissionService.hasPermission(node, PermissionService.READ) == AccessStatus.ALLOWED) { - String fileType = util.getExtension(node); + String fileName = documentManager.getDocumentName(node.toString()); + String fileType = documentManager.getExtension(fileName); if (requestData.has("command")) { data.put("c", requestData.get("command")); } data.put("fileType", fileType); - data.put("url", urlManager.getContentUrl(node)); - if (jwtManager.jwtEnabled()) { + data.put("url", urlManager.getFileUrl(node.toString())); + if (settingsManager.isSecurityEnabled()) { try { data.put("token", jwtManager.createToken(data)); } catch (Exception e) { @@ -126,7 +144,7 @@ private void insert(WebScriptRequest request, WebScriptResponse response) throws } response.setContentType("application/json"); - response.getWriter().write(responseJson.toString()); + response.getWriter().write(objectMapper.writeValueAsString(responseJson)); } catch (JSONException e) { throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not parse JSON from request", e); } @@ -152,14 +170,31 @@ private void docxToDocxf(WebScriptRequest request, WebScriptResponse response) t JSONObject data = new JSONObject(); if (permissionService.hasPermission(node, PermissionService.READ) == AccessStatus.ALLOWED) { - String fileType = util.getExtension(node); + String fileName = documentManager.getDocumentName(node.toString()); + String fileType = documentManager.getExtension(fileName); if (!mimetypeService.getMimetype(fileType).equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) { throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Selected file is not docx extension"); } try { - String downloadUrl = converterService.convert(util.getKey(node), fileType, "docxf", urlManager.getContentUrl(node), mesService.getLocale().toLanguageTag()); - String docTitle = util.getTitleWithoutExtension(node); + ConvertRequest convertRequest = ConvertRequest.builder() + .outputtype("docxf") + .region(mesService.getLocale().toLanguageTag()) + .build(); + + ConvertResponse convertResponse = convertService.processConvert(convertRequest, node.toString()); + + if (convertResponse.getError() != null && convertResponse.getError().equals(ConvertResponse.Error.TOKEN)) { + throw new SecurityException(); + } + + if (convertResponse.getEndConvert() == null || !convertResponse.getEndConvert() + || convertResponse.getFileUrl() == null || convertResponse.getFileUrl().isEmpty()) { + throw new Exception("'endConvert' is false or 'fileUrl' is empty"); + } + + String downloadUrl = convertResponse.getFileUrl(); + String docTitle = documentManager.getBaseName(fileName); String newNode = createNode(folderNode, docTitle, "docxf", downloadUrl); data.put("nodeRef", newNode); } catch (Exception e) { @@ -203,6 +238,7 @@ private void saveAs(WebScriptRequest request, WebScriptResponse response) throws private String createNode(NodeRef folderNode, String title, final String ext, String url) throws IOException { String fileName = util.getCorrectName(folderNode, title, ext); + url = urlManager.replaceToInnerDocumentServerUrl(url); final NodeRef nodeRef = nodeService.createNode( folderNode, @@ -212,11 +248,11 @@ private String createNode(NodeRef folderNode, String title, final String ext, St Collections. singletonMap(ContentModel.PROP_NAME, fileName)).getChildRef(); try { - requestManager.executeRequestToDocumentServer(url, new RequestManager.Callback() { - public Void doWork(HttpEntity httpEntity) throws IOException { + requestManager.executeGetRequest(url, new RequestManager.Callback() { + public Void doWork(Object response) throws IOException { ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); writer.setMimetype(mimetypeService.getMimetype(ext)); - writer.putContent(httpEntity.getContent()); + writer.putContent(((HttpEntity)response).getContent()); return null; } }); diff --git a/repo/src/main/java/com/parashift/onlyoffice/scripts/History.java b/repo/src/main/java/com/parashift/onlyoffice/scripts/History.java index 0db28d69..71fda38b 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/scripts/History.java +++ b/repo/src/main/java/com/parashift/onlyoffice/scripts/History.java @@ -1,8 +1,8 @@ package com.parashift.onlyoffice.scripts; import com.fasterxml.jackson.databind.ObjectMapper; +import com.onlyoffice.model.documenteditor.HistoryData; import com.parashift.onlyoffice.util.HistoryManager; -import com.parashift.onlyoffice.util.HistoryManager.HistoryData; import org.alfresco.service.cmr.repository.*; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.PermissionService; diff --git a/repo/src/main/java/com/parashift/onlyoffice/scripts/OnlyofficeSettings.java b/repo/src/main/java/com/parashift/onlyoffice/scripts/OnlyofficeSettings.java index 378d46ec..96199585 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/scripts/OnlyofficeSettings.java +++ b/repo/src/main/java/com/parashift/onlyoffice/scripts/OnlyofficeSettings.java @@ -1,7 +1,7 @@ package com.parashift.onlyoffice.scripts; -import com.parashift.onlyoffice.util.ConfigManager; -import com.parashift.onlyoffice.constants.Formats; +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.settings.SettingsManager; import org.json.JSONException; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; @@ -9,7 +9,6 @@ import org.springframework.stereotype.Component; import java.io.IOException; -import java.util.Set; /* Copyright (c) Ascensio System SIA 2023. All rights reserved. @@ -17,18 +16,19 @@ */ @Component(value = "webscript.onlyoffice.onlyoffice-settings.get") public class OnlyofficeSettings extends AbstractWebScript { + @Autowired + SettingsManager settingsManager; @Autowired - ConfigManager configManager; + DocumentManager documentManager; @Override public void execute(WebScriptRequest request, WebScriptResponse response) throws IOException { JSONObject responseJson = new JSONObject(); try { - Set editableFormats = configManager.getCustomizableEditableSet(); - responseJson.put("editableFormats", editableFormats); - responseJson.put("convertOriginal", configManager.getAsBoolean("convertOriginal", "false")); - responseJson.put("supportedFormats", Formats.getSupportedFormatsAsJson()); + responseJson.put("editableFormats", documentManager.getLossyEditableMap()); + responseJson.put("convertOriginal", settingsManager.getSettingBoolean("convertOriginal", false)); + responseJson.put("supportedFormats", documentManager.getFormats()); response.setContentType("application/json; charset=utf-8"); response.setContentEncoding("UTF-8"); diff --git a/repo/src/main/java/com/parashift/onlyoffice/scripts/Prepare.java b/repo/src/main/java/com/parashift/onlyoffice/scripts/Prepare.java index bd4250bd..952793fc 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/scripts/Prepare.java +++ b/repo/src/main/java/com/parashift/onlyoffice/scripts/Prepare.java @@ -1,15 +1,21 @@ package com.parashift.onlyoffice.scripts; -import com.parashift.onlyoffice.util.ConfigManager; -import com.parashift.onlyoffice.util.UrlManager; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.settings.SettingsManager; +import com.onlyoffice.model.documenteditor.Config; +import com.onlyoffice.model.documenteditor.config.document.DocumentType; +import com.onlyoffice.model.documenteditor.config.document.Type; +import com.onlyoffice.model.documenteditor.config.editorconfig.Mode; +import com.onlyoffice.service.documenteditor.config.ConfigService; +import com.parashift.onlyoffice.sdk.manager.url.UrlManager; import com.parashift.onlyoffice.util.Util; -import com.parashift.onlyoffice.util.UtilDocConfig; -import com.parashift.onlyoffice.constants.Type; import org.alfresco.model.ContentModel; import org.alfresco.repo.i18n.MessageService; -import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.repository.*; import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.OwnableService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -18,6 +24,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.extensions.webscripts.*; import org.springframework.stereotype.Component; @@ -40,6 +47,13 @@ public class Prepare extends AbstractWebScript { private Logger logger = LoggerFactory.getLogger(this.getClass()); + @Autowired + @Qualifier("checkOutCheckInService") + CheckOutCheckInService cociService; + + @Autowired + OwnableService ownableService; + @Autowired NodeService nodeService; @@ -52,9 +66,6 @@ public class Prepare extends AbstractWebScript { @Autowired MimetypeService mimetypeService; - @Autowired - ConfigManager configManager; - @Autowired PermissionService permissionService; @@ -65,7 +76,13 @@ public class Prepare extends AbstractWebScript { UrlManager urlManager; @Autowired - UtilDocConfig utilDocConfig; + ConfigService configService; + + @Autowired + DocumentManager documentManager; + + @Autowired + SettingsManager settingsManager; @Override public void execute(WebScriptRequest request, WebScriptResponse response) throws IOException { @@ -103,21 +120,8 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); writer.setMimetype(newFileMime); - String pathLocale = Util.PathLocale.get(mesService.getLocale().toLanguageTag()); - - if (pathLocale == null) { - pathLocale = Util.PathLocale.get(mesService.getLocale().getLanguage()); + InputStream in = documentManager.getNewBlankFile(ext, mesService.getLocale()); - if (pathLocale == null) pathLocale = Util.PathLocale.get("en"); - } - - InputStream in; - if (request.getParameter("templateNodeRef") != null) { - NodeRef templateNodeRef = new NodeRef(request.getParameter("templateNodeRef")); - in = contentService.getReader(templateNodeRef, ContentModel.PROP_CONTENT).getContentInputStream(); - } else { - in = getClass().getResourceAsStream("/newdocs/" + pathLocale + "/new." + ext); - } writer.putContent(in); util.ensureVersioningEnabled(nodeRef); util.postActivity(nodeRef, true); @@ -125,7 +129,6 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws responseJson.put("nodeRef", nodeRef); } else { NodeRef nodeRef = new NodeRef(request.getParameter("nodeRef")); - boolean isReadOnly = request.getParameter("readonly") != null; if (permissionService.hasPermission(nodeRef, PermissionService.READ) != AccessStatus.ALLOWED) { responseJson.put("error", "User have no read access"); @@ -134,12 +137,9 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws return; } - String docTitle = util.getTitle(nodeRef); - String docExt = util.getExtension(nodeRef); - String documentType = util.getDocType(docExt); - if (docExt.equals("docxf") || docExt.equals("oform")) { - documentType = Type.WORD.name().toLowerCase(); - } + String fileName = documentManager.getDocumentName(nodeRef.toString()); + String fileExtension = documentManager.getExtension(fileName); + DocumentType documentType = documentManager.getDocumentType(fileName); if (documentType == null) { responseJson.put("error", "File type is not supported"); @@ -151,25 +151,48 @@ public void execute(WebScriptRequest request, WebScriptResponse response) throws String previewParam = request.getParameter("preview"); Boolean preview = previewParam != null && previewParam.equals("true"); + com.onlyoffice.model.documenteditor.config.document.Type type = Type.DESKTOP; + Mode mode = Mode.EDIT; + responseJson.put("previewEnabled", false); + if (preview) { - if (((String)configManager.getOrDefault("webpreview", "")).equals("true")) { + if (settingsManager.getSettingBoolean("webpreview", false)) { + type = Type.EMBEDDED; + mode = Mode.VIEW; responseJson.put("previewEnabled", true); } else { - responseJson.put("previewEnabled", false); response.getWriter().write(responseJson.toString(3)); return; } } - String username = AuthenticationUtil.getFullyAuthenticatedUser(); + if (documentManager.isEditable(fileName) + && permissionService.hasPermission(nodeRef, PermissionService.WRITE) == AccessStatus.ALLOWED + && mode.equals(Mode.EDIT)) { + if (!cociService.isCheckedOut(nodeRef)) { + util.ensureVersioningEnabled(nodeRef); + NodeRef copyRef = cociService.checkout(nodeRef); + ownableService.setOwner(copyRef, ownableService.getOwner(nodeRef)); + nodeService.setProperty(copyRef, Util.EditingKeyAspect, documentManager.getDocumentKey(nodeRef.toString(), false)); + nodeService.setProperty(copyRef, Util.EditingHashAspect, util.generateHash()); + } + } + + Config config = configService.createConfig( + request.getParameter("nodeRef"), + mode, + type + ); + + config.getEditorConfig().setLang(mesService.getLocale().toLanguageTag()); + + ObjectMapper mapper = new ObjectMapper(); - JSONObject configJson = utilDocConfig.getConfigJson(nodeRef, null, username, documentType, docTitle, - docExt, preview, isReadOnly); - responseJson.put("editorConfig", configJson); - responseJson.put("onlyofficeUrl", urlManager.getEditorUrl()); - responseJson.put("mime", mimetypeService.getMimetype(docExt)); + responseJson.put("editorConfig", new JSONObject(mapper.writeValueAsString(config))); + responseJson.put("onlyofficeUrl", urlManager.getDocumentServerUrl() + "/"); + responseJson.put("mime", mimetypeService.getMimetype(fileExtension)); responseJson.put("folderNode", util.getParentNodeRef(nodeRef)); - responseJson.put("demo", configManager.demoActive()); + responseJson.put("demo", settingsManager.isDemoActive()); responseJson.put("historyInfoUrl", urlManager.getHistoryInfoUrl(nodeRef)); responseJson.put("historyDataUrl", urlManager.getHistoryDataUrl(nodeRef)); responseJson.put("favorite", urlManager.getFavoriteUrl(nodeRef)); diff --git a/repo/src/main/java/com/parashift/onlyoffice/scripts/PrepareQuickShare.java b/repo/src/main/java/com/parashift/onlyoffice/scripts/PrepareQuickShare.java index a70dc60a..1fc3025b 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/scripts/PrepareQuickShare.java +++ b/repo/src/main/java/com/parashift/onlyoffice/scripts/PrepareQuickShare.java @@ -1,16 +1,20 @@ package com.parashift.onlyoffice.scripts; -import com.parashift.onlyoffice.util.ConfigManager; -import com.parashift.onlyoffice.util.UrlManager; -import com.parashift.onlyoffice.util.Util; -import com.parashift.onlyoffice.util.UtilDocConfig; -import org.alfresco.model.ContentModel; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.settings.SettingsManager; + +import com.onlyoffice.model.documenteditor.Config; +import com.onlyoffice.model.documenteditor.config.document.DocumentType; +import com.onlyoffice.model.documenteditor.config.document.Type; +import com.onlyoffice.model.documenteditor.config.editorconfig.Mode; +import com.onlyoffice.service.documenteditor.config.ConfigService; +import com.parashift.onlyoffice.sdk.manager.url.UrlManager; import org.alfresco.model.QuickShareModel; import org.alfresco.repo.tenant.TenantUtil; import org.alfresco.service.cmr.quickshare.InvalidSharedIdException; import org.alfresco.service.cmr.quickshare.QuickShareService; import org.alfresco.service.cmr.repository.*; -import org.alfresco.service.namespace.QName; import org.alfresco.util.Pair; import org.json.JSONException; import org.json.JSONObject; @@ -21,8 +25,6 @@ import org.springframework.stereotype.Component; import java.io.IOException; -import java.io.Serializable; -import java.util.Map; /* Copyright (c) Ascensio System SIA 2023. All rights reserved. @@ -37,9 +39,6 @@ public class PrepareQuickShare extends AbstractWebScript { @Autowired NodeService nodeService; - @Autowired - ConfigManager configManager; - @Autowired MimetypeService mimetypeService; @@ -47,13 +46,16 @@ public class PrepareQuickShare extends AbstractWebScript { QuickShareService quickShareService; @Autowired - Util util; + UrlManager urlManager; @Autowired - UrlManager urlManager; + ConfigService configService; @Autowired - UtilDocConfig utilDocConfig; + DocumentManager documentManager; + + @Autowired + SettingsManager settingsManager; @Override public void execute(final WebScriptRequest request, final WebScriptResponse response) throws IOException { @@ -77,9 +79,9 @@ public Void doWork() throws Exception { try { JSONObject responseJson = new JSONObject(); - String docTitle = util.getTitle(nodeRef); - String docExt = util.getExtension(nodeRef); - String documentType = util.getDocType(docExt); + String fileName = documentManager.getDocumentName(nodeRef.toString()); + String fileExtension = documentManager.getExtension(fileName); + DocumentType documentType = documentManager.getDocumentType(fileName); if (documentType == null) { responseJson.put("error", "File type is not supported"); @@ -88,7 +90,7 @@ public Void doWork() throws Exception { return null; } - if (((String)configManager.getOrDefault("webpreview", "")).equals("true")) { + if (settingsManager.getSettingBoolean("webpreview", false)) { responseJson.put("previewEnabled", true); } else { responseJson.put("previewEnabled", false); @@ -96,12 +98,19 @@ public Void doWork() throws Exception { return null; } - JSONObject configJson = utilDocConfig.getConfigJson(nodeRef, sharedId, null, documentType, - docTitle, docExt, true, true); + Config config = configService.createConfig(nodeRef.toString(), Mode.VIEW, Type.EMBEDDED); + + config.getEditorConfig().getEmbedded().setSaveUrl( + urlManager.getEmbeddedSaveUrl(nodeRef.toString(), sharedId) + ); + + config.getEditorConfig().getCustomization().setGoback(null); + + ObjectMapper mapper = new ObjectMapper(); - responseJson.put("editorConfig", configJson); - responseJson.put("onlyofficeUrl", urlManager.getEditorUrl()); - responseJson.put("mime", mimetypeService.getMimetype(docExt)); + responseJson.put("editorConfig", new JSONObject(mapper.writeValueAsString(config))); + responseJson.put("onlyofficeUrl", urlManager.getDocumentServerUrl() + "/"); + responseJson.put("mime", mimetypeService.getMimetype(fileExtension)); logger.debug("Sending JSON prepare object"); logger.debug(responseJson.toString(3)); diff --git a/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/document/DocumentManagerImpl.java b/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/document/DocumentManagerImpl.java new file mode 100644 index 00000000..8d4dbf69 --- /dev/null +++ b/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/document/DocumentManagerImpl.java @@ -0,0 +1,68 @@ +package com.parashift.onlyoffice.sdk.manager.document; + +import com.onlyoffice.manager.document.DefaultDocumentManager; +import com.onlyoffice.manager.settings.SettingsManager; +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.QName; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import java.io.Serializable; +import java.util.Map; + +/* + Copyright (c) Ascensio System SIA 2023. All rights reserved. + http://www.onlyoffice.com +*/ + +public class DocumentManagerImpl extends DefaultDocumentManager { + public static final QName EditingKeyAspect = QName.createQName("onlyoffice:editing-key"); + public static final QName EditingHashAspect = QName.createQName("onlyoffice:editing-hash"); + + @Autowired + @Qualifier("checkOutCheckInService") + CheckOutCheckInService cociService; + + @Autowired + NodeService nodeService; + + public DocumentManagerImpl(SettingsManager settingsManager) { + super(settingsManager); + } + + @Override + public String getDocumentKey(String fileId, boolean embedded) { + NodeRef nodeRef = new NodeRef(fileId); + + String key = null; + if (cociService.isCheckedOut(nodeRef)) { + key = (String) nodeService.getProperty(cociService.getWorkingCopy(nodeRef), EditingKeyAspect); + } + + if (key == null) { + Map properties = nodeService.getProperties(nodeRef); + String version = (String) properties.get(ContentModel.PROP_VERSION_LABEL); + + if (version == null || version.isEmpty()) { + key = nodeRef.getId() + "_1.0"; + } else { + key = nodeRef.getId() + "_" + version; + } + + key = embedded ? key + "_embedded" : key; + } + + return key; + } + + @Override + public String getDocumentName(String fileId) { + NodeRef nodeRef = new NodeRef(fileId); + + return (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); + } +} diff --git a/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/settings/SettingsManagerImpl.java b/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/settings/SettingsManagerImpl.java new file mode 100644 index 00000000..6ba44397 --- /dev/null +++ b/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/settings/SettingsManagerImpl.java @@ -0,0 +1,27 @@ +package com.parashift.onlyoffice.sdk.manager.settings; + +import com.onlyoffice.manager.settings.DefaultSettingsManager; +import org.alfresco.service.cmr.attributes.AttributeService; +import org.springframework.beans.factory.annotation.Autowired; + +/* + Copyright (c) Ascensio System SIA 2023. All rights reserved. + http://www.onlyoffice.com +*/ + +public class SettingsManagerImpl extends DefaultSettingsManager { + private static final String SETTINGS_PREFIX = "onlyoffice."; + + @Autowired + AttributeService attributeService; + + @Override + public String getSetting(String name) { + return (String) attributeService.getAttribute(SETTINGS_PREFIX + name); + } + + @Override + public void setSetting(String name, String value) { + attributeService.setAttribute(value, SETTINGS_PREFIX + name); + } +} diff --git a/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/url/UrlManager.java b/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/url/UrlManager.java new file mode 100644 index 00000000..8de9e3df --- /dev/null +++ b/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/url/UrlManager.java @@ -0,0 +1,18 @@ +package com.parashift.onlyoffice.sdk.manager.url; + +import org.alfresco.service.cmr.repository.NodeRef; + +/* + Copyright (c) Ascensio System SIA 2023. All rights reserved. + http://www.onlyoffice.com +*/ + +public interface UrlManager extends com.onlyoffice.manager.url.UrlManager { + String getHistoryDiffUrl(NodeRef nodeRef); + String getShareUrl(); + String getEmbeddedSaveUrl(String fileId, String sharedId); + String getEmbeddedSaveUrl(String fileId); + String getFavoriteUrl(NodeRef nodeRef); + String getHistoryInfoUrl(NodeRef nodeRef); + String getHistoryDataUrl(NodeRef nodeRef); +} diff --git a/repo/src/main/java/com/parashift/onlyoffice/util/UrlManager.java b/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/url/UrlManagerImpl.java similarity index 50% rename from repo/src/main/java/com/parashift/onlyoffice/util/UrlManager.java rename to repo/src/main/java/com/parashift/onlyoffice/sdk/manager/url/UrlManagerImpl.java index 1f28cca5..c9a56ca6 100644 --- a/repo/src/main/java/com/parashift/onlyoffice/util/UrlManager.java +++ b/repo/src/main/java/com/parashift/onlyoffice/sdk/manager/url/UrlManagerImpl.java @@ -1,5 +1,11 @@ -package com.parashift.onlyoffice.util; - +package com.parashift.onlyoffice.sdk.manager.url; + +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.settings.SettingsManager; +import com.onlyoffice.manager.url.DefaultUrlManager; +import com.onlyoffice.model.documenteditor.config.document.DocumentType; +import com.onlyoffice.model.settings.SettingsConstants; +import com.parashift.onlyoffice.util.Util; import org.alfresco.repo.admin.SysAdminParams; import org.alfresco.repo.imap.ImapService; import org.alfresco.service.cmr.coci.CheckOutCheckInService; @@ -11,92 +17,104 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.extensions.surf.util.URLEncoder; -import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.Date; import java.util.List; /* - Copyright (c) Ascensio System SIA 2023. All rights reserved. - http://www.onlyoffice.com + Copyright (c) Ascensio System SIA 2023. All rights reserved. + http://www.onlyoffice.com */ -@Service -public class UrlManager { + +public class UrlManagerImpl extends DefaultUrlManager implements UrlManager { @Autowired @Qualifier("checkOutCheckInService") CheckOutCheckInService cociService; - + @Autowired + NodeService nodeService; @Autowired AuthenticationService authenticationService; - @Autowired SysAdminParams sysAdminParams; - @Autowired - NodeService nodeService; - - @Autowired - ConfigManager configManager; - + DocumentManager documentManager; @Autowired ImapService imapService; - public String getCreateNewUrl(NodeRef nodeRef, String docType){ - String folderNodeRef = this.nodeService.getPrimaryParent(nodeRef).getParentRef().toString(); - String docMime = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; - switch (docType) { - case "cell": { - docMime = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; - break; - } - case "slide": { - docMime = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; - break; - } - } - return getShareUrl() + "page/onlyoffice-edit?parentNodeRef=" + folderNodeRef + "&new=" + docMime; - } - - public String getFavoriteUrl(NodeRef nodeRef){ - return "parashift/onlyoffice/editor-api/favorite?nodeRef=" + nodeRef.toString(); - } - - public String getHistoryInfoUrl(NodeRef nodeRef) { - return "parashift/onlyoffice/history/info?nodeRef=" + nodeRef.toString(); + public UrlManagerImpl(SettingsManager settingsManager) { + super(settingsManager); } - public String getHistoryDataUrl(NodeRef nodeRef) { - return "parashift/onlyoffice/history/data?nodeRef=" + nodeRef.toString(); - } + @Override + public String getFileUrl(String fileId) { + NodeRef nodeRef = new NodeRef(fileId); - public String getHistoryDiffUrl(NodeRef nodeRef) { - return getAlfrescoUrl() + "s/parashift/onlyoffice/download/diff?nodeRef=" + nodeRef.toString() + "&alf_ticket=" + authenticationService.getCurrentTicket(); + return getAlfrescoUrl() + + "s/parashift/onlyoffice/download/file?nodeRef=" + + nodeRef.toString() + + "&alf_ticket=" + + authenticationService.getCurrentTicket(); } - public String getContentUrl(NodeRef nodeRef) { - return getAlfrescoUrl() + "s/parashift/onlyoffice/download/file?nodeRef=" + nodeRef.toString() + "&alf_ticket=" + authenticationService.getCurrentTicket(); - } + @Override + public String getCallbackUrl(String fileId) { + NodeRef nodeRef = new NodeRef(fileId); - public String getCallbackUrl(NodeRef nodeRef) { String hash = null; if (cociService.isCheckedOut(nodeRef)) { hash = (String) nodeService.getProperty(cociService.getWorkingCopy(nodeRef), Util.EditingHashAspect); } - return getAlfrescoUrl() + "s/parashift/onlyoffice/callback?nodeRef=" + nodeRef.toString() + "&cb_key=" + hash; + return getAlfrescoUrl() + + "s/parashift/onlyoffice/callback?nodeRef=" + + nodeRef.toString() + + "&cb_key=" + + hash; } - public String getTestConversionUrl() { - return getAlfrescoUrl() + "s/parashift/onlyoffice/convertertest?alf_ticket=" + authenticationService.getCurrentTicket(); + @Override + public String getCreateUrl(String fileId) { + //Todo: check if user have access create new document in current folder + NodeRef nodeRef = new NodeRef(fileId); + + String fileName = documentManager.getDocumentName(fileId); + String folderNodeRef = this.nodeService.getPrimaryParent(nodeRef).getParentRef().toString(); + + DocumentType documentType = documentManager.getDocumentType(fileName); + + String docMime = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + switch (documentType) { + case CELL: { + docMime = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + break; + } + case SLIDE: { + docMime = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + break; + } + } + return getShareUrl() + "page/onlyoffice-edit?parentNodeRef=" + folderNodeRef + "&new=" + docMime; } - public String getEditorUrl() { - return configManager.demoActive() ? configManager.getDemo("url") : (String) configManager.getOrDefault("url", "http://127.0.0.1/"); + @Override + public String getTestConvertUrl(String productUrl) { + if (productUrl != null && !productUrl.isEmpty()) { + return sanitizeUrl(productUrl) + + "alfresco/s/parashift/onlyoffice/convertertest?alf_ticket=" + + authenticationService.getCurrentTicket(); + } else { + return getAlfrescoUrl() + + "s/parashift/onlyoffice/convertertest?alf_ticket=" + + authenticationService.getCurrentTicket(); + } } - public String getBackUrl(NodeRef nodeRef){ + @Override + public String getGobackUrl(String fileId){ + NodeRef nodeRef = new NodeRef(fileId); + String url = imapService.getContentFolderUrl(nodeRef); if (url.contains("?filter=path|")) { @@ -107,22 +125,27 @@ public String getBackUrl(NodeRef nodeRef){ return url; } - public String getEditorInnerUrl() { - String url = (String) configManager.getOrDefault("innerurl", ""); - if (url.isEmpty() || configManager.demoActive()) { - return getEditorUrl(); - } else { - return url; - } + public String getHistoryDiffUrl(NodeRef nodeRef) { + return getAlfrescoUrl() + + "s/parashift/onlyoffice/download/diff?nodeRef=" + + nodeRef.toString() + + "&alf_ticket=" + + authenticationService.getCurrentTicket(); } - public String getEmbeddedSaveUrl(String sharedId, String docTitle) { + public String getShareUrl() { + return UrlUtil.getShareUrl(sysAdminParams) + "/"; + } + + public String getEmbeddedSaveUrl(String fileId, String sharedId) { + String fileName = documentManager.getDocumentName(fileId); + StringBuilder embeddedSaveUrl = new StringBuilder(8); embeddedSaveUrl.append(UrlUtil.getShareUrl(sysAdminParams)); embeddedSaveUrl.append("/proxy/alfresco-noauth/api/internal/shared/node/"); embeddedSaveUrl.append(sharedId); embeddedSaveUrl.append("/content/"); - embeddedSaveUrl.append(URLEncoder.encodeUriComponent(docTitle)); + embeddedSaveUrl.append(URLEncoder.encodeUriComponent(fileName)); embeddedSaveUrl.append("?c=force"); embeddedSaveUrl.append("&noCache=" + new Date().getTime()); embeddedSaveUrl.append("&a=true"); @@ -130,7 +153,10 @@ public String getEmbeddedSaveUrl(String sharedId, String docTitle) { return embeddedSaveUrl.toString(); } - public String getEmbeddedSaveUrl(NodeRef nodeRef, String docTitle) { + public String getEmbeddedSaveUrl(String fileId) { + NodeRef nodeRef = new NodeRef(fileId); + String fileName = documentManager.getDocumentName(fileId); + StringBuilder embeddedSaveUrl = new StringBuilder(7); StoreRef storeRef = nodeRef.getStoreRef(); embeddedSaveUrl.append(UrlUtil.getShareUrl(sysAdminParams)); @@ -138,31 +164,33 @@ public String getEmbeddedSaveUrl(NodeRef nodeRef, String docTitle) { embeddedSaveUrl.append("/" + storeRef.getProtocol()); embeddedSaveUrl.append("/" + storeRef.getIdentifier()); embeddedSaveUrl.append("/" + nodeRef.getId()); - embeddedSaveUrl.append("/" + URLEncoder.encodeUriComponent(docTitle)); + embeddedSaveUrl.append("/" + URLEncoder.encodeUriComponent(fileName)); embeddedSaveUrl.append("?a=true"); return embeddedSaveUrl.toString(); } - private String getAlfrescoUrl() { - String alfUrl = (String) configManager.getOrDefault("alfurl", ""); - if (alfUrl.isEmpty()) { - return UrlUtil.getAlfrescoUrl(sysAdminParams) + "/"; - } else { - return alfUrl + "alfresco/"; - } + public String getFavoriteUrl(NodeRef nodeRef) { + return "parashift/onlyoffice/editor-api/favorite?nodeRef=" + + nodeRef.toString(); } - public String getShareUrl(){ - return UrlUtil.getShareUrl(sysAdminParams) + "/"; + public String getHistoryInfoUrl(NodeRef nodeRef) { + return "parashift/onlyoffice/history/info?nodeRef=" + + nodeRef.toString(); + } + + public String getHistoryDataUrl(NodeRef nodeRef) { + return "parashift/onlyoffice/history/data?nodeRef=" + + nodeRef.toString(); } - public String replaceDocEditorURLToInternal(String url) { - String innerDocEditorUrl = getEditorInnerUrl(); - String publicDocEditorUrl = getEditorUrl(); - if (!publicDocEditorUrl.equals(innerDocEditorUrl) && !configManager.demoActive()) { - url = url.replace(publicDocEditorUrl, innerDocEditorUrl); + private String getAlfrescoUrl() { + String alfUrl = getSettingsManager().getSetting(SettingsConstants.PRODUCT_INNER_URL); + if (alfUrl == null || alfUrl.isEmpty()) { + return sanitizeUrl(UrlUtil.getAlfrescoUrl(sysAdminParams)) + "/"; + } else { + return sanitizeUrl(alfUrl) + "/alfresco/"; } - return url; } } diff --git a/repo/src/main/java/com/parashift/onlyoffice/sdk/service/CallbackServiceImpl.java b/repo/src/main/java/com/parashift/onlyoffice/sdk/service/CallbackServiceImpl.java new file mode 100644 index 00000000..5ea2ffea --- /dev/null +++ b/repo/src/main/java/com/parashift/onlyoffice/sdk/service/CallbackServiceImpl.java @@ -0,0 +1,213 @@ +package com.parashift.onlyoffice.sdk.service; + +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.request.RequestManager; +import com.onlyoffice.manager.security.JwtManager; +import com.onlyoffice.manager.settings.SettingsManager; +import com.onlyoffice.model.convertservice.ConvertRequest; +import com.onlyoffice.model.convertservice.ConvertResponse; +import com.onlyoffice.model.documenteditor.Callback; +import com.onlyoffice.model.documenteditor.callback.History; +import com.onlyoffice.service.convert.ConvertService; +import com.onlyoffice.service.documenteditor.callback.DefaultCallbackService; +import com.parashift.onlyoffice.util.HistoryManager; +import com.parashift.onlyoffice.util.Util; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.version.VersionModel; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.version.VersionType; +import org.apache.http.HttpEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +import java.io.IOException; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/* + Copyright (c) Ascensio System SIA 2023. All rights reserved. + http://www.onlyoffice.com +*/ + +public class CallbackServiceImpl extends DefaultCallbackService { + @Autowired + @Qualifier("checkOutCheckInService") + CheckOutCheckInService cociService; + @Autowired + ContentService contentService; + @Autowired + NodeService nodeService; + @Autowired + HistoryManager historyManager; + @Autowired + Util util; + @Autowired + RequestManager requestManager; + @Autowired + ConvertService convertService; + @Autowired + DocumentManager documentManager; + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + public CallbackServiceImpl(JwtManager jwtManager, + SettingsManager settingsManager) { + super(jwtManager, settingsManager); + } + + public void handlerEditing(final Callback callback, final String fileId) throws Exception { + logger.debug("User has entered/exited ONLYOFFICE"); + } + + @Override + public void handlerSave(final Callback callback, final String fileId) throws Exception { + NodeRef nodeRef = new NodeRef(fileId); + NodeRef wc = cociService.getWorkingCopy(nodeRef); + Map versionProperties = new HashMap(); + + logger.debug("Document Updated, changing content"); + updateNode(wc, callback.getUrl(), callback.getFiletype()); + + logger.info("removing prop"); + nodeService.removeProperty(wc, Util.EditingHashAspect); + nodeService.removeProperty(wc, Util.EditingKeyAspect); + + versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR); + cociService.checkin(wc, versionProperties, null); + + History history = callback.getHistory(); + if (history != null) { + try { + historyManager.saveHistory( + nodeRef, + history, + callback.getChangesurl() + ); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + + util.postActivity(nodeRef, false); + + logger.debug("Save complete"); + } + + @Override + public void handlerSaveCorrupted(Callback callback, String fileId) throws Exception { + logger.error("ONLYOFFICE has reported that saving the document has failed"); + NodeRef nodeRef = new NodeRef(fileId); + NodeRef wc = cociService.getWorkingCopy(nodeRef); + AuthenticationUtil.setRunAsUser(AuthenticationUtil.getSystemUserName()); + cociService.cancelCheckout(wc); + } + + @Override + public void handlerClosed(Callback callback, String fileId) throws Exception { + logger.debug("No document updates, unlocking node"); + NodeRef nodeRef = new NodeRef(fileId); + NodeRef wc = cociService.getWorkingCopy(nodeRef); + AuthenticationUtil.setRunAsUser(AuthenticationUtil.getSystemUserName()); + cociService.cancelCheckout(wc); + } + + @Override + public void handlerForcesave(Callback callback, String fileId) throws Exception { + if (!super.getSettingsManager().getSettingBoolean("editor.customization.forcesave", false)) { + logger.debug("Forcesave is disabled, ignoring forcesave request"); + return; + } + + NodeRef nodeRef = new NodeRef(fileId); + NodeRef wc = cociService.getWorkingCopy(nodeRef); + Map versionProperties = new HashMap(); + + logger.debug("Forcesave request (type: " + callback.getForcesavetype() + ")"); + updateNode(wc, callback.getUrl(), callback.getFiletype()); + + String hash = (String) nodeService.getProperty(wc, Util.EditingHashAspect); + String key = (String) nodeService.getProperty(wc, Util.EditingKeyAspect); + + nodeService.removeProperty(wc, Util.EditingHashAspect); + nodeService.removeProperty(wc, Util.EditingKeyAspect); + + versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR); + cociService.checkin(wc, versionProperties, null, true); + + nodeService.setProperty(wc, Util.EditingHashAspect, hash); + nodeService.setProperty(wc, Util.EditingKeyAspect, key); + + History history = callback.getHistory(); + if (history != null) { + try { + historyManager.saveHistory( + nodeRef, + history, + callback.getChangesurl() + ); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + + util.postActivity(nodeRef, false); + + logger.debug("Forcesave complete"); + } + + private void updateNode(final NodeRef nodeRef, String url, String fileType) throws Exception { + logger.debug("Retrieving URL:" + url); + + String documentName = documentManager.getDocumentName(nodeRef.toString()); + String currentFileType = documentManager.getExtension(documentName); + final String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); + + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() { + public Void doWork() { + NodeRef sourcesNodeRef = cociService.getCheckedOut(nodeRef); + nodeService.setProperty(sourcesNodeRef, ContentModel.PROP_LOCK_OWNER, currentUser); + nodeService.setProperty(nodeRef, ContentModel.PROP_WORKING_COPY_OWNER, currentUser); + return null; + } + }, AuthenticationUtil.getSystemUserName()); + + if (!currentFileType.equals(fileType)) { + try { + logger.debug("Should convert back"); + ConvertRequest convert = ConvertRequest.builder() + .outputtype(currentFileType) + .url(url) + .build(); + + ConvertResponse convertResponse = convertService.processConvert(convert, nodeRef.toString()); + + if (convertResponse.getError() != null && convertResponse.getError().equals(ConvertResponse.Error.TOKEN)) { + throw new SecurityException(); + } + + if (convertResponse.getEndConvert() == null || !convertResponse.getEndConvert() + || convertResponse.getFileUrl() == null || convertResponse.getFileUrl().isEmpty()) { + throw new Exception("'endConvert' is false or 'fileUrl' is empty"); + } + + url = convertResponse.getFileUrl(); + } catch (Exception e) { + throw new Exception("Error while converting document back to original format: " + e.getMessage(), e); + } + } + + requestManager.executeGetRequest(url, new RequestManager.Callback() { + public Void doWork(Object response) throws IOException { + contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true).putContent(((HttpEntity)response).getContent()); + return null; + } + }); + } +} diff --git a/repo/src/main/java/com/parashift/onlyoffice/sdk/service/ConfigServiceImpl.java b/repo/src/main/java/com/parashift/onlyoffice/sdk/service/ConfigServiceImpl.java new file mode 100644 index 00000000..f8fa9db8 --- /dev/null +++ b/repo/src/main/java/com/parashift/onlyoffice/sdk/service/ConfigServiceImpl.java @@ -0,0 +1,145 @@ +package com.parashift.onlyoffice.sdk.service; + +import com.onlyoffice.manager.document.DocumentManager; +import com.onlyoffice.manager.security.JwtManager; +import com.onlyoffice.manager.settings.SettingsManager; +import com.onlyoffice.model.common.User; +import com.onlyoffice.model.documenteditor.config.document.DocumentType; +import com.onlyoffice.model.documenteditor.config.document.Info; +import com.onlyoffice.model.documenteditor.config.document.Permissions; +import com.onlyoffice.model.documenteditor.config.editorconfig.Embedded; +import com.onlyoffice.model.documenteditor.config.editorconfig.Template; +import com.onlyoffice.service.documenteditor.config.DefaultConfigService; +import com.parashift.onlyoffice.sdk.manager.url.UrlManager; +import com.parashift.onlyoffice.util.Util; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.favourites.FavouritesService; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/* + Copyright (c) Ascensio System SIA 2023. All rights reserved. + http://www.onlyoffice.com +*/ + +public class ConfigServiceImpl extends DefaultConfigService { + @Autowired + PersonService personService; + @Autowired + PermissionService permissionService; + @Autowired + FavouritesService favouritesService; + @Autowired + NodeService nodeService; + @Autowired + Util util; + @Autowired + UrlManager urlManager; + + public ConfigServiceImpl(DocumentManager documentManager, + UrlManager urlManager, + JwtManager jwtManager, + SettingsManager settingsManager) { + super(documentManager, urlManager, jwtManager, settingsManager); + } + + @Override + public Info getInfo(String fileId) { + NodeRef nodeRef = new NodeRef(fileId); + String userName = AuthenticationUtil.getFullyAuthenticatedUser(); + + if (userName != null) { + try { + return Info.builder() + .favorite(favouritesService.isFavourite(userName, nodeRef)) + .build(); + } catch (Exception e) { } + } + + return null; + } + + @Override + public Permissions getPermissions(String fileId) { + NodeRef nodeRef = new NodeRef(fileId); + String fileName = super.getDocumentManager().getDocumentName(fileId); + + Boolean editPermission = permissionService.hasPermission(nodeRef, PermissionService.WRITE) + == AccessStatus.ALLOWED; + Boolean isEditable = super.getDocumentManager().isEditable(fileName) + || super.getDocumentManager().isFillable(fileName); + + return Permissions.builder() + .edit(editPermission && isEditable) + .build(); + } + + @Override + public User getUser() { + String userName = AuthenticationUtil.getFullyAuthenticatedUser(); + + NodeRef person = personService.getPersonOrNull(userName); + PersonService.PersonInfo personInfo = null; + if (person != null) { + personInfo = personService.getPerson(person); + } + + User user = User.builder() + .id(userName) + .build(); + + if (personInfo == null) { + user.setName(userName); + } else { + user.setName(personInfo.getFirstName() + " " + personInfo.getLastName()); + } + + return user; + } + + @Override + public List