From a177b2479a449eedcce9de61dec038d043064f99 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Thu, 2 Aug 2018 18:32:26 +0200
Subject: [PATCH] date of acceptance of terms of use added; when changing terms
 of use admin can reset the acceptance

---
 frontend-js/src/main/js/ServerConnector.js    | 21 +++++++++++--
 .../js/gui/admin/ConfigurationAdminPanel.js   | 31 +++++++++++++++++++
 frontend-js/src/main/js/minerva.js            |  3 +-
 .../mapviewer/model/map/species/Element.java  |  6 ----
 .../java/lcsb/mapviewer/model/user/User.java  | 22 +++++++++++++
 ..._terms_of_use_consent_stores_timestamp.sql | 10 ++++++
 6 files changed, 84 insertions(+), 9 deletions(-)
 create mode 100644 persist/src/main/resources/db/migration/12.1.0~alpha.0/V12.1.0_20180802__user_terms_of_use_consent_stores_timestamp.sql

diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js
index 451ed4f88a..83564c9520 100644
--- a/frontend-js/src/main/js/ServerConnector.js
+++ b/frontend-js/src/main/js/ServerConnector.js
@@ -310,7 +310,7 @@ ServerConnector.objectToRequestString = function (object) {
     value = this.pointToString(object);
   } else if (Object.prototype.toString.call(object) === '[object Array]') {
     value = this.idsToString(object);
-  } else if (object===null){
+  } else if (object === null) {
     value = undefined;
   } else if (typeof object === 'string' || object instanceof String || !isNaN(object)) {
     value = object.toString();
@@ -1233,6 +1233,23 @@ ServerConnector.updateUser = function (user) {
   });
 };
 
+/**
+ *
+ * @returns {Promise}
+ */
+ServerConnector.resetUserTos = function () {
+  var self = this;
+  return self.getUsers().then(function (users) {
+    var promises = [];
+    for (var i = 0; i < users.length; i++) {
+      var user = users[i];
+      user.setTermsOfUseConsent(false);
+      promises.push(self.sendPatchRequest(self.getUserUrl({login: user.getLogin()}), {user: {termsOfUseConsent: false}}));
+    }
+    return Promise.all(promises);
+  });
+};
+
 /**
  *
  * @param {User} user
@@ -1346,7 +1363,7 @@ ServerConnector.updateUserPreferences = function (params) {
 
 /**
  *
- * @param {boolean} forceRefresh
+ * @param {boolean} [forceRefresh=false]
  *
  * @returns {Promise}
  */
diff --git a/frontend-js/src/main/js/gui/admin/ConfigurationAdminPanel.js b/frontend-js/src/main/js/gui/admin/ConfigurationAdminPanel.js
index 1d0a6c1c4d..fe173b2b8e 100644
--- a/frontend-js/src/main/js/gui/admin/ConfigurationAdminPanel.js
+++ b/frontend-js/src/main/js/gui/admin/ConfigurationAdminPanel.js
@@ -2,6 +2,7 @@
 
 var AbstractAdminPanel = require('./AbstractAdminPanel');
 var PrivilegeType = require('../../map/data/PrivilegeType');
+var ConfigurationType = require('../../ConfigurationType');
 
 var Functions = require('../../Functions');
 var GuiConnector = require('../../GuiConnector');
@@ -245,6 +246,36 @@ ConfigurationAdminPanel.prototype.saveOption = function (type) {
     }
     option.setValue(value);
     return self.getServerConnector().updateConfigurationOption(option);
+  }).then(function () {
+    if (type === ConfigurationType.TERMS_OF_USE) {
+      return new Promise(function (resolve) {
+        var html = '<form><span>Do you want to reset user the status of ToS acceptance for all users of the platform?</span><br></form>';
+        $(html).dialog({
+          modal: true,
+          title: 'Status of users ToS acceptance',
+          close: function () {
+            $(this).dialog('destroy').remove();
+            resolve(false);
+          },
+          buttons: {
+            'YES': function () {
+              $(this).dialog('destroy').remove();
+              resolve(true);
+            },
+            'NO': function () {
+              $(this).dialog('destroy').remove();
+              resolve(false);
+            }
+          }
+        });
+      }).then(function (status) {
+        if (status) {
+          return self.getServerConnector().resetUserTos();
+        } else {
+          console.log("no");
+        }
+      });
+    }
   });
 };
 
diff --git a/frontend-js/src/main/js/minerva.js b/frontend-js/src/main/js/minerva.js
index 5d9b6934f4..1127f3d3f6 100644
--- a/frontend-js/src/main/js/minerva.js
+++ b/frontend-js/src/main/js/minerva.js
@@ -77,7 +77,8 @@ function requestConsent(user, termsOfUseUrl) {
   var dialogContent = document.createElement("div");
   dialogContent.appendChild(functions.createElement({
     type: "span",
-    content: "I agree to the minerva <a href='" + termsOfUseUrl + "' target='_blank'>Terms of Use</a>."
+    content: "I agree to the minerva <a href='" + termsOfUseUrl + "' target='_blank'>Terms of Use</a>.",
+    xss: false
   }));
   var checkbox = functions.createElement({type: "input", inputType: "checkbox", style: "float: left"});
   var okButton = functions.createElement({
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/species/Element.java b/model/src/main/java/lcsb/mapviewer/model/map/species/Element.java
index 2af540b125..8089c5bccd 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/species/Element.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/species/Element.java
@@ -222,9 +222,6 @@ public abstract class Element implements BioEntity, Serializable, SbmlArgument {
    */
   private String name = "";
 
-  /**
-   * Lists of all synonyms used for describing this element.
-   */
   /**
    * Lists of all synonyms used for describing this element.
    */
@@ -235,9 +232,6 @@ public abstract class Element implements BioEntity, Serializable, SbmlArgument {
   @Cascade({ org.hibernate.annotations.CascadeType.ALL })
   private List<String> synonyms = new ArrayList<>();
 
-  /**
-   * List of former symbols used to describe this element.
-   */
   /**
    * Lists of all synonyms used for describing this element.
    */
diff --git a/model/src/main/java/lcsb/mapviewer/model/user/User.java b/model/src/main/java/lcsb/mapviewer/model/user/User.java
index 1add1fd25f..59c480f3c8 100644
--- a/model/src/main/java/lcsb/mapviewer/model/user/User.java
+++ b/model/src/main/java/lcsb/mapviewer/model/user/User.java
@@ -2,12 +2,15 @@ package lcsb.mapviewer.model.user;
 
 import java.awt.Color;
 import java.io.Serializable;
+import java.util.Calendar;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Set;
 
 import javax.persistence.CascadeType;
+import javax.persistence.CollectionTable;
 import javax.persistence.Column;
+import javax.persistence.ElementCollection;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
@@ -18,6 +21,8 @@ import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 
+import org.hibernate.annotations.Cascade;
+
 import lcsb.mapviewer.common.comparator.StringComparator;
 
 /**
@@ -126,6 +131,12 @@ public class User implements Serializable {
   @Column(name = "terms_of_use_consent")
   private boolean termsOfUseConsent = false;
 
+  @ElementCollection(fetch = FetchType.EAGER)
+  @CollectionTable(name = "user_terms_of_use_consent", joinColumns = @JoinColumn(name = "user_iddb"))
+  @Column(name = "date")
+  @Cascade({ org.hibernate.annotations.CascadeType.ALL })
+  private Set<Calendar> termsOfUseConsentDates = new HashSet<>();
+
   /**
    * Set of user privileges.
    */
@@ -380,6 +391,9 @@ public class User implements Serializable {
   }
 
   public void setTermsOfUseConsent(boolean termsOfUseConsent) {
+    if (!this.termsOfUseConsent && termsOfUseConsent) {
+      this.getTermsOfUseConsentDates().add(Calendar.getInstance());
+    }
     this.termsOfUseConsent = termsOfUseConsent;
   }
 
@@ -391,4 +405,12 @@ public class User implements Serializable {
     this.connectedToLdap = connectedToLdap;
   }
 
+  public Set<Calendar> getTermsOfUseConsentDates() {
+    return termsOfUseConsentDates;
+  }
+
+  public void setTermsOfUseConsentDates(Set<Calendar> termsOfUseConsentDates) {
+    this.termsOfUseConsentDates = termsOfUseConsentDates;
+  }
+
 }
diff --git a/persist/src/main/resources/db/migration/12.1.0~alpha.0/V12.1.0_20180802__user_terms_of_use_consent_stores_timestamp.sql b/persist/src/main/resources/db/migration/12.1.0~alpha.0/V12.1.0_20180802__user_terms_of_use_consent_stores_timestamp.sql
new file mode 100644
index 0000000000..e15229a4ab
--- /dev/null
+++ b/persist/src/main/resources/db/migration/12.1.0~alpha.0/V12.1.0_20180802__user_terms_of_use_consent_stores_timestamp.sql
@@ -0,0 +1,10 @@
+-- user account stores info about timestamp of terms of service acceptance 
+create table user_terms_of_use_consent (                                                                                            
+	user_iddb integer not null,
+	date timestamp without time zone,constraint user_terms_of_use_consent_user_fk foreign key (user_iddb)
+	references public.user_table (iddb) match simple
+	on update cascade on delete cascade
+);
+
+-- former acceptance is marked as from today
+insert into user_terms_of_use_consent (date, user_iddb)  (select now(), iddb from user_table where terms_of_use_consent = true);
-- 
GitLab