Skip to content
Snippets Groups Projects
Commit f515ce86 authored by uhensler's avatar uhensler
Browse files

OO-4905: OnlyOffice as thumbnail generator for office documents

parent 9f58e5a2
No related branches found
No related tags found
No related merge requests found
Showing
with 684 additions and 17 deletions
......@@ -29,7 +29,6 @@
<import resource="classpath:/org/olat/core/gui/components/form/flexible/impl/elements/richText/_spring/richTextCorecontext.xml"/>
<import resource="classpath:/org/olat/core/commons/services/_spring/servicesCorecontext.xml"/>
<import resource="classpath:/org/olat/core/commons/services/thumbnail/_spring/thumbnailserviceContext.xml"/>
<import resource="classpath:/org/olat/core/commons/services/webdav/_spring/webdavContext.xml"/>
<bean class="org.olat.core.gui.render.velocity.VelocityModule" depends-on="org.olat.core.helpers.Settings,coordinatorManager" init-method="init">
......
......@@ -72,6 +72,11 @@ public class FileEditor implements DocEditor {
return translator.translate("editor.display.name");
}
@Override
public boolean isViewOnly() {
return false;
}
@Override
public boolean isCollaborative() {
return false;
......
......@@ -45,6 +45,8 @@ public interface DocEditor {
String getDisplayName(Locale locale);
boolean isViewOnly();
boolean isCollaborative();
boolean isDataTransferConfirmationEnabled();
......
......@@ -72,6 +72,11 @@ public class CollaboraEditor implements DocEditor {
return translator.translate("editor.display.name");
}
@Override
public boolean isViewOnly() {
return false;
}
@Override
public boolean isCollaborative() {
return true;
......
......@@ -106,6 +106,7 @@ public class CollaboraServiceImpl implements CollaboraService, GenericEventListe
}
if (updated) {
refreshLock(vfsLeaf);
vfsRepositoryService.resetThumbnails(vfsLeaf);
}
return updated;
}
......
......@@ -111,6 +111,7 @@ public class DocEditorServiceImpl implements DocEditorService, UserDataDeletable
return editors.stream()
.filter(editor -> !FileEditor.TYPE.equals(editor.getType()))
.filter(DocEditor::isEnable)
.filter(editor -> !editor.isViewOnly())
.filter(editor -> editor.isEnabledFor(identity, roles))
.collect(Collectors.toList());
}
......
......@@ -70,6 +70,11 @@ public class Office365Editor implements DocEditor {
return translator.translate("editor.display.name");
}
@Override
public boolean isViewOnly() {
return false;
}
@Override
public boolean isCollaborative() {
return true;
......
......@@ -112,6 +112,7 @@ public class Office365ServiceImpl implements Office365Service, GenericEventListe
}
if (updated) {
refreshLock(vfsLeaf);
vfsRepositoryService.resetThumbnails(vfsLeaf);
}
return updated;
}
......
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.core.commons.services.doceditor.onlyoffice;
import org.olat.core.commons.services.thumbnail.FinalSize;
import org.olat.core.util.vfs.VFSLeaf;
/**
*
* Initial date: 4 Sep 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public interface OnlyOfficeConversionService {
FinalSize createThumbnail(VFSLeaf file, VFSLeaf thumbnailFile, int maxWidth, int maxHeight);
}
......@@ -58,7 +58,7 @@ public class OnlyOfficeEditor implements DocEditor {
@Override
public boolean isEnable() {
return onlyOfficeModule.isEnabled();
return onlyOfficeModule.isEnabled() && onlyOfficeModule.isEnabled();
}
@Override
......@@ -72,6 +72,12 @@ public class OnlyOfficeEditor implements DocEditor {
return translator.translate("editor.display.name");
}
@Override
public boolean isViewOnly() {
Integer licenseEdit = onlyOfficeModule.getLicenseEdit();
return licenseEdit != null && licenseEdit.intValue() <= 0? true: false;
}
@Override
public boolean isCollaborative() {
return true;
......
......@@ -47,11 +47,13 @@ public class OnlyOfficeModule extends AbstractSpringModule implements ConfigOnOf
private static final String ONLYOFFICE_ENABLED = "onlyoffice.enabled";
private static final String ONLYOFFICE_BASE_URL = "onlyoffice.baseUrl";
private static final String ONLYOFFICE_JWT_SECRET = "onlyoffice.jwt.secret";
private static final String ONLYOFFICE_EDITOR_ENABLED = "onlyoffice.editor.enabled";
private static final String ONLYOFFICE_LICENSE_EDIT = "onlyoffice.license.edit";
private static final String ONLYOFFICE_DATA_TRANSER_CONFIRMATION_ENABLED = "onlyoffice.data.transfer.confirmation.enabled";
private static final String ONLYOFFICE_USAGE_AUTHORS = "onlyoffice.usage.authors";
private static final String ONLYOFFICE_USAGE_COACHES = "onlyoffice.usage.coaches";
private static final String ONLYOFFICE_USAGE_MANAGERS = "onlyoffice.usage.managers";
private static final String ONLYOFFICE_THUMBNAILS_ENABLED = "onlyoffice.thumbnails.enabled";
@Value("${onlyoffice.enabled:false}")
private boolean enabled;
......@@ -60,8 +62,13 @@ public class OnlyOfficeModule extends AbstractSpringModule implements ConfigOnOf
@Value("${onlyoffice.api.path}")
private String apiPath;
private String apiUrl;
@Value("${onlyoffice.conversion.path}")
private String conversionPath;
private String conversionUrl;
private String jwtSecret;
private Key jwtSignKey;
@Value("${onlyoffice.editor.enabled:false}")
private boolean editorEnabled;
@Value("${onlyoffice.license.edit}")
private Integer licenseEdit;
@Value("${onlyoffice.data.transfer.confirmation.enabled:false}")
......@@ -72,6 +79,8 @@ public class OnlyOfficeModule extends AbstractSpringModule implements ConfigOnOf
private boolean usageRestrictedToCoaches;
@Value("${onlyoffice.usage.restricted.managers:false}")
private boolean usageRestrictedToManagers;
@Value("${onlyoffice.thumbnails.enabled:false}")
private boolean thumbnailsEnabled;
@Autowired
private OnlyOfficeModule(CoordinatorManager coordinateManager) {
......@@ -97,7 +106,7 @@ public class OnlyOfficeModule extends AbstractSpringModule implements ConfigOnOf
String baseUrlObj = getStringPropertyValue(ONLYOFFICE_BASE_URL, true);
if(StringHelper.containsNonWhitespace(baseUrlObj)) {
baseUrl = baseUrlObj;
resetApiUrl();
resetApiUrls();
}
String jwtSecretObj = getStringPropertyValue(ONLYOFFICE_JWT_SECRET, true);
......@@ -105,6 +114,11 @@ public class OnlyOfficeModule extends AbstractSpringModule implements ConfigOnOf
jwtSecret = jwtSecretObj;
}
String editorEnabledObj = getStringPropertyValue(ONLYOFFICE_EDITOR_ENABLED, true);
if(StringHelper.containsNonWhitespace(editorEnabledObj)) {
editorEnabled = "true".equals(editorEnabledObj);
}
String dataTransferConfirmationEnabledObj = getStringPropertyValue(ONLYOFFICE_DATA_TRANSER_CONFIRMATION_ENABLED, true);
if(StringHelper.containsNonWhitespace(dataTransferConfirmationEnabledObj)) {
dataTransferConfirmationEnabled = "true".equals(dataTransferConfirmationEnabledObj);
......@@ -129,6 +143,11 @@ public class OnlyOfficeModule extends AbstractSpringModule implements ConfigOnOf
if(StringHelper.containsNonWhitespace(usageRestrictedToManagersObj)) {
usageRestrictedToManagers = "true".equals(usageRestrictedToManagersObj);
}
String thumbnailsEnabledObj = getStringPropertyValue(ONLYOFFICE_THUMBNAILS_ENABLED, true);
if(StringHelper.containsNonWhitespace(thumbnailsEnabledObj)) {
thumbnailsEnabled = "true".equals(thumbnailsEnabledObj);
}
}
private Integer getIntOrNull(String val) {
......@@ -157,15 +176,20 @@ public class OnlyOfficeModule extends AbstractSpringModule implements ConfigOnOf
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
setStringProperty(ONLYOFFICE_BASE_URL, baseUrl, true);
resetApiUrl();
resetApiUrls();
}
public String getApiUrl() {
return apiUrl;
}
private void resetApiUrl() {
public String getConversionUrl() {
return conversionUrl;
}
private void resetApiUrls() {
this.apiUrl = baseUrl + apiPath;
this.conversionUrl = baseUrl + conversionPath;
}
public String getJwtSecret() {
......@@ -188,6 +212,15 @@ public class OnlyOfficeModule extends AbstractSpringModule implements ConfigOnOf
}
return jwtSignKey;
}
public boolean isEditorEnabled() {
return editorEnabled;
}
public void setEditorEnabled(boolean editorEnabled) {
this.editorEnabled = enabled;
setStringProperty(ONLYOFFICE_EDITOR_ENABLED, Boolean.toString(editorEnabled), true);
}
public Integer getLicenseEdit() {
return licenseEdit;
......@@ -237,5 +270,14 @@ public class OnlyOfficeModule extends AbstractSpringModule implements ConfigOnOf
this.usageRestrictedToManagers = usageRestrictedToManagers;
setStringProperty(ONLYOFFICE_USAGE_MANAGERS, Boolean.toString(usageRestrictedToManagers), true);
}
public boolean isThumbnailsEnabled() {
return thumbnailsEnabled;
}
public void setThumbnailsEnabled(boolean thumbnailsEnabled) {
this.thumbnailsEnabled = thumbnailsEnabled;
setStringProperty(ONLYOFFICE_THUMBNAILS_ENABLED, Boolean.toString(thumbnailsEnabled), true);
}
}
......@@ -19,8 +19,7 @@
*/
package org.olat.core.commons.services.doceditor.onlyoffice;
import org.olat.core.commons.services.doceditor.onlyoffice.model.DocumentImpl;
import org.olat.core.commons.services.doceditor.onlyoffice.model.EditorConfigImpl;
import java.util.Map;
/**
*
......@@ -51,7 +50,7 @@ public interface OnlyOfficeSecurityService {
* @param editorConfig
* @return jwtToken
*/
String getApiConfigToken(DocumentImpl document, EditorConfigImpl editorConfig);
String getApiConfigToken(Document document, EditorConfig editorConfig);
/**
* Creates the JWT token to use for download a file.
......@@ -61,6 +60,7 @@ public interface OnlyOfficeSecurityService {
* @return jwtToken
*/
String getFileDonwloadToken();
String getToken(Map<String, Object> claims);
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.core.commons.services.doceditor.onlyoffice.manager;
import java.io.InputStream;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.Logger;
import org.olat.core.commons.services.doceditor.onlyoffice.OnlyOfficeConversionService;
import org.olat.core.commons.services.doceditor.onlyoffice.OnlyOfficeModule;
import org.olat.core.commons.services.doceditor.onlyoffice.OnlyOfficeSecurityService;
import org.olat.core.commons.services.doceditor.onlyoffice.model.ConversionParams;
import org.olat.core.commons.services.doceditor.onlyoffice.model.ConversionResult;
import org.olat.core.commons.services.doceditor.onlyoffice.model.Thumbnail;
import org.olat.core.commons.services.thumbnail.FinalSize;
import org.olat.core.dispatcher.mapper.Mapper;
import org.olat.core.dispatcher.mapper.MapperService;
import org.olat.core.dispatcher.mapper.manager.MapperKey;
import org.olat.core.helpers.Settings;
import org.olat.core.logging.Tracing;
import org.olat.core.util.FileUtils;
import org.olat.core.util.Formatter;
import org.olat.core.util.StringHelper;
import org.olat.core.util.vfs.VFSLeaf;
import org.olat.core.util.vfs.VFSManager;
import org.olat.core.util.vfs.VFSMediaMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
*
* Initial date: 4 Sep 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
@Service
public class OnlyOfficeConversionServiceImpl implements OnlyOfficeConversionService {
private static final Logger log = Tracing.createLoggerFor(OnlyOfficeConversionServiceImpl.class);
private static ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private OnlyOfficeModule onlyOfficeModule;
@Autowired
private OnlyOfficeSecurityService onlyOfficeSecurityService;
@Autowired
private MapperService mapperService;
@Override
public FinalSize createThumbnail(VFSLeaf inputLeaf, VFSLeaf thumbnailLeaf, int maxWidth, int maxHeight) {
log.debug("Generate thumbnail for {}, ({})", inputLeaf.getMetaInfo().getUuid(), inputLeaf.getName());
boolean thumbnailCreated = false;
Mapper mapper = new VFSMediaMapper(inputLeaf);
MapperKey mapperKey = mapperService.register(null, mapper);
String url = Settings.createServerURI() + mapperKey.getUrl();
log.debug("Input leaf mapper url: {}", url);
ConversionParams conversionParams = createConversionParams(inputLeaf, thumbnailLeaf, maxWidth, maxHeight, url);
signConversionParams(conversionParams);
try {
thumbnailCreated = tryCreateThumbnail(conversionParams, thumbnailLeaf);
} catch (Exception e) {
log.error("Exception when creating thumbnail for {}, ({}).", inputLeaf.getMetaInfo().getUuid(), inputLeaf.getName(), e);
}
mapperService.cleanUp(Collections.singletonList(mapperKey));
if (!thumbnailCreated) {
log.warn("Thumbnail generation for {}, ({}) failed.", inputLeaf.getMetaInfo().getUuid(), inputLeaf.getName());
return null;
}
log.debug("Thumbnail generation for {}, ({}) successful.", inputLeaf.getMetaInfo().getUuid(), inputLeaf.getName());
return new FinalSize(maxWidth, maxWidth);
}
private ConversionParams createConversionParams(VFSLeaf inputLeaf, VFSLeaf thumbnailLeaf, int maxWidth,
int maxHeight, String url) {
ConversionParams conversionParams = new ConversionParams();
//Defines the document identifier used to unambiguously identify the document file.
conversionParams.setKey(inputLeaf.getMetaInfo().getUuid() + Formatter.formatDatetimeFilesystemSave(new Date()));
conversionParams.setUrl(url);
String suffix = FileUtils.getFileSuffix(thumbnailLeaf.getName());
conversionParams.setOutputtype(suffix);
// Defines the converted file name.
conversionParams.setTitle(thumbnailLeaf.getName());
Thumbnail thumbnail = new Thumbnail();
thumbnail.setAspect(1); // Keep aspect
thumbnail.setFirst(Boolean.TRUE); // First page only
thumbnail.setWidth(Integer.valueOf(maxWidth));
thumbnail.setHeight(Integer.valueOf(maxHeight));
conversionParams.setThumbnail(thumbnail);
return conversionParams;
}
private void signConversionParams(ConversionParams conversionParams) {
@SuppressWarnings("unchecked")
Map<String, Object> clainmsMap = objectMapper.convertValue(conversionParams, Map.class);
String token = onlyOfficeSecurityService.getToken(clainmsMap);
conversionParams.setToken(token);
}
private boolean tryCreateThumbnail(ConversionParams conversionParams, VFSLeaf thumbnailLeaf) throws JsonProcessingException {
boolean thumbnailCreated = false;
ConversionResult conversionResult = sendCreateThumbnailRequest(conversionParams);
if (conversionResult != null) {
Integer error = conversionResult.getError();
if (error == null) {
if (conversionResult.getEndConvert() != null && conversionResult.getEndConvert().booleanValue()) {
String fileUrl = conversionResult.getFileUrl();
if (StringHelper.containsNonWhitespace(fileUrl)) {
thumbnailCreated = fetchThumbnail(thumbnailLeaf, fileUrl);
}
}
} else {
logConversionError(error);
}
}
return thumbnailCreated;
}
private ConversionResult sendCreateThumbnailRequest(ConversionParams conversionParams)
throws JsonProcessingException {
HttpPost request = new HttpPost(onlyOfficeModule.getConversionUrl());
request.setHeader("Accept", "application/json");
request.addHeader("Authorization", getAutorisationHeader(conversionParams));
StringEntity requestEntity = new StringEntity(objectMapper.writeValueAsString(conversionParams), ContentType.APPLICATION_JSON);
request.setEntity(requestEntity);
ConversionResult conversionResult = null;
try (CloseableHttpClient client = HttpClientBuilder.create().build();
CloseableHttpResponse response = client.execute(request)) {
int statusCode = response.getStatusLine().getStatusCode();
log.debug("Status code of create thumbnail request: {}", statusCode);
if (statusCode == HttpStatus.SC_OK) {
String json = EntityUtils.toString(response.getEntity(), "UTF-8");
log.debug("Conversion response: {}", json);
conversionResult = objectMapper.readValue(json, ConversionResult.class);
}
} catch (Exception e) {
log.error("Create thumbnail request error.", e);
}
return conversionResult;
}
private String getAutorisationHeader(ConversionParams conversionParams) {
Map<String, Object> payloadMap = new HashMap<>();
payloadMap.put("payload", conversionParams);
String payloadToken = onlyOfficeSecurityService.getToken(payloadMap);
return "Bearer " + payloadToken;
}
private boolean fetchThumbnail(VFSLeaf thumbnailLeaf, String fileUrl) {
boolean thumbnailCreated = false;
HttpGet downLoadRequest = new HttpGet(fileUrl);
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse httpResponse = httpClient.execute(downLoadRequest);) {
if (httpResponse.getStatusLine().getStatusCode() == 200) {
InputStream content = httpResponse.getEntity().getContent();
thumbnailCreated = VFSManager.copyContent(content, thumbnailLeaf);
} else {
log.warn("Get thumbnail from ONLYOFICE failed. URL: {}", fileUrl);
}
} catch (Exception e) {
log.error("Get thumbnail from ONLYOFICE failed. URL: {}", fileUrl, e);
}
return thumbnailCreated;
}
/**
* See https://api.onlyoffice.com/editors/conversionapi#error
*
* @param error
*/
private void logConversionError(Integer error) {
String description;
switch (error.intValue()) {
case -1: description = "Unknown error.";
break;
case -2: description = "Conversion timeout error.";
break;
case -3: description = "Conversion error.";
break;
case -4: description = "Error while downloading the document file to be converted.";
break;
case -5: description = "Incorrect password.";
break;
case -6: description = "Error while accessing the conversion result database.";
break;
case -7: description = "Input error.";
break;
case -8: description = "Invalid token.";
break;
default:
description = "???.";
break;
}
log.warn("ONLYOFFICE conversion response error. Code {}: {}", error, description);
}
}
......@@ -21,15 +21,16 @@ package org.olat.core.commons.services.doceditor.onlyoffice.manager;
import java.io.IOException;
import java.security.Key;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.logging.log4j.Logger;
import org.olat.core.commons.services.doceditor.onlyoffice.Callback;
import org.olat.core.commons.services.doceditor.onlyoffice.Document;
import org.olat.core.commons.services.doceditor.onlyoffice.EditorConfig;
import org.olat.core.commons.services.doceditor.onlyoffice.OnlyOfficeModule;
import org.olat.core.commons.services.doceditor.onlyoffice.OnlyOfficeSecurityService;
import org.olat.core.commons.services.doceditor.onlyoffice.model.CallbackImpl;
import org.olat.core.commons.services.doceditor.onlyoffice.model.DocumentImpl;
import org.olat.core.commons.services.doceditor.onlyoffice.model.EditorConfigImpl;
import org.apache.logging.log4j.Logger;
import org.olat.core.logging.Tracing;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -102,7 +103,7 @@ public class OnlyOfficeSecurityServiceImpl implements OnlyOfficeSecurityService
}
@Override
public String getApiConfigToken(DocumentImpl document, EditorConfigImpl editorConfig) {
public String getApiConfigToken(Document document, EditorConfig editorConfig) {
return Jwts.builder()
.claim("document", document)
.claim("editorConfig", editorConfig)
......@@ -118,4 +119,12 @@ public class OnlyOfficeSecurityServiceImpl implements OnlyOfficeSecurityService
.compact();
}
@Override
public String getToken(Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.signWith(onlyOfficeModule.getJwtSignKey())
.compact();
}
}
......@@ -272,6 +272,7 @@ public class OnlyOfficeServiceImpl implements OnlyOfficeService {
if (updated) {
log.debug("File updated. File name: " + vfsLeaf.getName());
refreshLock(vfsLeaf);
vfsRepositoryService.resetThumbnails(vfsLeaf);
}
return updated;
......@@ -289,10 +290,10 @@ public class OnlyOfficeServiceImpl implements OnlyOfficeService {
public boolean isEditLicenseAvailable() {
Integer licenseEdit = onlyOfficeModule.getLicenseEdit();
if (licenseEdit == null) return true;
if (licenseEdit.intValue() == 0) return false;
if (licenseEdit.intValue() <= 0) return false;
Long accessCount = documentEditorServie.getAccessCount(OnlyOfficeEditor.TYPE, Mode.EDIT);
return accessCount < licenseEdit.byteValue();
return accessCount < licenseEdit.intValue();
}
@Override
......
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.core.commons.services.doceditor.onlyoffice.manager;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.olat.core.commons.services.doceditor.onlyoffice.OnlyOfficeConversionService;
import org.olat.core.commons.services.doceditor.onlyoffice.OnlyOfficeModule;
import org.olat.core.commons.services.thumbnail.CannotGenerateThumbnailException;
import org.olat.core.commons.services.thumbnail.FinalSize;
import org.olat.core.commons.services.thumbnail.ThumbnailSPI;
import org.olat.core.util.vfs.VFSLeaf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*
* Initial date: 4 Sep 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
@Service
public class OnlyOfficeThumbnailSPI implements ThumbnailSPI {
// https://api.onlyoffice.com/editors/conversionapi#text-matrix
private static final List<String> PNG_OUTPUT_EXTENSION = Arrays.asList(
// Text document file formats
"doc", "docm", "docx", "dot", "dotm", "dotx", "epub", "fodt", "html", "mht", "odt", "ott",
//"pdf", // PDFToThumbnail
"rtf", "txt",
// Spreadsheet file formats
"xps", "csv", "fods", "ods", "ots", "xls", "xlsm", "xlsx", "xlt", "xltm", "xltx",
// https://api.onlyoffice.com/editors/conversionapi#presentation-matrix
"fodp", "odp", "otp", "pot", "potm", "potx", "pps", "ppsm", "ppsx", "ppt", "pptm", "pptx");
@Autowired
private OnlyOfficeModule onlyOfficeModule;
@Autowired
private OnlyOfficeConversionService onlyOfficeConversionService;
@Override
public List<String> getExtensions() {
if (onlyOfficeModule.isEnabled() && onlyOfficeModule.isThumbnailsEnabled()) {
return PNG_OUTPUT_EXTENSION;
}
return Collections.emptyList();
}
@Override
public FinalSize generateThumbnail(VFSLeaf file, VFSLeaf thumbnailFile, int maxWidth, int maxHeight, boolean fill)
throws CannotGenerateThumbnailException {
return onlyOfficeConversionService.createThumbnail(file, thumbnailFile, maxWidth, maxHeight);
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.core.commons.services.doceditor.onlyoffice.model;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
*
* Initial date: 4 Sep 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ConversionParams {
private String filetype;
private String key;
private String outputtype;
private Thumbnail thumbnail;
private String title;
private String url;
private String token;
public String getFiletype() {
return filetype;
}
public void setFiletype(String filetype) {
this.filetype = filetype;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getOutputtype() {
return outputtype;
}
public void setOutputtype(String outputtype) {
this.outputtype = outputtype;
}
public Thumbnail getThumbnail() {
return thumbnail;
}
public void setThumbnail(Thumbnail thumbnail) {
this.thumbnail = thumbnail;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.core.commons.services.doceditor.onlyoffice.model;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
*
* Initial date: 9 Sep 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ConversionResult {
private Boolean endConvert;
private String fileUrl;
private Integer percent;
private Integer error;
public Boolean getEndConvert() {
return endConvert;
}
public void setEndConvert(Boolean endConvert) {
this.endConvert = endConvert;
}
public String getFileUrl() {
return fileUrl;
}
public void setFileUrl(String fileUrl) {
this.fileUrl = fileUrl;
}
public Integer getPercent() {
return percent;
}
public void setPercent(Integer percent) {
this.percent = percent;
}
public Integer getError() {
return error;
}
public void setError(Integer error) {
this.error = error;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.core.commons.services.doceditor.onlyoffice.model;
/**
*
* Initial date: 4 Sep 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class Thumbnail {
private Integer aspect;
private Boolean first;
private Integer height;
private Integer width;
public Integer getAspect() {
return aspect;
}
public void setAspect(Integer aspect) {
this.aspect = aspect;
}
public Boolean getFirst() {
return first;
}
public void setFirst(Boolean first) {
this.first = first;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
}
......@@ -94,7 +94,7 @@ public class OnlyOfficeWebService {
log.debug("ONLYOFFICE REST post callback request for File ID: " + fileId);
logRequestHeaders(httpHeaders);
if (!onlyOfficeModule.isEnabled()) {
if (!onlyOfficeModule.isEnabled() || !onlyOfficeModule.isEditorEnabled()) {
return Response.serverError().status(Status.FORBIDDEN).build();
}
......@@ -223,7 +223,7 @@ public class OnlyOfficeWebService {
log.debug("ONLYOFFICE REST get file contents request for File ID: " + fileId);
logRequestHeaders(httpHeaders);
if (!onlyOfficeModule.isEnabled()) {
if (!onlyOfficeModule.isEnabled() || !onlyOfficeModule.isEditorEnabled()) {
return Response.serverError().status(Status.FORBIDDEN).build();
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment