mirror of
https://github.com/sismics/docs.git
synced 2024-11-22 14:07:55 +01:00
#41: Batch to rebuild quota storage + UI: show and edit quota
This commit is contained in:
parent
0fab0e4fc0
commit
aa97253ec7
@ -22,8 +22,10 @@ import org.apache.log4j.Appender;
|
|||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.sismics.docs.core.dao.jpa.FileDao;
|
import com.sismics.docs.core.dao.jpa.FileDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.UserDao;
|
||||||
import com.sismics.docs.core.model.context.AppContext;
|
import com.sismics.docs.core.model.context.AppContext;
|
||||||
import com.sismics.docs.core.model.jpa.File;
|
import com.sismics.docs.core.model.jpa.File;
|
||||||
|
import com.sismics.docs.core.model.jpa.User;
|
||||||
import com.sismics.docs.core.util.ConfigUtil;
|
import com.sismics.docs.core.util.ConfigUtil;
|
||||||
import com.sismics.docs.core.util.DirectoryUtil;
|
import com.sismics.docs.core.util.DirectoryUtil;
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedList;
|
import com.sismics.docs.core.util.jpa.PaginatedList;
|
||||||
@ -185,4 +187,53 @@ public class AppResource extends BaseResource {
|
|||||||
.add("status", "ok");
|
.add("status", "ok");
|
||||||
return Response.ok().entity(response.build()).build();
|
return Response.ok().entity(response.build()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recompute the quota for each user.
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("batch/recompute_quota")
|
||||||
|
public Response batchRecomputeQuota() {
|
||||||
|
if (!authenticate()) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
checkBaseFunction(BaseFunction.ADMIN);
|
||||||
|
|
||||||
|
// Get all files
|
||||||
|
FileDao fileDao = new FileDao();
|
||||||
|
List<File> fileList = fileDao.findAll();
|
||||||
|
|
||||||
|
// Count each file for the corresponding user quota
|
||||||
|
UserDao userDao = new UserDao();
|
||||||
|
Map<String, User> userMap = new HashMap<>();
|
||||||
|
for (File file : fileList) {
|
||||||
|
java.nio.file.Path storedFile = DirectoryUtil.getStorageDirectory().resolve(file.getId());
|
||||||
|
User user = null;
|
||||||
|
if (userMap.containsKey(file.getUserId())) {
|
||||||
|
user = userMap.get(file.getUserId());
|
||||||
|
} else {
|
||||||
|
user = userDao.getById(file.getUserId());
|
||||||
|
user.setStorageCurrent(0l);
|
||||||
|
userMap.put(user.getId(), user);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
user.setStorageCurrent(user.getStorageCurrent() + Files.size(storedFile));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ServerException("MissingFile", "File does not exist", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save all users
|
||||||
|
for (User user : userMap.values()) {
|
||||||
|
userDao.update(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always return OK
|
||||||
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
|
.add("status", "ok");
|
||||||
|
return Response.ok().entity(response.build()).build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ angular.module('docs').controller('SettingsUserEdit', function($scope, $dialog,
|
|||||||
*/
|
*/
|
||||||
if ($scope.isEdit()) {
|
if ($scope.isEdit()) {
|
||||||
Restangular.one('user', $stateParams.username).get().then(function(data) {
|
Restangular.one('user', $stateParams.username).get().then(function(data) {
|
||||||
|
data.storage_quota /= 1000000;
|
||||||
$scope.user = data;
|
$scope.user = data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -25,15 +26,17 @@ angular.module('docs').controller('SettingsUserEdit', function($scope, $dialog,
|
|||||||
*/
|
*/
|
||||||
$scope.edit = function() {
|
$scope.edit = function() {
|
||||||
var promise = null;
|
var promise = null;
|
||||||
|
var user = angular.copy($scope.user);
|
||||||
|
user.storage_quota *= 1000000;
|
||||||
|
|
||||||
if ($scope.isEdit()) {
|
if ($scope.isEdit()) {
|
||||||
promise = Restangular
|
promise = Restangular
|
||||||
.one('user', $stateParams.username)
|
.one('user', $stateParams.username)
|
||||||
.post('', $scope.user);
|
.post('', user);
|
||||||
} else {
|
} else {
|
||||||
promise = Restangular
|
promise = Restangular
|
||||||
.one('user')
|
.one('user')
|
||||||
.put($scope.user);
|
.put(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
promise.then(function() {
|
promise.then(function() {
|
||||||
|
@ -110,7 +110,10 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#/settings/account" title="Logged in as {{ userInfo.username }}">{{ userInfo.username }}</a>
|
<a href="#/settings/account" title="Logged in as {{ userInfo.username }}">
|
||||||
|
<span class="glyphicon glyphicon-user"></span>
|
||||||
|
{{ userInfo.username }}
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li ng-class="{active: $uiRoute}" ui-route="/settings.*">
|
<li ng-class="{active: $uiRoute}" ui-route="/settings.*">
|
||||||
<a href="#/settings/account">
|
<a href="#/settings/account">
|
||||||
|
@ -73,6 +73,11 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="pull-left" title="To upgrade your quota, ask your administrator">
|
||||||
|
{{ userInfo.storage_current / 1000000 | number: 0 }}MB ({{ userInfo.storage_current / userInfo.storage_quota * 100 | number: 1 }}%)
|
||||||
|
used on {{ userInfo.storage_quota / 1000000 | number: 0 }}MB
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
{{ totalDocuments }} document{{ totalDocuments > 1 ? 's' : '' }} found
|
{{ totalDocuments }} document{{ totalDocuments > 1 ? 's' : '' }} found
|
||||||
</div>
|
</div>
|
||||||
|
@ -37,6 +37,21 @@
|
|||||||
<span class="help-block" ng-show="editUserForm.email.$error.maxlength">Too long</span>
|
<span class="help-block" ng-show="editUserForm.email.$error.maxlength">Too long</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" ng-class="{ 'has-error': !editUserForm.storage_quota.$valid, success: editUserForm.storage_quota.$valid }">
|
||||||
|
<label class="col-sm-2 control-label" for="inputQuota">Storage quota</label>
|
||||||
|
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<div class="input-group">
|
||||||
|
<input name="storage_quota" type="number" id="inputQuota" required class="form-control"
|
||||||
|
ng-pattern="/[0-9]*/" placeholder="Storage quota (in MB)" ng-model="user.storage_quota"/>
|
||||||
|
<div class="input-group-addon">MB</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<span class="help-block" ng-show="editUserForm.storage_quota.$error.pattern">Number required</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group" ng-class="{ 'has-error': !editUserForm.password.$valid, success: editUserForm.password.$valid }">
|
<div class="form-group" ng-class="{ 'has-error': !editUserForm.password.$valid, success: editUserForm.password.$valid }">
|
||||||
<label class="col-sm-2 control-label" for="inputPassword">Password</label>
|
<label class="col-sm-2 control-label" for="inputPassword">Password</label>
|
||||||
|
|
||||||
|
@ -53,6 +53,12 @@ public class TestAppResource extends BaseJerseyTest {
|
|||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
|
||||||
.post(Entity.form(new Form()));
|
.post(Entity.form(new Form()));
|
||||||
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
|
|
||||||
|
// Recompute quota
|
||||||
|
response = target().path("/app/batch/recompute_quota").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
|
||||||
|
.post(Entity.form(new Form()));
|
||||||
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user