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 697b8a62..1c12c419 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 @@ -488,7 +488,8 @@ public class UserResource extends BaseResource { response.add("username", user.getUsername()) .add("email", user.getEmail()) .add("storage_quota", user.getStorageQuota()) - .add("storage_current", user.getStorageCurrent()); + .add("storage_current", user.getStorageCurrent()) + .add("totp_enabled", user.getTotpKey() != null); // Base functions JsonArrayBuilder baseFunctions = Json.createArrayBuilder(); @@ -657,6 +658,11 @@ public class UserResource extends BaseResource { return Response.ok().entity(response.build()).build(); } + /** + * Enable time-based one-time password. + * + * @return Response + */ @POST @Path("enable_totp") public Response enableTotp() { @@ -679,6 +685,39 @@ public class UserResource extends BaseResource { return Response.ok().entity(response.build()).build(); } + /** + * Disable time-based one-time password. + * + * @param password Password + * @return Response + */ + @POST + @Path("disable_totp") + public Response disableTotp(@FormParam("password") String password) { + if (!authenticate()) { + throw new ForbiddenClientException(); + } + + // Validate the input data + password = ValidationUtil.validateLength(password, "password", 1, 100, false); + + // Check the password and get the user + UserDao userDao = new UserDao(); + User user = userDao.authenticate(principal.getName(), password); + if (user == null) { + throw new ForbiddenClientException(); + } + + // Remove the TOTP key + user.setTotpKey(null); + userDao.update(user, principal.getId()); + + // Always return OK + JsonObjectBuilder response = Json.createObjectBuilder() + .add("status", "ok"); + return Response.ok().entity(response.build()).build(); + } + /** * Returns the authentication token value. * 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 e338ca3e..3ed9bcb5 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 @@ -295,8 +295,14 @@ public class TestUserResource extends BaseJerseyTest { clientUtil.createUser("totp1"); String totp1Token = clientUtil.login("totp1"); + // Check TOTP enablement + JsonObject json = target().path("/user").request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, totp1Token) + .get(JsonObject.class); + Assert.assertFalse(json.getBoolean("totp_enabled")); + // Enable TOTP for totp1 - JsonObject json = target().path("/user/enable_totp").request() + json = target().path("/user/enable_totp").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, totp1Token) .post(Entity.form(new Form()), JsonObject.class); String secret = json.getString("secret"); @@ -323,5 +329,30 @@ public class TestUserResource extends BaseJerseyTest { .param("password", "12345678") .param("code", Integer.toString(validationCode)) .param("remember", "false")), JsonObject.class); + + // Check TOTP enablement + json = target().path("/user").request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, totp1Token) + .get(JsonObject.class); + Assert.assertTrue(json.getBoolean("totp_enabled")); + + // Disable TOTP for totp1 + json = 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() + .post(Entity.form(new Form() + .param("username", "totp1") + .param("password", "12345678") + .param("remember", "false")), JsonObject.class); + + // Check TOTP enablement + json = target().path("/user").request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, totp1Token) + .get(JsonObject.class); + Assert.assertFalse(json.getBoolean("totp_enabled")); } } \ No newline at end of file