From b6707bed46eabb66b1f65ab21dec085fb56e3036 Mon Sep 17 00:00:00 2001 From: Ashar Fuadi Date: Sat, 3 Aug 2024 18:10:13 +0700 Subject: [PATCH] Allow guests for exporting users which will exclude email --- .../jophiel/api/UserApiIntegrationTests.java | 11 +++++-- .../UserApiPermissionIntegrationTests.java | 7 ++--- .../StatsUserProblemHibernateDao.java | 5 ++++ .../persistence/StatsUserProblemDao.java | 1 + .../judgels/jophiel/user/UserResource.java | 29 +++++++++++++++---- .../main/java/judgels/jophiel/UserClient.java | 4 +++ 6 files changed, 44 insertions(+), 13 deletions(-) diff --git a/judgels-backends/judgels-server-app/src/integTest/java/judgels/jophiel/api/UserApiIntegrationTests.java b/judgels-backends/judgels-server-app/src/integTest/java/judgels/jophiel/api/UserApiIntegrationTests.java index a9203ce0e..915fa9b31 100644 --- a/judgels-backends/judgels-server-app/src/integTest/java/judgels/jophiel/api/UserApiIntegrationTests.java +++ b/judgels-backends/judgels-server-app/src/integTest/java/judgels/jophiel/api/UserApiIntegrationTests.java @@ -54,9 +54,14 @@ void create_get_export_users() { assertThat(response.getLastSessionTimesMap()).doesNotContainKeys(nani.getJid()); String exportedCsv = userClient.exportUsers(adminToken, List.of("nani", "nano", "bogus")); - assertThat(exportedCsv).isEqualTo(String.format("jid,username,email\n" - + "%s,nani,nani@domain.com\n" - + "%s,nano,nano@domain.com\n", nani.getJid(), nano.getJid())); + assertThat(exportedCsv).isEqualTo(String.format("username,jid,email\n" + + "nani,%s,nani@domain.com\n" + + "nano,%s,nano@domain.com\n", nani.getJid(), nano.getJid())); + + exportedCsv = userClient.exportUsers(List.of("nani", "nano", "bogus")); + assertThat(exportedCsv).isEqualTo(String.format("username,jid\n" + + "nani,%s\n" + + "nano,%s\n", nani.getJid(), nano.getJid())); } @Test diff --git a/judgels-backends/judgels-server-app/src/integTest/java/judgels/jophiel/api/UserApiPermissionIntegrationTests.java b/judgels-backends/judgels-server-app/src/integTest/java/judgels/jophiel/api/UserApiPermissionIntegrationTests.java index 482d6dc74..a4abc271b 100644 --- a/judgels-backends/judgels-server-app/src/integTest/java/judgels/jophiel/api/UserApiPermissionIntegrationTests.java +++ b/judgels-backends/judgels-server-app/src/integTest/java/judgels/jophiel/api/UserApiPermissionIntegrationTests.java @@ -35,8 +35,7 @@ void get_users() { @Test void export_users() { - assertPermitted(exportUsers(adminToken)); - assertForbidden(exportUsers(userToken)); + assertPermitted(exportUsers()); } @Test @@ -61,8 +60,8 @@ private ThrowingCallable getUsers(String token) { return () -> userClient.getUsers(token); } - private ThrowingCallable exportUsers(String token) { - return () -> userClient.exportUsers(token, List.of()); + private ThrowingCallable exportUsers() { + return () -> userClient.exportUsers(List.of()); } private ThrowingCallable upsertUsers(String token) { diff --git a/judgels-backends/judgels-server-app/src/main/java/judgels/jerahmeel/hibernate/StatsUserProblemHibernateDao.java b/judgels-backends/judgels-server-app/src/main/java/judgels/jerahmeel/hibernate/StatsUserProblemHibernateDao.java index 4731772e4..070a231ff 100644 --- a/judgels-backends/judgels-server-app/src/main/java/judgels/jerahmeel/hibernate/StatsUserProblemHibernateDao.java +++ b/judgels-backends/judgels-server-app/src/main/java/judgels/jerahmeel/hibernate/StatsUserProblemHibernateDao.java @@ -162,6 +162,11 @@ public long selectCountTriedByUserJid(String userJid) { .count(); } + @Override + public long selectTotalScoreByUserJid(String userJid) { + return 0; + } + @Override public Map selectCountsVerdictByUserJid(String userJid) { CriteriaBuilder cb = currentSession().getCriteriaBuilder(); diff --git a/judgels-backends/judgels-server-app/src/main/java/judgels/jerahmeel/persistence/StatsUserProblemDao.java b/judgels-backends/judgels-server-app/src/main/java/judgels/jerahmeel/persistence/StatsUserProblemDao.java index 1d8c8d111..b0e42aaab 100644 --- a/judgels-backends/judgels-server-app/src/main/java/judgels/jerahmeel/persistence/StatsUserProblemDao.java +++ b/judgels-backends/judgels-server-app/src/main/java/judgels/jerahmeel/persistence/StatsUserProblemDao.java @@ -17,5 +17,6 @@ public interface StatsUserProblemDao extends Dao { Map selectCountsAcceptedByProblemJids(Collection problemJids); Map selectCountsTriedByProblemJids(Collection problemJids); long selectCountTriedByUserJid(String userJid); + long selectTotalScoreByUserJid(String userJid); Map selectCountsVerdictByUserJid(String userJid); } diff --git a/judgels-backends/judgels-server-app/src/main/java/judgels/jophiel/user/UserResource.java b/judgels-backends/judgels-server-app/src/main/java/judgels/jophiel/user/UserResource.java index df0139e9c..35890dbc6 100644 --- a/judgels-backends/judgels-server-app/src/main/java/judgels/jophiel/user/UserResource.java +++ b/judgels-backends/judgels-server-app/src/main/java/judgels/jophiel/user/UserResource.java @@ -1,20 +1,22 @@ package judgels.jophiel.user; +import static com.google.common.base.Preconditions.checkArgument; import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static javax.ws.rs.core.MediaType.TEXT_PLAIN; import static judgels.service.ServiceUtils.checkAllowed; import static judgels.service.ServiceUtils.checkFound; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import io.dropwizard.hibernate.UnitOfWork; import java.io.IOException; import java.io.StringWriter; import java.time.Instant; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import javax.inject.Inject; import javax.ws.rs.Consumes; @@ -91,13 +93,15 @@ public User createUser( @Produces(TEXT_PLAIN) @UnitOfWork(readOnly = true) public String exportUsers( - @HeaderParam(AUTHORIZATION) AuthHeader authHeader, + @HeaderParam(AUTHORIZATION) Optional authHeader, List usernames) { String actorJid = actorChecker.check(authHeader); - checkAllowed(roleChecker.canAdminister(actorJid)); + boolean canAdminister = roleChecker.canAdminister(actorJid); + + checkArgument(usernames.size() <= 100, "Cannot get more than 100 users."); - Map usersMap = userStore.getUsersByUsername(ImmutableSet.copyOf(usernames)); + Map usersMap = userStore.getUsersByUsername(Set.copyOf(usernames)); List users = usernames.stream() .filter(usersMap::containsKey) .map(usersMap::get) @@ -106,9 +110,22 @@ public String exportUsers( StringWriter csv = new StringWriter(); CSVWriter writer = new CSVWriter(csv); - writer.writeNext(new String[]{"jid", "username", "email"}, false); + List header = new ArrayList<>(); + header.add("username"); + header.add("jid"); + if (canAdminister) { + header.add("email"); + } + + writer.writeNext(header.toArray(new String[0]), false); for (User user : users) { - writer.writeNext(new String[]{user.getJid(), user.getUsername(), user.getEmail()}, false); + List row = new ArrayList<>(); + row.add(user.getUsername()); + row.add(user.getJid()); + if (canAdminister) { + row.add(user.getEmail()); + } + writer.writeNext(row.toArray(new String[0]), false); } return csv.toString(); } diff --git a/judgels-backends/judgels-server-feign/src/main/java/judgels/jophiel/UserClient.java b/judgels-backends/judgels-server-feign/src/main/java/judgels/jophiel/UserClient.java index 91cab89fd..3df44bfa9 100644 --- a/judgels-backends/judgels-server-feign/src/main/java/judgels/jophiel/UserClient.java +++ b/judgels-backends/judgels-server-feign/src/main/java/judgels/jophiel/UserClient.java @@ -30,6 +30,10 @@ public interface UserClient { @Headers("Authorization: Bearer {token}") User getMyself(@Param("token") String token); + @RequestLine("POST /api/v2/users/batch-get") + @Headers("Content-Type: application/json") + String exportUsers(List usernames); + @RequestLine("POST /api/v2/users/batch-get") @Headers({"Authorization: Bearer {token}", "Content-Type: application/json"}) String exportUsers(@Param("token") String token, List usernames);