From 85651617b9fd34b8a0dfb34a4b96d1e2887f7497 Mon Sep 17 00:00:00 2001 From: Thore Date: Wed, 1 Sep 2021 16:44:31 +0200 Subject: [PATCH 1/3] Fix anonymous user being mapped incorrectly --- reqbaz/src/main/resources/changelog.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/reqbaz/src/main/resources/changelog.yaml b/reqbaz/src/main/resources/changelog.yaml index 19dd9ccd..9c2e8bb2 100644 --- a/reqbaz/src/main/resources/changelog.yaml +++ b/reqbaz/src/main/resources/changelog.yaml @@ -1670,3 +1670,15 @@ databaseChangeLog: splitStatements: true path: base-permissions.sql stripComments: true + - changeSet: + id: fix-anonymous-las2peerid + author: thore + changes: + - update: + columns: + - column: + name: las2peer_id + value: anonymous + schemaName: public + tableName: user + where: las2peer_id='-1722613621014065292' From 9321f3b5358b39d9c69e0e8fa57f0a6e0914d2f1 Mon Sep 17 00:00:00 2001 From: Thore Date: Wed, 1 Sep 2021 19:43:33 +0200 Subject: [PATCH 2/3] Add a privacyPolicyAccepted field to users --- ...is.bazaar.service.BazaarService.properties | 1 + etc/launcher-configuration.ini | 14 +++++ .../acis/bazaar/service/BazaarService.java | 10 +++ .../bazaar/service/dal/entities/User.java | 18 ++++++ .../dal/transform/UserTransformer.java | 7 ++- .../service/resources/UsersResource.java | 61 ++++++++++++++++++- reqbaz/src/main/resources/changelog.yaml | 12 ++++ .../dbis/acis/bazaar/service/BazaarTest.java | 9 +++ 8 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 etc/launcher-configuration.ini diff --git a/etc/de.rwth.dbis.acis.bazaar.service.BazaarService.properties b/etc/de.rwth.dbis.acis.bazaar.service.BazaarService.properties index 082404f1..c14aea0f 100644 --- a/etc/de.rwth.dbis.acis.bazaar.service.BazaarService.properties +++ b/etc/de.rwth.dbis.acis.bazaar.service.BazaarService.properties @@ -11,3 +11,4 @@ smtpServer= emailFromAddress= emailSummaryTimePeriodInMinutes= monitor= +privacyPolicyVersion=2001-01-01 diff --git a/etc/launcher-configuration.ini b/etc/launcher-configuration.ini new file mode 100644 index 00000000..ff3affbe --- /dev/null +++ b/etc/launcher-configuration.ini @@ -0,0 +1,14 @@ +port = 9011 +useMonitoringObserver = false + +[bootstrap] + +[serviceDirectories] +service + +[commands] +uploadStartupDirectory +startService('de.rwth.dbis.acis.bazaar.service.BazaarService@0.9.0','Passphrase') +startWebConnector +interactive + diff --git a/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/BazaarService.java b/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/BazaarService.java index 6bc9130b..a1509d94 100755 --- a/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/BazaarService.java +++ b/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/BazaarService.java @@ -69,7 +69,10 @@ import javax.xml.bind.DatatypeConverter; import java.net.HttpURLConnection; import java.net.URISyntaxException; +import java.time.LocalDate; import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.*; @@ -104,6 +107,7 @@ public class BazaarService extends RESTService { protected String smtpServer; protected String emailFromAddress; protected String emailSummaryTimePeriodInMinutes; + protected String privacyPolicyVersion; public BazaarService() throws Exception { setFieldValues(); @@ -187,6 +191,12 @@ public String getBaseURL() { return baseURL; } + public OffsetDateTime getPrivacyPolicyVersion() { + DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE; + LocalDate tmp = LocalDate.from(timeFormatter.parse(Objects.requireNonNullElse(privacyPolicyVersion, "2000-01-01"))); + return tmp.atStartOfDay().atOffset(ZoneOffset.UTC); + } + public String notifyRegistrars(EnumSet functions) { String resultJSON = null; try { diff --git a/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/entities/User.java b/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/entities/User.java index d2091d73..3008fa33 100644 --- a/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/entities/User.java +++ b/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/entities/User.java @@ -22,6 +22,8 @@ import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; import de.rwth.dbis.acis.bazaar.service.dal.helpers.SerializerViews; import lombok.Builder; @@ -86,6 +88,12 @@ public class User extends EntityBase { @JsonView(SerializerViews.Private.class) private OffsetDateTime lastLoginDate; + @JsonIgnore + private OffsetDateTime privacyPolicy; + + @JsonIgnore + private OffsetDateTime lastPrivacyPolicyVersion; + @JsonView(SerializerViews.Private.class) public String getEMail() { return eMail; @@ -123,4 +131,14 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(id, userName, firstName, lastName, eMail, las2peerId, profileImage, emailLeadSubscription, emailFollowSubscription, personalizationEnabled, creationDate, lastUpdatedDate, lastLoginDate); } + + @JsonProperty("privacyPolicyAccepted") + @JsonView(SerializerViews.Private.class) + private Boolean privacyPolicyAccepted() { + if (privacyPolicy == null) { + return false; + } + return privacyPolicy.isAfter(lastPrivacyPolicyVersion); + } + } diff --git a/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/transform/UserTransformer.java b/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/transform/UserTransformer.java index febaacee..c94ed488 100644 --- a/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/transform/UserTransformer.java +++ b/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/transform/UserTransformer.java @@ -45,7 +45,7 @@ public UserRecord createRecord(User entity) { record.setEmailFollowSubscription(entity.isEmailFollowSubscription()); record.setPersonalizationEnabled(entity.isPersonalizationEnabled()); record.setCreationDate(OffsetDateTime.now()); - + record.setPrivacyPolicyAccepted(OffsetDateTime.now()); return record; } @@ -65,6 +65,7 @@ public User getEntityFromTableRecord(UserRecord record) { .lastUpdatedDate(record.getLastUpdatedDate()) .lastLoginDate(record.getLastLoginDate()) .personalizationEnabled(record.getPersonalizationEnabled()) + .privacyPolicy(record.getPrivacyPolicyAccepted()) .build(); } @@ -80,6 +81,7 @@ public User getEntityFromQueryResult(de.rwth.dbis.acis.bazaar.dal.jooq.tables.Us .emailLeadSubscription(queryResult.getValues(user.EMAIL_LEAD_SUBSCRIPTION).get(0)) .emailFollowSubscription(queryResult.getValues(user.EMAIL_FOLLOW_SUBSCRIPTION).get(0)) .personalizationEnabled(queryResult.getValues(user.PERSONALIZATION_ENABLED).get(0)) + .privacyPolicy(queryResult.getValues(user.PRIVACY_POLICY_ACCEPTED).get(0)) .build(); } @@ -125,6 +127,9 @@ public Map getUpdateMap(User entity) { if (entity.isPersonalizationEnabled() != null) { put(USER.PERSONALIZATION_ENABLED, entity.isPersonalizationEnabled()); } + if (entity.getPrivacyPolicy() != null) { + put(USER.PRIVACY_POLICY_ACCEPTED, entity.getPrivacyPolicy()); + } }}; if (!updateMap.isEmpty()) { updateMap.put(USER.LAST_UPDATED_DATE, OffsetDateTime.now()); diff --git a/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/resources/UsersResource.java b/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/resources/UsersResource.java index 8e52beb3..09713c5b 100644 --- a/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/resources/UsersResource.java +++ b/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/resources/UsersResource.java @@ -161,7 +161,6 @@ public Response searchUser(@ApiParam(value = "Search filter", required = false) public Response getUser(@PathParam("userId") int userId) { DALFacade dalFacade = null; try { - // TODO: check whether the current user may request this project String registrarErrors = bazaarService.notifyRegistrars(EnumSet.of(BazaarFunction.VALIDATION, BazaarFunction.USER_FIRST_LOGIN_HANDLING)); if (registrarErrors != null) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); @@ -228,6 +227,8 @@ public Response getActiveUser() { bazaarService.getNotificationDispatcher().dispatchNotification(OffsetDateTime.now(), Activity.ActivityAction.RETRIEVE, MonitoringEvent.SERVICE_CUSTOM_MESSAGE_54, internalUserId, Activity.DataType.USER, internalUserId); + user.setLastPrivacyPolicyVersion(bazaarService.getPrivacyPolicyVersion()); + return Response.ok(user.toPrivateJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { @@ -442,5 +443,63 @@ public Response getEntityOverview( } } + /** + * Allows a user to accept the most recent privacy policy + * + * @return Response with the updated user as a JSON object. + */ + @PUT + @Path("/me/privacy") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "This method allows to set that a user has accepted the most recent privacy policy.") + @ApiResponses(value = { + @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "Returns the updated user", response = User.class), + @ApiResponse(code = HttpURLConnection.HTTP_UNAUTHORIZED, message = "Unauthorized"), + @ApiResponse(code = HttpURLConnection.HTTP_NOT_FOUND, message = "Not found"), + @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "Internal server problems") + }) + public Response acceptPrivacyPolicy() { + DALFacade dalFacade = null; + try { + Agent agent = Context.getCurrent().getMainAgent(); + String userId = agent.getIdentifier(); + String registrarErrors = bazaarService.notifyRegistrars(EnumSet.of(BazaarFunction.VALIDATION, BazaarFunction.USER_FIRST_LOGIN_HANDLING)); + if (registrarErrors != null) { + ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); + } + + // Block anonymous user + if (userId.equals("anonymous")) { + ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.user.read")); + } + + dalFacade = bazaarService.getDBConnection(); + + User user = dalFacade.getUserById(dalFacade.getUserIdByLAS2PeerId(userId)); + user.setPrivacyPolicy(OffsetDateTime.now()); + + user = dalFacade.modifyUser(user); + user.setLastPrivacyPolicyVersion(bazaarService.getPrivacyPolicyVersion()); + + return Response.ok(user.toPrivateJSON()).build(); + } catch (BazaarException bex) { + if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { + return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } else { + logger.warning(bex.getMessage()); + Context.get().monitorEvent(MonitoringEvent.SERVICE_ERROR, "Get active user"); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } + } catch (Exception ex) { + BazaarException bex = ExceptionHandler.getInstance().convert(ex, ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, ex.getMessage()); + logger.warning(bex.getMessage()); + Context.get().monitorEvent(MonitoringEvent.SERVICE_ERROR, "Get active user"); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } finally { + bazaarService.closeDBConnection(dalFacade); + } + } + } diff --git a/reqbaz/src/main/resources/changelog.yaml b/reqbaz/src/main/resources/changelog.yaml index 9c2e8bb2..74819a18 100644 --- a/reqbaz/src/main/resources/changelog.yaml +++ b/reqbaz/src/main/resources/changelog.yaml @@ -1682,3 +1682,15 @@ databaseChangeLog: schemaName: public tableName: user where: las2peer_id='-1722613621014065292' + - changeSet: + id: add-user-privacyclaim + author: thore + changes: + - addColumn: + tableName: user + columns: + - column: + constraints: + nullable: true + name: privacy_policy_accepted + type: TIMESTAMP WITH TIME ZONE diff --git a/reqbaz/src/test/java/de/rwth/dbis/acis/bazaar/service/BazaarTest.java b/reqbaz/src/test/java/de/rwth/dbis/acis/bazaar/service/BazaarTest.java index f13c7c46..86572086 100644 --- a/reqbaz/src/test/java/de/rwth/dbis/acis/bazaar/service/BazaarTest.java +++ b/reqbaz/src/test/java/de/rwth/dbis/acis/bazaar/service/BazaarTest.java @@ -441,6 +441,8 @@ public void testUserJsonView() { assertTrue(response.isJsonObject()); assertTrue(response.has("email")); assertTrue(response.has("emailFollowSubscription")); + assertTrue(response.has("privacyPolicyAccepted")); + assertTrue(response.get("privacyPolicyAccepted").getAsBoolean()); result = client.sendRequest("GET", mainPath + "users/" + initUser.getId(), ""); System.out.println(result.toString()); @@ -450,6 +452,13 @@ public void testUserJsonView() { assertTrue(response.isJsonObject()); assertFalse(response.has("email")); assertFalse(response.has("emailFollowSubscription")); + assertFalse(response.has("privacyPolicyAccepted")); + + + // Test privacy policy update entpoint + result = client.sendRequest("PUT", mainPath + "users/me/privacy", "", + MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON, new HashMap<>()); + assertEquals(200, result.getHttpCode()); } catch (Exception e) { e.printStackTrace(); From 78172e3a34e0ad28e4d042a908979df56f39e566 Mon Sep 17 00:00:00 2001 From: Thore Date: Wed, 8 Sep 2021 03:13:38 +0200 Subject: [PATCH 3/3] Create without accepted privacy policy --- etc/i5.las2peer.webConnector.WebConnector.properties | 3 +-- .../acis/bazaar/service/dal/transform/UserTransformer.java | 1 - .../test/java/de/rwth/dbis/acis/bazaar/service/BazaarTest.java | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/etc/i5.las2peer.webConnector.WebConnector.properties b/etc/i5.las2peer.webConnector.WebConnector.properties index 8bcbca0e..563348ee 100755 --- a/etc/i5.las2peer.webConnector.WebConnector.properties +++ b/etc/i5.las2peer.webConnector.WebConnector.properties @@ -11,5 +11,4 @@ preferLocalServices = TRUE xmlPath = defaultLoginUser=anonymous defaultLoginPassword=anonymous -oidcProviders = https://api.learning-layers.eu/o/oauth2,https://accounts.google.com -#oidcProviders = http://api.learning-layers.eu:8081/auth/realms/main,https://accounts.google.com +oidcProviders = https://api.learning-layers.eu/auth/realms/main,https://accounts.google.com diff --git a/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/transform/UserTransformer.java b/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/transform/UserTransformer.java index c94ed488..fc431924 100644 --- a/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/transform/UserTransformer.java +++ b/reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/transform/UserTransformer.java @@ -45,7 +45,6 @@ public UserRecord createRecord(User entity) { record.setEmailFollowSubscription(entity.isEmailFollowSubscription()); record.setPersonalizationEnabled(entity.isPersonalizationEnabled()); record.setCreationDate(OffsetDateTime.now()); - record.setPrivacyPolicyAccepted(OffsetDateTime.now()); return record; } diff --git a/reqbaz/src/test/java/de/rwth/dbis/acis/bazaar/service/BazaarTest.java b/reqbaz/src/test/java/de/rwth/dbis/acis/bazaar/service/BazaarTest.java index 86572086..8d0ee745 100644 --- a/reqbaz/src/test/java/de/rwth/dbis/acis/bazaar/service/BazaarTest.java +++ b/reqbaz/src/test/java/de/rwth/dbis/acis/bazaar/service/BazaarTest.java @@ -442,7 +442,7 @@ public void testUserJsonView() { assertTrue(response.has("email")); assertTrue(response.has("emailFollowSubscription")); assertTrue(response.has("privacyPolicyAccepted")); - assertTrue(response.get("privacyPolicyAccepted").getAsBoolean()); + assertFalse(response.get("privacyPolicyAccepted").getAsBoolean()); result = client.sendRequest("GET", mainPath + "users/" + initUser.getId(), ""); System.out.println(result.toString());