diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/UserDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/UserDao.java index 216177cd..209fa97c 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/UserDao.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/UserDao.java @@ -256,7 +256,7 @@ public class UserDao { Map parameterMap = new HashMap<>(); List criteriaList = new ArrayList<>(); - StringBuilder sb = new StringBuilder("select u.USE_ID_C as c0, u.USE_USERNAME_C as c1, u.USE_EMAIL_C as c2, u.USE_CREATEDATE_D as c3, u.USE_STORAGECURRENT_N as c4, u.USE_STORAGEQUOTA_N as c5"); + StringBuilder sb = new StringBuilder("select u.USE_ID_C as c0, u.USE_USERNAME_C as c1, u.USE_EMAIL_C as c2, u.USE_CREATEDATE_D as c3, u.USE_STORAGECURRENT_N as c4, u.USE_STORAGEQUOTA_N as c5, u.USE_TOTPKEY_C as c6"); sb.append(" from T_USER u "); // Add search criterias @@ -292,7 +292,8 @@ public class UserDao { userDto.setEmail((String) o[i++]); userDto.setCreateTimestamp(((Timestamp) o[i++]).getTime()); userDto.setStorageCurrent(((Number) o[i++]).longValue()); - userDto.setStorageQuota(((Number) o[i]).longValue()); + userDto.setStorageQuota(((Number) o[i++]).longValue()); + userDto.setTotpKey((String) o[i]); userDtoList.add(userDto); } return userDtoList; diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/UserDto.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/UserDto.java index b0cc166b..081e3a5b 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/UserDto.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/UserDto.java @@ -35,7 +35,12 @@ public class UserDto { * Storage current usage. */ private Long storageCurrent; - + + /** + * TOTP key. + */ + private String totpKey; + public String getId() { return id; } @@ -83,4 +88,12 @@ public class UserDto { public void setStorageCurrent(Long storageCurrent) { this.storageCurrent = storageCurrent; } + + public String getTotpKey() { + return totpKey; + } + + public void setTotpKey(String totpKey) { + this.totpKey = totpKey; + } } diff --git a/docs-web-common/src/main/java/com/sismics/util/filter/SecurityFilter.java b/docs-web-common/src/main/java/com/sismics/util/filter/SecurityFilter.java index 385210b1..b4bad6e1 100644 --- a/docs-web-common/src/main/java/com/sismics/util/filter/SecurityFilter.java +++ b/docs-web-common/src/main/java/com/sismics/util/filter/SecurityFilter.java @@ -90,8 +90,8 @@ public abstract class SecurityFilter implements Filter { // Add base functions groupRoleIdSet.add(user.getRoleId()); - RoleBaseFunctionDao userBaseFuction = new RoleBaseFunctionDao(); - Set baseFunctionSet = userBaseFuction.findByRoleId(groupRoleIdSet); + RoleBaseFunctionDao userBaseFunction = new RoleBaseFunctionDao(); + Set baseFunctionSet = userBaseFunction.findByRoleId(groupRoleIdSet); userPrincipal.setBaseFunctionSet(baseFunctionSet); // Add email diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java index 731488c4..aaca4646 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java @@ -724,6 +724,7 @@ public class UserResource extends BaseResource { users.add(Json.createObjectBuilder() .add("id", userDto.getId()) .add("username", userDto.getUsername()) + .add("totp_enabled", userDto.getTotpKey() != null) .add("email", userDto.getEmail()) .add("storage_quota", userDto.getStorageQuota()) .add("storage_current", userDto.getStorageCurrent()) diff --git a/docs-web/src/main/webapp/src/locale/en.json b/docs-web/src/main/webapp/src/locale/en.json index b4fe52ff..8dc98c4f 100644 --- a/docs-web/src/main/webapp/src/locale/en.json +++ b/docs-web/src/main/webapp/src/locale/en.json @@ -216,6 +216,7 @@ "add_user": "Add a user", "username": "Username", "create_date": "Create date", + "totp_enabled": "Two-factor authentication enabled for this account", "edit": { "delete_user_title": "Delete user", "delete_user_message": "Do you really want to delete this user? All associated documents, files and tags will be deleted", diff --git a/docs-web/src/main/webapp/src/partial/docs/settings.user.html b/docs-web/src/main/webapp/src/partial/docs/settings.user.html index 75cc6e51..6cc614c8 100644 --- a/docs-web/src/main/webapp/src/partial/docs/settings.user.html +++ b/docs-web/src/main/webapp/src/partial/docs/settings.user.html @@ -15,7 +15,10 @@ - {{ user.username }} + + {{ user.username }} + + {{ user.create_date | date: dateFormat }} diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestUserResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestUserResource.java index 3ed9bcb5..4d5bdfa7 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestUserResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestUserResource.java @@ -1,7 +1,9 @@ package com.sismics.docs.rest; -import java.util.Date; -import java.util.Locale; +import com.sismics.util.filter.TokenBasedSecurityFilter; +import com.sismics.util.totp.GoogleAuthenticator; +import org.junit.Assert; +import org.junit.Test; import javax.json.JsonArray; import javax.json.JsonObject; @@ -9,12 +11,8 @@ import javax.ws.rs.client.Entity; import javax.ws.rs.core.Form; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; - -import org.junit.Assert; -import org.junit.Test; - -import com.sismics.util.filter.TokenBasedSecurityFilter; -import com.sismics.util.totp.GoogleAuthenticator; +import java.util.Date; +import java.util.Locale; /** * Exhaustive test of the user resource. @@ -55,7 +53,8 @@ public class TestUserResource extends BaseJerseyTest { Assert.assertNotNull(user.getJsonNumber("storage_quota")); Assert.assertNotNull(user.getJsonNumber("storage_current")); Assert.assertNotNull(user.getJsonNumber("create_date")); - + Assert.assertFalse(user.getBoolean("totp_enabled")); + // Create a user KO (login length validation) Response response = target().path("/user").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) @@ -114,7 +113,7 @@ public class TestUserResource extends BaseJerseyTest { .param("email", " bob@docs.com ") .param("password", " 12345678 ") .param("storage_quota", "10"); - json = target().path("/user").request() + target().path("/user").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .put(Entity.form(form), JsonObject.class); @@ -178,8 +177,8 @@ public class TestUserResource extends BaseJerseyTest { .get(JsonObject.class); Assert.assertEquals("alice@docs.com", json.getString("email")); Assert.assertFalse(json.getBoolean("is_default_password")); - Assert.assertEquals(0l, json.getJsonNumber("storage_current").longValue()); - Assert.assertEquals(1000000l, json.getJsonNumber("storage_quota").longValue()); + Assert.assertEquals(0L, json.getJsonNumber("storage_current").longValue()); + Assert.assertEquals(1000000L, json.getJsonNumber("storage_quota").longValue()); // Check bob user information json = target().path("/user").request() @@ -243,8 +242,8 @@ public class TestUserResource extends BaseJerseyTest { .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); Assert.assertTrue(json.getBoolean("is_default_password")); - Assert.assertEquals(0l, json.getJsonNumber("storage_current").longValue()); - Assert.assertEquals(10000000000l, json.getJsonNumber("storage_quota").longValue()); + Assert.assertEquals(0L, json.getJsonNumber("storage_current").longValue()); + Assert.assertEquals(10000000000L, json.getJsonNumber("storage_quota").longValue()); // User admin updates his information json = target().path("/user").request() @@ -323,7 +322,7 @@ public class TestUserResource extends BaseJerseyTest { int validationCode = googleAuthenticator.calculateCode(secret, new Date().getTime() / 30000); // Login with totp1 with a validation code - json = target().path("/user/login").request() + target().path("/user/login").request() .post(Entity.form(new Form() .param("username", "totp1") .param("password", "12345678") @@ -337,13 +336,13 @@ public class TestUserResource extends BaseJerseyTest { Assert.assertTrue(json.getBoolean("totp_enabled")); // Disable TOTP for totp1 - json = target().path("/user/disable_totp").request() + target().path("/user/disable_totp").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, totp1Token) .post(Entity.form(new Form() .param("password", "12345678")), JsonObject.class); // Login with totp1 without a validation code - json = target().path("/user/login").request() + target().path("/user/login").request() .post(Entity.form(new Form() .param("username", "totp1") .param("password", "12345678")