feat: add option to disable OCR (#768)

fixes #344
refs #767
This commit is contained in:
Alexander ADAM 2024-09-07 22:27:48 +02:00 committed by GitHub
parent 8f1ff56d34
commit c2d7f3ebc6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 221 additions and 62 deletions

View File

@ -20,6 +20,11 @@ public enum ConfigType {
*/
GUEST_LOGIN,
/**
* OCR enabled.
*/
OCR_ENABLED,
/**
* Default language.
*/

View File

@ -9,7 +9,6 @@ import java.util.ResourceBundle;
/**
* Configuration parameter utilities.
*
* @author jtremeaux
*/
public class ConfigUtil {
/**
@ -72,7 +71,21 @@ public class ConfigUtil {
*/
public static boolean getConfigBooleanValue(ConfigType configType) {
String value = getConfigStringValue(configType);
return Boolean.parseBoolean(value);
}
/**
* Returns the boolean value of a configuration parameter with a default value.
*
* @param configType Type of the configuration parameter
* @param defaultValue Default value to return if the configuration parameter is undefined
* @return Boolean value of the configuration parameter
*/
public static boolean getConfigBooleanValue(ConfigType configType, boolean defaultValue) {
try {
return getConfigBooleanValue(configType);
} catch (IllegalStateException e) {
return defaultValue;
}
}
}

View File

@ -3,6 +3,8 @@ package com.sismics.docs.core.util.format;
import com.google.common.io.Closer;
import com.sismics.docs.core.constant.Constants;
import com.sismics.docs.core.util.FileUtil;
import com.sismics.docs.core.util.ConfigUtil;
import com.sismics.docs.core.constant.ConfigType;
import com.sismics.util.mime.MimeType;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.pdmodel.PDDocument;
@ -22,7 +24,6 @@ import java.nio.file.Path;
/**
* Image format handler.
*
* @author bgamard
*/
public class ImageFormatHandler implements FormatHandler {
/**
@ -45,7 +46,7 @@ public class ImageFormatHandler implements FormatHandler {
@Override
public String extractContent(String language, Path file) throws Exception {
if (language == null) {
if (language == null || !ConfigUtil.getConfigBooleanValue(ConfigType.OCR_ENABLED, true)) {
return null;
}

View File

@ -2,6 +2,8 @@ package com.sismics.docs.core.util.format;
import com.google.common.io.Closer;
import com.sismics.docs.core.util.FileUtil;
import com.sismics.docs.core.util.ConfigUtil;
import com.sismics.docs.core.constant.ConfigType;
import com.sismics.util.mime.MimeType;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
@ -53,7 +55,7 @@ public class PdfFormatHandler implements FormatHandler {
}
// No text content, try to OCR it
if (language != null && content != null && content.trim().isEmpty()) {
if (language != null && content != null && content.trim().isEmpty() && ConfigUtil.getConfigBooleanValue(ConfigType.OCR_ENABLED, true)) {
StringBuilder sb = new StringBuilder();
try (InputStream inputStream = Files.newInputStream(file);
PDDocument pdfDocument = PDDocument.load(inputStream)) {

View File

@ -182,9 +182,9 @@ abstract class DbOpenHelper {
public abstract void onUpgrade(int oldVersion, int newVersion) throws Exception;
/**
* Returns a List of all Exceptions which occured during the export.
* Returns a List of all Exceptions which occurred during the export.
*
* @return A List containig the Exceptions occured during the export
* @return A List containing the Exceptions occurred during the export
*/
public List<?> getExceptions() {
return exceptions;

View File

@ -1 +1 @@
db.version=30
db.version=31

View File

@ -0,0 +1,7 @@
-- DBUPDATE-031-0.SQL
-- Insert a new setting for OCR recognition
insert into T_CONFIG (CFG_ID_C, CFG_VALUE_C) values ('OCR_ENABLED', 'true');
-- Update the database version
update T_CONFIG set CFG_VALUE_C = '31' where CFG_ID_C = 'DB_VERSION';

View File

@ -1,3 +1,3 @@
api.current_version=${project.version}
api.min_version=1.0
db.version=30
db.version=31

View File

@ -58,9 +58,9 @@ public class AppResource extends BaseResource {
private static final Logger log = LoggerFactory.getLogger(AppResource.class);
/**
* Returns informations about the application.
* Returns information about the application.
*
* @api {get} /app Get application informations
* @api {get} /app Get application information
* @apiName GetApp
* @apiGroup App
* @apiSuccess {String} current_version API current version
@ -85,6 +85,7 @@ public class AppResource extends BaseResource {
String currentVersion = configBundle.getString("api.current_version");
String minVersion = configBundle.getString("api.min_version");
Boolean guestLogin = ConfigUtil.getConfigBooleanValue(ConfigType.GUEST_LOGIN);
Boolean ocrEnabled = ConfigUtil.getConfigBooleanValue(ConfigType.OCR_ENABLED, true);
String defaultLanguage = ConfigUtil.getConfigStringValue(ConfigType.DEFAULT_LANGUAGE);
UserDao userDao = new UserDao();
DocumentDao documentDao = new DocumentDao();
@ -98,6 +99,7 @@ public class AppResource extends BaseResource {
.add("current_version", currentVersion.replace("-SNAPSHOT", ""))
.add("min_version", minVersion)
.add("guest_login", guestLogin)
.add("ocr_enabled", ocrEnabled)
.add("default_language", defaultLanguage)
.add("queued_tasks", AppContext.getInstance().getQueuedTaskCount())
.add("total_memory", Runtime.getRuntime().totalMemory())
@ -140,6 +142,34 @@ public class AppResource extends BaseResource {
return Response.ok().build();
}
/**
* Enable/disable OCR.
*
* @api {post} /app/ocr Enable/disable OCR
* @apiName PostAppOcr
* @apiGroup App
* @apiParam {Boolean} enabled If true, enable OCR
* @apiError (client) ForbiddenError Access denied
* @apiPermission admin
* @apiVersion 1.5.0
*
* @param enabled If true, enable OCR
* @return Response
*/
@POST
@Path("ocr")
public Response ocr(@FormParam("enabled") Boolean enabled) {
if (!authenticate()) {
throw new ForbiddenClientException();
}
checkBaseFunction(BaseFunction.ADMIN);
ConfigDao configDao = new ConfigDao();
configDao.update(ConfigType.OCR_ENABLED, enabled.toString());
return Response.ok().build();
}
/**
* General application configuration.
*

View File

@ -21,6 +21,15 @@ angular.module('docs').controller('SettingsConfig', function($scope, $rootScope,
});
};
// Enable/disable OCR
$scope.changeOcrEnabled = function (enabled) {
Restangular.one('app').post('ocr', {
enabled: enabled
}).then(function () {
$scope.app.ocr_enabled = enabled;
});
};
// Fetch the current theme configuration
Restangular.one('theme').get().then(function (data) {
$scope.theme = data;

View File

@ -421,6 +421,10 @@
"smtp_username": "SMTP-Benutzername",
"smtp_password": "SMTP-Passwort",
"smtp_updated": "SMTP-Konfiguration erfolgreich aktualisiert",
"title_ocr": "Texterkennung (OCR)",
"message_ocr": "OCR ist eine Technologie, die es ermöglicht, Text aus Bildern zu extrahieren. Es wird verwendet, um den Inhalt von Bildern zu durchsuchen und zu indizieren. Diese Funktionalität setzt voraus, dass die Tesseract auf Ihrem Server installiert ist.",
"enable_ocr": "OCR aktivieren",
"disable_ocr": "OCR deaktivieren",
"webhooks": "Webhooks",
"webhooks_explain": "Webhooks werden aufgerufen, wenn das angegebene Ereignis eintritt. Die angegebene URL wird mit einer JSON-Payload gepostet, die den Ereignisnamen und die ID der betreffenden Ressource enthält.",
"webhook_event": "Ereignisse",

View File

@ -421,6 +421,10 @@
"smtp_username": "SMTP username",
"smtp_password": "SMTP password",
"smtp_updated": "SMTP configuration updated successfully",
"title_ocr": "Optical Character Recognition (OCR)",
"message_ocr": "OCR is a feature that extracts text from images and PDF files. This feature requires a working Tesseract installation on the server.",
"enable_ocr": "Enable OCR",
"disable_ocr": "Disable OCR",
"webhooks": "Webhooks",
"webhooks_explain": "Webhooks will be called when the specified event occur. The given URL will be POST-ed with a JSON payload containing the event name and the ID of the concerned resource.",
"webhook_event": "Event",

View File

@ -31,6 +31,17 @@
</div>
</form>
<h2>
<span translate="settings.config.title_ocr"></span>
<span class="label" ng-class="{ 'label-success': app.ocr_enabled, 'label-danger': !app.ocr_enabled }">
{{ app.ocr_enabled ? 'enabled' : 'disabled' | translate }}
</h2>
<p translate="settings.config.message_ocr" translate-values="{ appName: appName }"></p>
<div ng-if="app">
<button ng-if="!app.ocr_enabled" class="btn btn-primary" ng-click="changeOcrEnabled(true)">{{ 'settings.config.enable_ocr' | translate }}</button>
<button ng-if="app.ocr_enabled" class="btn btn-danger" ng-click="changeOcrEnabled(false)">{{ 'settings.config.disable_ocr' | translate }}</button>
</div>
<h2 translate="settings.config.title_theme"></h2>
<form class="form-horizontal" name="editColorForm" novalidate>
<div class="form-group">

View File

@ -1,3 +1,3 @@
api.current_version=${project.version}
api.min_version=1.0
db.version=30
db.version=31

View File

@ -58,6 +58,7 @@ public class TestAppResource extends BaseJerseyTest {
Assert.assertTrue(totalMemory > 0 && totalMemory > freeMemory);
Assert.assertEquals(0, json.getJsonNumber("queued_tasks").intValue());
Assert.assertFalse(json.getBoolean("guest_login"));
Assert.assertFalse(json.getBoolean("ocr_enabled"));
Assert.assertEquals("eng", json.getString("default_language"));
Assert.assertTrue(json.containsKey("global_storage_current"));
Assert.assertTrue(json.getJsonNumber("active_user_count").longValue() > 0);
@ -202,6 +203,37 @@ public class TestAppResource extends BaseJerseyTest {
.param("enabled", "false")), JsonObject.class);
}
/**
* Test the ocr setting
*/
@Test
public void testOcrSetting() {
// Login admin
String adminToken = adminToken();
// Get OCR configuration
JsonObject json = target().path("/app/ocr").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.get(JsonObject.class);
if (!configInboxChanged) {
Assert.assertFalse(json.getBoolean("enabled"));
}
// Change OCR configuration
target().path("/app/ocr").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.post(Entity.form(new Form()
.param("enabled", "true")
), JsonObject.class);
configInboxChanged = true;
// Get OCR configuration
json = target().path("/app/ocr").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.get(JsonObject.class);
Assert.assertTrue(json.getBoolean("enabled"));
}
/**
* Test SMTP configuration changes.
*/

41
scripts/dev_setup.sh Executable file
View File

@ -0,0 +1,41 @@
#!/bin/bash
install_macos_dependencies() {
brew install openjdk@11
export JAVA_HOME=/usr/local/opt/openjdk@11
brew install maven
brew install node
npm install -g grunt-cli
brew install tesseract
brew install ffmpeg
brew install mediainfo
}
install_ubuntu_debian_dependencies() {
sudo apt update
sudo apt install -y openjdk-11-jdk maven nodejs npm tesseract-ocr ffmpeg mediainfo
sudo npm install -g grunt-cli
}
install_fedora_dependencies() {
sudo dnf install -y java-11-openjdk-devel maven nodejs npm tesseract ffmpeg mediainfo
sudo npm install -g grunt-cli
}
echo "📥 Installing dependencies"
if [[ "$OSTYPE" == "darwin"* ]]; then
install_macos_dependencies
elif [[ -f /etc/debian_version ]]; then
install_ubuntu_debian_dependencies
elif [[ -f /etc/fedora-release ]]; then
install_fedora_dependencies
else
echo "❔ Unsupported OS. Feel free to contribute!"
exit 1
fi
echo "✅ Dependencies installed."
mvn clean -DskipTests install
echo "You can start the server with 'mvn jetty:run' and then access it at http://localhost:8080/docs-web/src/"