Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Privacy Policy Accepted Claim #117

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ smtpServer=
emailFromAddress=
emailSummaryTimePeriodInMinutes=
monitor=
privacyPolicyVersion=2001-01-01
3 changes: 1 addition & 2 deletions etc/i5.las2peer.webConnector.WebConnector.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
14 changes: 14 additions & 0 deletions etc/launcher-configuration.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
port = 9011
useMonitoringObserver = false

[bootstrap]

[serviceDirectories]
service

[commands]
uploadStartupDirectory
startService('[email protected]','Passphrase')
startWebConnector
interactive

Original file line number Diff line number Diff line change
Expand Up @@ -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.*;


Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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<BazaarFunction> functions) {
String resultJSON = null;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ public UserRecord createRecord(User entity) {
record.setEmailFollowSubscription(entity.isEmailFollowSubscription());
record.setPersonalizationEnabled(entity.isPersonalizationEnabled());
record.setCreationDate(OffsetDateTime.now());

return record;
}

Expand All @@ -65,6 +64,7 @@ public User getEntityFromTableRecord(UserRecord record) {
.lastUpdatedDate(record.getLastUpdatedDate())
.lastLoginDate(record.getLastLoginDate())
.personalizationEnabled(record.getPersonalizationEnabled())
.privacyPolicy(record.getPrivacyPolicyAccepted())
.build();
}

Expand All @@ -80,6 +80,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();
}

Expand Down Expand Up @@ -125,6 +126,9 @@ public Map<Field, Object> 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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
}


}
24 changes: 24 additions & 0 deletions reqbaz/src/main/resources/changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1670,3 +1670,27 @@ 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'
- 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
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,8 @@ public void testUserJsonView() {
assertTrue(response.isJsonObject());
assertTrue(response.has("email"));
assertTrue(response.has("emailFollowSubscription"));
assertTrue(response.has("privacyPolicyAccepted"));
assertFalse(response.get("privacyPolicyAccepted").getAsBoolean());

result = client.sendRequest("GET", mainPath + "users/" + initUser.getId(), "");
System.out.println(result.toString());
Expand All @@ -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();
Expand Down