mirror of
https://github.com/sismics/docs.git
synced 2025-12-15 02:36:24 +00:00
@@ -1,3 +1,3 @@
|
||||
api.current_version=${project.version}
|
||||
api.min_version=1.0
|
||||
db.version=30
|
||||
db.version=31
|
||||
|
||||
@@ -47,7 +47,7 @@ import java.util.*;
|
||||
|
||||
/**
|
||||
* General app REST resource.
|
||||
*
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
@Path("/app")
|
||||
@@ -56,11 +56,11 @@ public class AppResource extends BaseResource {
|
||||
* Logger.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@@ -240,7 +270,7 @@ public class AppResource extends BaseResource {
|
||||
|
||||
return Response.ok().entity(response.build()).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure the SMTP server.
|
||||
*
|
||||
@@ -546,13 +576,13 @@ public class AppResource extends BaseResource {
|
||||
throw new ServerException("ServerError", "MEMORY appender not configured");
|
||||
}
|
||||
MemoryAppender memoryAppender = (MemoryAppender) appender;
|
||||
|
||||
|
||||
// Find the logs
|
||||
LogCriteria logCriteria = new LogCriteria()
|
||||
.setMinLevel(Level.toLevel(StringUtils.stripToNull(minLevel)))
|
||||
.setTag(StringUtils.stripToNull(tag))
|
||||
.setMessage(StringUtils.stripToNull(message));
|
||||
|
||||
|
||||
PaginatedList<LogEntry> paginatedList = PaginatedLists.create(limit, offset);
|
||||
memoryAppender.find(logCriteria, paginatedList);
|
||||
JsonArrayBuilder logs = Json.createArrayBuilder();
|
||||
@@ -563,14 +593,14 @@ public class AppResource extends BaseResource {
|
||||
.add("tag", logEntry.getTag())
|
||||
.add("message", logEntry.getMessage()));
|
||||
}
|
||||
|
||||
|
||||
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||
.add("total", paginatedList.getResultCount())
|
||||
.add("logs", logs);
|
||||
|
||||
|
||||
return Response.ok().entity(response.build()).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destroy and rebuild the search index.
|
||||
*
|
||||
@@ -592,7 +622,7 @@ public class AppResource extends BaseResource {
|
||||
throw new ForbiddenClientException();
|
||||
}
|
||||
checkBaseFunction(BaseFunction.ADMIN);
|
||||
|
||||
|
||||
RebuildIndexAsyncEvent rebuildIndexAsyncEvent = new RebuildIndexAsyncEvent();
|
||||
ThreadLocalContext.get().addAsyncEvent(rebuildIndexAsyncEvent);
|
||||
|
||||
@@ -601,7 +631,7 @@ public class AppResource extends BaseResource {
|
||||
.add("status", "ok");
|
||||
return Response.ok().entity(response.build()).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clean storage.
|
||||
*
|
||||
@@ -623,7 +653,7 @@ public class AppResource extends BaseResource {
|
||||
throw new ForbiddenClientException();
|
||||
}
|
||||
checkBaseFunction(BaseFunction.ADMIN);
|
||||
|
||||
|
||||
// Get all files
|
||||
FileDao fileDao = new FileDao();
|
||||
List<File> fileList = fileDao.findAll(0, Integer.MAX_VALUE);
|
||||
@@ -632,7 +662,7 @@ public class AppResource extends BaseResource {
|
||||
fileMap.put(file.getId(), file);
|
||||
}
|
||||
log.info("Checking {} files", fileMap.size());
|
||||
|
||||
|
||||
// Check if each stored file is valid
|
||||
try (DirectoryStream<java.nio.file.Path> storedFileList = Files.newDirectoryStream(DirectoryUtil.getStorageDirectory())) {
|
||||
for (java.nio.file.Path storedFile : storedFileList) {
|
||||
@@ -646,7 +676,7 @@ public class AppResource extends BaseResource {
|
||||
} catch (IOException e) {
|
||||
throw new ServerException("FileError", "Error deleting orphan files", e);
|
||||
}
|
||||
|
||||
|
||||
// Hard delete orphan audit logs
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
StringBuilder sb = new StringBuilder("delete from T_AUDIT_LOG al where al.LOG_ID_C in (select al.LOG_ID_C from T_AUDIT_LOG al ");
|
||||
@@ -660,7 +690,7 @@ public class AppResource extends BaseResource {
|
||||
sb.append(" where d.DOC_ID_C is null and a.ACL_ID_C is null and c.COM_ID_C is null and f.FIL_ID_C is null and t.TAG_ID_C is null and u.USE_ID_C is null and g.GRP_ID_C is null)");
|
||||
Query q = em.createNativeQuery(sb.toString());
|
||||
log.info("Deleting {} orphan audit logs", q.executeUpdate());
|
||||
|
||||
|
||||
// Soft delete orphan ACLs
|
||||
sb = new StringBuilder("update T_ACL a set ACL_DELETEDATE_D = :dateNow where a.ACL_ID_C in (select a.ACL_ID_C from T_ACL a ");
|
||||
sb.append(" left join T_SHARE s on s.SHA_ID_C = a.ACL_TARGETID_C ");
|
||||
@@ -672,37 +702,37 @@ public class AppResource extends BaseResource {
|
||||
q = em.createNativeQuery(sb.toString());
|
||||
q.setParameter("dateNow", new Date());
|
||||
log.info("Deleting {} orphan ACLs", q.executeUpdate());
|
||||
|
||||
|
||||
// Soft delete orphan comments
|
||||
q = em.createNativeQuery("update T_COMMENT set COM_DELETEDATE_D = :dateNow where COM_ID_C in (select c.COM_ID_C from T_COMMENT c left join T_DOCUMENT d on d.DOC_ID_C = c.COM_IDDOC_C and d.DOC_DELETEDATE_D is null where d.DOC_ID_C is null)");
|
||||
q.setParameter("dateNow", new Date());
|
||||
log.info("Deleting {} orphan comments", q.executeUpdate());
|
||||
|
||||
|
||||
// Soft delete orphan document tag links
|
||||
q = em.createNativeQuery("update T_DOCUMENT_TAG set DOT_DELETEDATE_D = :dateNow where DOT_ID_C in (select dt.DOT_ID_C from T_DOCUMENT_TAG dt left join T_DOCUMENT d on dt.DOT_IDDOCUMENT_C = d.DOC_ID_C and d.DOC_DELETEDATE_D is null left join T_TAG t on t.TAG_ID_C = dt.DOT_IDTAG_C and t.TAG_DELETEDATE_D is null where d.DOC_ID_C is null or t.TAG_ID_C is null)");
|
||||
q.setParameter("dateNow", new Date());
|
||||
log.info("Deleting {} orphan document tag links", q.executeUpdate());
|
||||
|
||||
|
||||
// Soft delete orphan shares
|
||||
q = em.createNativeQuery("update T_SHARE set SHA_DELETEDATE_D = :dateNow where SHA_ID_C in (select s.SHA_ID_C from T_SHARE s left join T_ACL a on a.ACL_TARGETID_C = s.SHA_ID_C and a.ACL_DELETEDATE_D is null where a.ACL_ID_C is null)");
|
||||
q.setParameter("dateNow", new Date());
|
||||
log.info("Deleting {} orphan shares", q.executeUpdate());
|
||||
|
||||
|
||||
// Soft delete orphan tags
|
||||
q = em.createNativeQuery("update T_TAG set TAG_DELETEDATE_D = :dateNow where TAG_ID_C in (select t.TAG_ID_C from T_TAG t left join T_USER u on u.USE_ID_C = t.TAG_IDUSER_C and u.USE_DELETEDATE_D is null where u.USE_ID_C is null)");
|
||||
q.setParameter("dateNow", new Date());
|
||||
log.info("Deleting {} orphan tags", q.executeUpdate());
|
||||
|
||||
|
||||
// Soft delete orphan documents
|
||||
q = em.createNativeQuery("update T_DOCUMENT set DOC_DELETEDATE_D = :dateNow where DOC_ID_C in (select d.DOC_ID_C from T_DOCUMENT d left join T_USER u on u.USE_ID_C = d.DOC_IDUSER_C and u.USE_DELETEDATE_D is null where u.USE_ID_C is null)");
|
||||
q.setParameter("dateNow", new Date());
|
||||
log.info("Deleting {} orphan documents", q.executeUpdate());
|
||||
|
||||
|
||||
// Soft delete orphan files
|
||||
q = em.createNativeQuery("update T_FILE set FIL_DELETEDATE_D = :dateNow where FIL_ID_C in (select f.FIL_ID_C from T_FILE f left join T_USER u on u.USE_ID_C = f.FIL_IDUSER_C and u.USE_DELETEDATE_D is null where u.USE_ID_C is null)");
|
||||
q.setParameter("dateNow", new Date());
|
||||
log.info("Deleting {} orphan files", q.executeUpdate());
|
||||
|
||||
|
||||
// Hard delete softly deleted data
|
||||
log.info("Deleting {} soft deleted document tag links", em.createQuery("delete DocumentTag where deleteDate is not null").executeUpdate());
|
||||
log.info("Deleting {} soft deleted ACLs", em.createQuery("delete Acl where deleteDate is not null").executeUpdate());
|
||||
@@ -713,7 +743,7 @@ public class AppResource extends BaseResource {
|
||||
log.info("Deleting {} soft deleted documents", em.createQuery("delete Document where deleteDate is not null").executeUpdate());
|
||||
log.info("Deleting {} soft deleted users", em.createQuery("delete User where deleteDate is not null").executeUpdate());
|
||||
log.info("Deleting {} soft deleted groups", em.createQuery("delete Group where deleteDate is not null").executeUpdate());
|
||||
|
||||
|
||||
// Always return OK
|
||||
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||
.add("status", "ok");
|
||||
|
||||
@@ -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;
|
||||
@@ -36,7 +45,7 @@ angular.module('docs').controller('SettingsConfig', function($scope, $rootScope,
|
||||
$rootScope.appName = $scope.theme.name;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// Send an image
|
||||
$scope.sendingImage = false;
|
||||
$scope.sendImage = function (type, image) {
|
||||
@@ -108,4 +117,4 @@ angular.module('docs').controller('SettingsConfig', function($scope, $rootScope,
|
||||
$scope.loadWebhooks();
|
||||
});
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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">
|
||||
@@ -196,4 +207,4 @@
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
api.current_version=${project.version}
|
||||
api.min_version=1.0
|
||||
db.version=30
|
||||
db.version=31
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test the app resource.
|
||||
*
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public class TestAppResource extends BaseJerseyTest {
|
||||
@@ -46,7 +46,7 @@ public class TestAppResource extends BaseJerseyTest {
|
||||
public void testAppResource() {
|
||||
// Login admin
|
||||
String adminToken = adminToken();
|
||||
|
||||
|
||||
// Check the application info
|
||||
JsonObject json = target().path("/app").request()
|
||||
.get(JsonObject.class);
|
||||
@@ -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);
|
||||
@@ -67,13 +68,13 @@ public class TestAppResource extends BaseJerseyTest {
|
||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||
.post(Entity.form(new Form()));
|
||||
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||
|
||||
|
||||
// Clean storage
|
||||
response = target().path("/app/batch/clean_storage").request()
|
||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||
.post(Entity.form(new Form()));
|
||||
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||
|
||||
|
||||
// Change the default language
|
||||
response = target().path("/app/config").request()
|
||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||
@@ -104,7 +105,7 @@ public class TestAppResource extends BaseJerseyTest {
|
||||
public void testLogResource() {
|
||||
// Login admin
|
||||
String adminToken = adminToken();
|
||||
|
||||
|
||||
// Check the logs (page 1)
|
||||
JsonObject json = target().path("/app/log")
|
||||
.queryParam("level", "DEBUG")
|
||||
@@ -116,7 +117,7 @@ public class TestAppResource extends BaseJerseyTest {
|
||||
Long date1 = logs.getJsonObject(0).getJsonNumber("date").longValue();
|
||||
Long date2 = logs.getJsonObject(9).getJsonNumber("date").longValue();
|
||||
Assert.assertTrue(date1 >= date2);
|
||||
|
||||
|
||||
// Check the logs (page 2)
|
||||
json = target().path("/app/log")
|
||||
.queryParam("offset", "10")
|
||||
@@ -194,7 +195,7 @@ public class TestAppResource extends BaseJerseyTest {
|
||||
target().path("/document/list").request()
|
||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, guestToken)
|
||||
.get(JsonObject.class);
|
||||
|
||||
|
||||
// Disable guest login (clean up state)
|
||||
target().path("/app/guest_login").request()
|
||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user