mirror of
https://github.com/sismics/docs.git
synced 2024-11-22 05:57:57 +01:00
Closes #166: global quota
This commit is contained in:
parent
66f781b716
commit
fb75bafe96
@ -46,23 +46,28 @@ public class Constants {
|
||||
public static final List<String> SUPPORTED_LANGUAGES = Lists.newArrayList("eng", "fra", "ita", "deu", "spa", "por", "pol", "rus", "ukr", "ara", "hin", "chi_sim", "chi_tra", "jpn", "tha", "kor");
|
||||
|
||||
/**
|
||||
* Base URL environnement variable.
|
||||
* Base URL environment variable.
|
||||
*/
|
||||
public static final String BASE_URL_ENV = "DOCS_BASE_URL";
|
||||
|
||||
/**
|
||||
* Default language environnement variable.
|
||||
* Default language environment variable.
|
||||
*/
|
||||
public static final String DEFAULT_LANGUAGE_ENV = "DOCS_DEFAULT_LANGUAGE";
|
||||
|
||||
/**
|
||||
* SMTP configuration environnement variables.
|
||||
* SMTP configuration environment variables.
|
||||
*/
|
||||
public static final String SMTP_HOSTNAME_ENV = "DOCS_SMTP_HOSTNAME";
|
||||
public static final String SMTP_PORT_ENV = "DOCS_SMTP_PORT";
|
||||
public static final String SMTP_USERNAME_ENV = "DOCS_SMTP_USERNAME";
|
||||
public static final String SMTP_PASSWORD_ENV = "DOCS_SMTP_PASSWORD";
|
||||
|
||||
/**
|
||||
* Global quota environment variable.
|
||||
*/
|
||||
public static final String GLOBAL_QUOTA_ENV = "DOCS_GLOBAL_QUOTA";
|
||||
|
||||
/**
|
||||
* Expiration time of the password recovery in hours.
|
||||
*/
|
||||
|
@ -1,19 +1,5 @@
|
||||
package com.sismics.docs.core.dao.jpa;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.mindrot.jbcrypt.BCrypt;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.sismics.docs.core.constant.AuditLogType;
|
||||
import com.sismics.docs.core.dao.jpa.criteria.UserCriteria;
|
||||
@ -24,6 +10,13 @@ import com.sismics.docs.core.util.jpa.QueryParam;
|
||||
import com.sismics.docs.core.util.jpa.QueryUtil;
|
||||
import com.sismics.docs.core.util.jpa.SortCriteria;
|
||||
import com.sismics.util.context.ThreadLocalContext;
|
||||
import org.mindrot.jbcrypt.BCrypt;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* User DAO.
|
||||
@ -59,7 +52,7 @@ public class UserDao {
|
||||
* @param user User to create
|
||||
* @param userId User ID
|
||||
* @return User ID
|
||||
* @throws Exception
|
||||
* @throws Exception e
|
||||
*/
|
||||
public String create(User user, String userId) throws Exception {
|
||||
// Create the user UUID
|
||||
@ -116,9 +109,8 @@ public class UserDao {
|
||||
* Updates a user's quota.
|
||||
*
|
||||
* @param user User to update
|
||||
* @return Updated user
|
||||
*/
|
||||
public User updateQuota(User user) {
|
||||
public void updateQuota(User user) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
|
||||
// Get the user
|
||||
@ -128,8 +120,6 @@ public class UserDao {
|
||||
|
||||
// Update the user
|
||||
userFromDb.setStorageQuota(user.getStorageQuota());
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -298,4 +288,15 @@ public class UserDao {
|
||||
}
|
||||
return userDtoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the global storage used by all users.
|
||||
*
|
||||
* @return Current global storage
|
||||
*/
|
||||
public long getGlobalStorageCurrent() {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
Query query = em.createNativeQuery("select sum(u.USE_STORAGECURRENT_N) from T_USER u where u.USE_DELETEDATE_D is null");
|
||||
return ((Number) query.getSingleResult()).longValue();
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,8 @@ public class AppResource extends BaseResource {
|
||||
* @apiSuccess {Boolean} guest_login True if guest login is enabled
|
||||
* @apiSuccess {String} total_memory Allocated JVM memory (in bytes)
|
||||
* @apiSuccess {String} free_memory Free JVM memory (in bytes)
|
||||
* @apiSuccess {String} global_storage_current Global storage currently used (in bytes)
|
||||
* @apiSuccess {String} global_storage_quota Maximum global storage (in bytes)
|
||||
* @apiPermission none
|
||||
* @apiVersion 1.5.0
|
||||
*
|
||||
@ -74,13 +76,23 @@ 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);
|
||||
UserDao userDao = new UserDao();
|
||||
String globalQuotaStr = System.getenv(Constants.GLOBAL_QUOTA_ENV);
|
||||
long globalQuota = 0;
|
||||
if (!Strings.isNullOrEmpty(globalQuotaStr)) {
|
||||
globalQuota = Long.valueOf(globalQuotaStr);
|
||||
}
|
||||
|
||||
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||
.add("current_version", currentVersion.replace("-SNAPSHOT", ""))
|
||||
.add("min_version", minVersion)
|
||||
.add("guest_login", guestLogin)
|
||||
.add("total_memory", Runtime.getRuntime().totalMemory())
|
||||
.add("free_memory", Runtime.getRuntime().freeMemory());
|
||||
.add("free_memory", Runtime.getRuntime().freeMemory())
|
||||
.add("global_storage_current", userDao.getGlobalStorageCurrent());
|
||||
if (globalQuota > 0) {
|
||||
response.add("global_storage_quota", globalQuota);
|
||||
}
|
||||
|
||||
return Response.ok().entity(response.build()).build();
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.sismics.docs.rest.resource;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.sismics.docs.core.constant.Constants;
|
||||
import com.sismics.docs.core.constant.PermType;
|
||||
import com.sismics.docs.core.dao.jpa.AclDao;
|
||||
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
||||
@ -14,7 +15,10 @@ import com.sismics.docs.core.event.FileCreatedAsyncEvent;
|
||||
import com.sismics.docs.core.event.FileDeletedAsyncEvent;
|
||||
import com.sismics.docs.core.model.jpa.File;
|
||||
import com.sismics.docs.core.model.jpa.User;
|
||||
import com.sismics.docs.core.util.*;
|
||||
import com.sismics.docs.core.util.DirectoryUtil;
|
||||
import com.sismics.docs.core.util.EncryptionUtil;
|
||||
import com.sismics.docs.core.util.FileUtil;
|
||||
import com.sismics.docs.core.util.PdfUtil;
|
||||
import com.sismics.rest.exception.ClientException;
|
||||
import com.sismics.rest.exception.ForbiddenClientException;
|
||||
import com.sismics.rest.exception.ServerException;
|
||||
@ -34,7 +38,9 @@ import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
import java.io.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
@ -130,11 +136,21 @@ public class FileResource extends BaseResource {
|
||||
throw new ServerException("ErrorGuessMime", "Error guessing mime type", e);
|
||||
}
|
||||
|
||||
// Validate quota
|
||||
// Validate user quota
|
||||
if (user.getStorageCurrent() + fileSize > user.getStorageQuota()) {
|
||||
throw new ClientException("QuotaReached", "Quota limit reached");
|
||||
}
|
||||
|
||||
// Validate global quota
|
||||
String globalStorageQuotaStr = System.getenv(Constants.GLOBAL_QUOTA_ENV);
|
||||
if (!Strings.isNullOrEmpty(globalStorageQuotaStr)) {
|
||||
long globalStorageQuota = Long.valueOf(globalStorageQuotaStr);
|
||||
long globalStorageCurrent = userDao.getGlobalStorageCurrent();
|
||||
if (globalStorageCurrent + fileSize > globalStorageQuota) {
|
||||
throw new ClientException("QuotaReached", "Global quota limit reached");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Get files of this document
|
||||
FileDao fileDao = new FileDao();
|
||||
|
@ -77,7 +77,7 @@ angular.module('docs').controller('DocumentDefault', function($scope, $rootScope
|
||||
})
|
||||
.error(function (data) {
|
||||
newfile.status = $translate.instant('document.default.upload_error');
|
||||
if (data.type == 'QuotaReached') {
|
||||
if (data.type === 'QuotaReached') {
|
||||
newfile.status += ' - ' + $translate.instant('document.default.upload_error_quota');
|
||||
}
|
||||
});
|
||||
|
@ -157,6 +157,10 @@
|
||||
|
||||
<div class="row" ng-controller="Footer">
|
||||
<div class="col-md-12 footer text-center text-muted">
|
||||
<div class="alert alert-danger" ng-show="app.global_storage_quota && app.global_storage_quota * 0.8 < app.global_storage_current"
|
||||
translate="index.global_quota_warning"
|
||||
translate-values="{ current: app.global_storage_current / 1000000, percent: app.global_storage_current / app.global_storage_quota * 100, total: app.global_storage_quota / 1000000 }">
|
||||
</div>
|
||||
<ul class="list-inline">
|
||||
<li uib-dropdown class="dropdown">
|
||||
<a href uib-dropdown-toggle>
|
||||
|
@ -35,7 +35,8 @@
|
||||
"error_info": "{{ count }} new error{{ count > 1 ? 's' : '' }}",
|
||||
"logged_as": "Logged in as {{ username }}",
|
||||
"nav_settings": "Settings",
|
||||
"logout": "Logout"
|
||||
"logout": "Logout",
|
||||
"global_quota_warning": "<strong>Warning!</strong> Global quota almost reached at {{ current | number: 0 }}MB ({{ percent | number: 1 }}%) used on {{ total | number: 0 }}MB"
|
||||
},
|
||||
"document": {
|
||||
"search_simple": "Simple search",
|
||||
|
@ -36,6 +36,7 @@ public class TestAppResource extends BaseJerseyTest {
|
||||
Long totalMemory = json.getJsonNumber("total_memory").longValue();
|
||||
Assert.assertTrue(totalMemory > 0 && totalMemory > freeMemory);
|
||||
Assert.assertFalse(json.getBoolean("guest_login"));
|
||||
Assert.assertTrue(json.containsKey("global_storage_current"));
|
||||
|
||||
// Rebuild Lucene index
|
||||
Response response = target().path("/app/batch/reindex").request()
|
||||
|
@ -9,3 +9,4 @@ log4j.logger.com.sismics=INFO
|
||||
log4j.logger.com.sismics.util.jpa=ERROR
|
||||
log4j.logger.org.hibernate=ERROR
|
||||
log4j.logger.org.apache.pdfbox=INFO
|
||||
log4j.logger.com.mchange=ERROR
|
||||
|
Loading…
Reference in New Issue
Block a user