From 9c52e10456b5e4db82e39bdc0ea54694c49c12fd Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 21 Oct 2020 15:26:40 -0400 Subject: [PATCH 1/8] #7307 add endpoint to get user by token --- .../edu/harvard/iq/dataverse/api/Admin.java | 32 +++++++++++++------ .../iq/dataverse/api/BuiltinUsersIT.java | 26 +++++++++++++++ .../edu/harvard/iq/dataverse/api/UtilIT.java | 6 ++++ 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 226f39d0f52..4d9f6a40d95 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -324,15 +324,29 @@ public Response deleteAuthenticationProvider(@PathParam("id") String id) { : "")); } - @GET - @Path("authenticatedUsers/{identifier}/") - public Response getAuthenticatedUser(@PathParam("identifier") String identifier) { - AuthenticatedUser authenticatedUser = authSvc.getAuthenticatedUser(identifier); - if (authenticatedUser != null) { - return ok(json(authenticatedUser)); - } - return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found."); - } + @GET + @Path("authenticatedUsers/{identifier}/") + public Response getAuthenticatedUserByIdentifier(@PathParam("identifier") String identifier) { + AuthenticatedUser authenticatedUser = authSvc.getAuthenticatedUser(identifier); + if (authenticatedUser != null) { + return getAuthenticatedUser(authenticatedUser); + } + return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found."); + } + + @GET + @Path("authenticatedUsers/token/{token}/") + public Response getAuthenticatedUserByToken(@PathParam("token") String token) { + AuthenticatedUser authenticatedUser = authSvc.lookupUser(token); + if (authenticatedUser != null) { + return getAuthenticatedUser(authenticatedUser); + } + return error(Response.Status.BAD_REQUEST, "User with token " + token + " not found."); + } + + private Response getAuthenticatedUser(AuthenticatedUser authenticatedUser) { + return ok(json(authenticatedUser)); + } @DELETE @Path("authenticatedUsers/{identifier}/") diff --git a/src/test/java/edu/harvard/iq/dataverse/api/BuiltinUsersIT.java b/src/test/java/edu/harvard/iq/dataverse/api/BuiltinUsersIT.java index 7c8034eb703..0f8385409a3 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/BuiltinUsersIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/BuiltinUsersIT.java @@ -16,6 +16,7 @@ import java.util.stream.Stream; import javax.json.Json; import javax.json.JsonObjectBuilder; +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static javax.ws.rs.core.Response.Status.OK; import static javax.ws.rs.core.Response.Status.FORBIDDEN; import static junit.framework.Assert.assertEquals; @@ -72,6 +73,31 @@ public void testCreateTimeAndApiLastUse() { .statusCode(OK.getStatusCode()); } + + @Test + public void testFindByToken() { + + Response createUser = UtilIT.createRandomUser(); + createUser.prettyPrint(); + createUser.then().assertThat() + .statusCode(OK.getStatusCode()); + + String username = UtilIT.getUsernameFromResponse(createUser); + String apiToken = UtilIT.getApiTokenFromResponse(createUser); + + Response getUserAsJsonByToken = UtilIT.getAuthenticatedUserByToken(apiToken); + + getUserAsJsonByToken.then().assertThat() + .statusCode(OK.getStatusCode()); + + getUserAsJsonByToken = UtilIT.getAuthenticatedUserByToken("badcode"); + getUserAsJsonByToken.then().assertThat() + .body("status", equalTo("ERROR")) + .body("message", equalTo("User with token badcode not found.")) + .statusCode(BAD_REQUEST.getStatusCode()); + + } + @Test public void testLastApiUse() { diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index 618b17c765c..386ff92f386 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -1178,6 +1178,12 @@ static Response getAuthenticatedUser(String userIdentifier, String apiToken) { .get("/api/admin/authenticatedUsers/" + userIdentifier); return response; } + + static Response getAuthenticatedUserByToken(String apiToken) { + Response response = given() + .get("/api/admin/authenticatedUsers/token/" + apiToken); + return response; + } /** * Used to the test the filter Authenticated Users API endpoint From 722b4619053a43d75d42a358c278fcc3088a947a Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 21 Oct 2020 15:51:44 -0400 Subject: [PATCH 2/8] Update native-api.rst --- doc/sphinx-guides/source/api/native-api.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 3240ee9ebe0..ecf4f84d2c5 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2875,8 +2875,15 @@ Sample output using "dataverseAdmin" as the ``identifier``:: "superuser": true, "affiliation": "Dataverse.org" } + +Alternatively you may pass a user's api ``token`` to retrieve the same output:: + + GET http://$SERVER/api/admin/authenticatedUsers/token/$token + +Create an Authenticated User +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Create an authenticateUser:: +Create an authenticatedUser:: POST http://$SERVER/api/admin/authenticatedUsers From 3d955193d5d2b2971d7398ad431ee9a70c35ffa3 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 21 Oct 2020 16:02:49 -0400 Subject: [PATCH 3/8] adding release note --- doc/release-notes/7307-get-user-info.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/release-notes/7307-get-user-info.md diff --git a/doc/release-notes/7307-get-user-info.md b/doc/release-notes/7307-get-user-info.md new file mode 100644 index 00000000000..f251c7e8e85 --- /dev/null +++ b/doc/release-notes/7307-get-user-info.md @@ -0,0 +1,3 @@ +### Notes for Developer and Integrators + +New API endpoint to retrieve user info so that tools can email users if needed. \ No newline at end of file From 977188f635095b340663888cfc3ad97502f91f25 Mon Sep 17 00:00:00 2001 From: Danny Brooke Date: Wed, 21 Oct 2020 16:33:51 -0400 Subject: [PATCH 4/8] updating header will clean this up in eventual release notes, just wanted to make sure I have something to pull from. :) --- doc/release-notes/7307-get-user-info.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/release-notes/7307-get-user-info.md b/doc/release-notes/7307-get-user-info.md index f251c7e8e85..a5cbffe86db 100644 --- a/doc/release-notes/7307-get-user-info.md +++ b/doc/release-notes/7307-get-user-info.md @@ -1,3 +1,3 @@ -### Notes for Developer and Integrators +### Notes for Tool Developers and Integrators -New API endpoint to retrieve user info so that tools can email users if needed. \ No newline at end of file +New API endpoint to retrieve user info so that tools can email users if needed. From f428250e7ce79bc8418fa9b6201bf3738bdfa362 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 26 Oct 2020 15:54:43 -0400 Subject: [PATCH 5/8] #7307 move endpoint to users --- .../java/edu/harvard/iq/dataverse/api/Admin.java | 16 +--------------- .../java/edu/harvard/iq/dataverse/api/Users.java | 16 ++++++++++++++++ .../edu/harvard/iq/dataverse/api/UtilIT.java | 10 +++++++++- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 4d9f6a40d95..e0165f45aa2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -329,25 +329,11 @@ public Response deleteAuthenticationProvider(@PathParam("id") String id) { public Response getAuthenticatedUserByIdentifier(@PathParam("identifier") String identifier) { AuthenticatedUser authenticatedUser = authSvc.getAuthenticatedUser(identifier); if (authenticatedUser != null) { - return getAuthenticatedUser(authenticatedUser); + return ok(json(authenticatedUser)); } return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found."); } - @GET - @Path("authenticatedUsers/token/{token}/") - public Response getAuthenticatedUserByToken(@PathParam("token") String token) { - AuthenticatedUser authenticatedUser = authSvc.lookupUser(token); - if (authenticatedUser != null) { - return getAuthenticatedUser(authenticatedUser); - } - return error(Response.Status.BAD_REQUEST, "User with token " + token + " not found."); - } - - private Response getAuthenticatedUser(AuthenticatedUser authenticatedUser) { - return ok(json(authenticatedUser)); - } - @DELETE @Path("authenticatedUsers/{identifier}/") public Response deleteAuthenticatedUser(@PathParam("identifier") String identifier) { diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Users.java b/src/main/java/edu/harvard/iq/dataverse/api/Users.java index 1ffdb441ca9..37eedbe7714 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Users.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Users.java @@ -11,6 +11,7 @@ import edu.harvard.iq.dataverse.authorization.users.User; import edu.harvard.iq.dataverse.engine.command.impl.ChangeUserIdentifierCommand; import edu.harvard.iq.dataverse.engine.command.impl.MergeInAccountCommand; +import static edu.harvard.iq.dataverse.util.json.JsonPrinter.json; import java.util.logging.Logger; import javax.ejb.Stateless; import javax.ws.rs.DELETE; @@ -174,5 +175,20 @@ public Response recreateToken() { return ok("New token for " + au.getUserIdentifier() + " is " + newToken.getTokenString()); } + + @GET + @Path(":me") + public Response getAuthenticatedUserByToken() { + + String tokenFromRequestAPI = getRequestApiKey(); + + AuthenticatedUser authenticatedUser = findUserByApiToken(tokenFromRequestAPI); + if (authenticatedUser == null) { + return error(Response.Status.BAD_REQUEST, "User with token " + tokenFromRequestAPI + " not found."); + } else { + return ok(json(authenticatedUser)); + } + + } } diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index 386ff92f386..ee78989b45c 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -1180,8 +1180,16 @@ static Response getAuthenticatedUser(String userIdentifier, String apiToken) { } static Response getAuthenticatedUserByToken(String apiToken) { + /* + return given() + .header(API_TOKEN_HTTP_HEADER, apiToken) + .urlEncodingEnabled(false) + .post("/api/dataverses/" + dataverseAlias + "/actions/:publish"); + */ Response response = given() - .get("/api/admin/authenticatedUsers/token/" + apiToken); + .header(API_TOKEN_HTTP_HEADER, apiToken) + .urlEncodingEnabled(false) + .get("/api/users/:me"); return response; } From d530a628421728649931c2c1b6fbeae038576993 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 26 Oct 2020 16:24:14 -0400 Subject: [PATCH 6/8] Update native-api.rst --- doc/sphinx-guides/source/api/native-api.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index ecf4f84d2c5..77af62f0214 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2875,10 +2875,6 @@ Sample output using "dataverseAdmin" as the ``identifier``:: "superuser": true, "affiliation": "Dataverse.org" } - -Alternatively you may pass a user's api ``token`` to retrieve the same output:: - - GET http://$SERVER/api/admin/authenticatedUsers/token/$token Create an Authenticated User ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 4ea431035070426ea1a9c9200fe71315205d5adc Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 26 Oct 2020 17:22:24 -0400 Subject: [PATCH 7/8] Update native-api.rst --- doc/sphinx-guides/source/api/native-api.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 77af62f0214..0c355b35254 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -2525,6 +2525,18 @@ Get All Notifications by User Each user can get a dump of their notifications by passing in their API token:: curl -H "X-Dataverse-key:$API_TOKEN" $SERVER_URL/api/notifications/all + +.. _User Information: + +User Information +---------------- + +Get User Information in JSON Format +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each user can get a dump of their basic information in JSON format by passing in their API token:: + + curl -H "X-Dataverse-key:$API_TOKEN" $SERVER_URL/api/users/:me .. _pids-api: From c500b0575c8a81166a75a2a5dc6bd5866dd8a6b0 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 27 Oct 2020 09:18:03 -0400 Subject: [PATCH 8/8] #7307 remove debug code --- src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index ee78989b45c..47aedb910d9 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -1180,12 +1180,6 @@ static Response getAuthenticatedUser(String userIdentifier, String apiToken) { } static Response getAuthenticatedUserByToken(String apiToken) { - /* - return given() - .header(API_TOKEN_HTTP_HEADER, apiToken) - .urlEncodingEnabled(false) - .post("/api/dataverses/" + dataverseAlias + "/actions/:publish"); - */ Response response = given() .header(API_TOKEN_HTTP_HEADER, apiToken) .urlEncodingEnabled(false)