diff --git a/Model/lib/conifer/roles/conifer/templates/WDK/model-config.xml.j2 b/Model/lib/conifer/roles/conifer/templates/WDK/model-config.xml.j2
index 3cd45abc51..41fc61bba5 100644
--- a/Model/lib/conifer/roles/conifer/templates/WDK/model-config.xml.j2
+++ b/Model/lib/conifer/roles/conifer/templates/WDK/model-config.xml.j2
@@ -145,49 +145,6 @@ site_vars file: {{ site_vars }}
{% endif -%}
/>
-
-
-
-
-
-
-
-
-
-
-
{% if modelconfig_userDatasetStoreConfig is defined -%}
{{ modelconfig_userDatasetStoreConfig|indent }}
{% endif -%}
diff --git a/Model/lib/rng/wdkModel-config.rng b/Model/lib/rng/wdkModel-config.rng
index e3fde44be3..e9d5e48b59 100644
--- a/Model/lib/rng/wdkModel-config.rng
+++ b/Model/lib/rng/wdkModel-config.rng
@@ -94,39 +94,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Model/pom.xml b/Model/pom.xml
index af5da321e9..14c53f6244 100644
--- a/Model/pom.xml
+++ b/Model/pom.xml
@@ -77,17 +77,22 @@
org.gusdb
- fgputil-accountdb
+ fgputil-server
org.gusdb
- fgputil-server
+ fgputil-db
org.gusdb
- fgputil-db
+ oauth2-client
+
+
+
+ com.github.ben-manes.caffeine
+ caffeine
@@ -115,17 +120,6 @@
jersey-container-grizzly2-http
-
- io.jsonwebtoken
- jjwt
-
-
- com.fasterxml.jackson.core
- jackson-databind
-
-
-
-
javax.mail
mail
diff --git a/Model/src/main/java/org/gusdb/wdk/cache/TemporaryUserDataStore.java b/Model/src/main/java/org/gusdb/wdk/cache/TemporaryUserDataStore.java
new file mode 100644
index 0000000000..5ca37b68e3
--- /dev/null
+++ b/Model/src/main/java/org/gusdb/wdk/cache/TemporaryUserDataStore.java
@@ -0,0 +1,85 @@
+package org.gusdb.wdk.cache;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.log4j.Logger;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.RemovalListener;
+import com.github.benmanes.caffeine.cache.stats.CacheStats;
+
+/**
+ * Manages a map of user-scoped short-term information. Traditionally,
+ * this data was stored in the user's session object; instead, we store
+ * it now in a userId-keyed map, whose values time out some duration
+ * after last access (currently 60 minutes). If instance() is called
+ * within the application, shutDown() should also be called to clean
+ * up the expiration thread threadpool.
+ */
+public class TemporaryUserDataStore {
+
+ private static final Logger LOG = Logger.getLogger(TemporaryUserDataStore.class);
+
+ public static class TemporaryUserData extends ConcurrentHashMap {
+
+ private final TemporaryUserDataStore _parent;
+ private final Long _owner;
+
+ private TemporaryUserData(TemporaryUserDataStore parent, Long owner) {
+ _parent = parent;
+ _owner = owner;
+ }
+
+ public void invalidate() {
+ _parent.remove(_owner);
+ }
+
+ }
+
+ // singleton pattern
+ private static TemporaryUserDataStore _instance;
+
+ public static synchronized TemporaryUserDataStore instance() {
+ return _instance == null ? (_instance = new TemporaryUserDataStore()) : _instance;
+ }
+
+ public static synchronized void shutDown() {
+ if (_instance != null)
+ _instance._threadPool.shutdown();
+ _instance = null;
+ }
+
+ private static final RemovalListener> LISTENER =
+ (k,v,cause) -> LOG.info("User " + k + "'s temporary user data store has expired with " + v.size() + " entries; Reason: " + cause);
+
+ private final ExecutorService _threadPool;
+ private final Cache _data;
+
+ private TemporaryUserDataStore() {
+ _threadPool = Executors.newCachedThreadPool();
+ _data = Caffeine.newBuilder()
+ .executor(_threadPool)
+ .recordStats()
+ .removalListener(LISTENER)
+ .expireAfterAccess(60, TimeUnit.MINUTES)
+ .build();
+ }
+
+ public TemporaryUserData get(Long userId) {
+ return _data.get(userId, id -> new TemporaryUserData(this, id));
+ }
+
+ public void remove(Long userId) {
+ _data.invalidate(userId);
+ }
+
+ public CacheStats getStats() {
+ return _data.stats();
+ }
+
+}
diff --git a/Model/src/main/java/org/gusdb/wdk/controller/WdkInitializer.java b/Model/src/main/java/org/gusdb/wdk/controller/WdkInitializer.java
index 245a95ea82..69b5550736 100644
--- a/Model/src/main/java/org/gusdb/wdk/controller/WdkInitializer.java
+++ b/Model/src/main/java/org/gusdb/wdk/controller/WdkInitializer.java
@@ -6,6 +6,7 @@
import org.gusdb.fgputil.logging.ThreadLocalLoggingVars;
import org.gusdb.fgputil.runtime.GusHome;
import org.gusdb.fgputil.web.ApplicationContext;
+import org.gusdb.wdk.cache.TemporaryUserDataStore;
import org.gusdb.wdk.model.ThreadMonitor;
import org.gusdb.wdk.model.Utilities;
import org.gusdb.wdk.model.WdkModel;
@@ -77,6 +78,9 @@ public static void terminateWdk(ApplicationContext applicationScope) {
// shut down thread monitor
ThreadMonitor.shutDown();
+ // shut down TemporaryUserData threadpool
+ TemporaryUserDataStore.shutDown();
+
WdkModel wdkModel = getWdkModel(applicationScope);
if (wdkModel != null) {
// insulate in case model never properly loaded
diff --git a/Model/src/main/java/org/gusdb/wdk/controller/filter/CheckLoginFilterShared.java b/Model/src/main/java/org/gusdb/wdk/controller/filter/CheckLoginFilterShared.java
deleted file mode 100644
index 529c9ae58b..0000000000
--- a/Model/src/main/java/org/gusdb/wdk/controller/filter/CheckLoginFilterShared.java
+++ /dev/null
@@ -1,185 +0,0 @@
-package org.gusdb.wdk.controller.filter;
-
-import java.util.Optional;
-
-import org.apache.log4j.Logger;
-import org.gusdb.fgputil.Tuples.ThreeTuple;
-import org.gusdb.fgputil.events.Events;
-import org.gusdb.fgputil.web.CookieBuilder;
-import org.gusdb.fgputil.web.LoginCookieFactory;
-import org.gusdb.fgputil.web.LoginCookieFactory.LoginCookieParts;
-import org.gusdb.fgputil.web.SessionProxy;
-import org.gusdb.wdk.events.NewUserEvent;
-import org.gusdb.wdk.model.Utilities;
-import org.gusdb.wdk.model.WdkModel;
-import org.gusdb.wdk.model.WdkRuntimeException;
-import org.gusdb.wdk.model.user.UnregisteredUser.UnregisteredUserType;
-
-import io.prometheus.client.Counter;
-
-import org.gusdb.wdk.model.user.User;
-import org.gusdb.wdk.model.user.UserFactory;
-
-public class CheckLoginFilterShared {
-
- private static final Logger LOG = Logger.getLogger(CheckLoginFilterShared.class);
-
- private static final Counter GUEST_CREATION_COUNTER = Counter.build()
- .name("wdk_guest_creation_count")
- .help("Number of guest users created by WDK services")
- .register();
-
- private enum CurrentState {
-
- REGISTERED_USER_MATCHING_COOKIE, // 1. registered user, matching wdk cookie = no action
- REGISTERED_USER_BAD_COOKIE, // 2. registered user, unmatching, invalid, or missing wdk cookie = send expired cookie, new guest
- GUEST_USER_COOKIE_PRESENT, // 3. guest user, any wdk cookie = send expired cookie, keep guest
- GUEST_USER_COOKIE_MISSING, // 4. guest user, missing wdk cookie = no action
- NO_USER_VALID_COOKIE, // 5. no user, valid wdk cookie = log user in, but do not send updated cookie, since doing so is a bug for GBrowse
- NO_USER_INVALID_COOKIE, // 6. no user, invalid wdk cookie = send expired cookie, new guest
- NO_USER_MISSING_COOKIE; // 7. no user, missing wdk cookie = new guest
-
- public boolean requiresAction() {
- return !equals(REGISTERED_USER_MATCHING_COOKIE) &&
- !equals(GUEST_USER_COOKIE_MISSING);
- }
-
- public static CurrentState calculateState(
- boolean userPresent,
- boolean isGuestUser,
- boolean cookiePresent,
- boolean cookieValid,
- boolean cookieMatches) {
- return
- (userPresent ?
- // user is present cases
- (isGuestUser ?
- // guest user cases
- (cookiePresent ? GUEST_USER_COOKIE_PRESENT : GUEST_USER_COOKIE_MISSING) :
- // logged user cases
- (cookieMatches ? REGISTERED_USER_MATCHING_COOKIE : REGISTERED_USER_BAD_COOKIE)) :
- // no user present cases
- (cookiePresent ?
- // cookie but no user
- (cookieValid ? NO_USER_VALID_COOKIE : NO_USER_INVALID_COOKIE) :
- // no cookie, no user
- NO_USER_MISSING_COOKIE));
- }
- }
-
- private static class StateBundle extends ThreeTuple {
-
- public StateBundle(CurrentState state, User sessionUser, String cookieEmail) {
- super(state, sessionUser, cookieEmail);
- }
-
- public CurrentState getCurrentState() { return getFirst(); }
- public User getSessionUser() { return getSecond(); }
- public String getCookieEmail() { return getThird(); }
-
- }
-
- public static Optional calculateUserActions(
- Optional currentCookie,
- WdkModel wdkModel,
- SessionProxy session,
- String requestPath) {
-
- UserFactory userFactory = wdkModel.getUserFactory();
-
- // three-tuple is: caseNumber, sessionUser, cookieEmail
- StateBundle stateBundle = calculateCurrentState(wdkModel, session, currentCookie);
-
- // only enter synchronized block if action is required
- // (i.e. a new user must be added to the session or a logout cookie returned
- if (stateBundle.getCurrentState().requiresAction()) {
-
- // since action cases require creation of a user and assignment on session, synchronize on session
- synchronized(session.getUnderlyingSession()) { // must sync on shared object
-
- // recalculate in case something changed outside the synchronized block
- stateBundle = calculateCurrentState(wdkModel, session, currentCookie);
-
- try {
- // determine actions based on state
- CookieBuilder cookieToSend = null;
- User userToSet = null;
- switch (stateBundle.getCurrentState()) {
- case REGISTERED_USER_BAD_COOKIE:
- cookieToSend = LoginCookieFactory.createLogoutCookie();
- userToSet = createGuest(requestPath, userFactory);
- break;
- case GUEST_USER_COOKIE_PRESENT:
- cookieToSend = LoginCookieFactory.createLogoutCookie();
- // guest user present in session is sufficient
- break;
- case NO_USER_VALID_COOKIE:
- // do not want to update max age on cookie since we have no way to tell GBrowse to also update
- userToSet = userFactory.getUserByEmail(stateBundle.getCookieEmail());
- break;
- case NO_USER_INVALID_COOKIE:
- cookieToSend = LoginCookieFactory.createLogoutCookie();
- userToSet = createGuest(requestPath, userFactory);
- break;
- case NO_USER_MISSING_COOKIE:
- // no cookie necessary
- userToSet = createGuest(requestPath, userFactory);
- break;
- default:
- // other cases require no action
- break;
- }
-
- // take action as needed
- if (userToSet != null) {
- session.setAttribute(Utilities.WDK_USER_KEY, userToSet);
- Events.triggerAndWait(new NewUserEvent(userToSet, stateBundle.getSessionUser(), session),
- new WdkRuntimeException("Unable to complete WDK user assignement."));
- }
- return Optional.ofNullable(cookieToSend);
- }
- catch (Exception ex) {
- LOG.error("Caught exception while checking login cookie", ex);
- return Optional.of(LoginCookieFactory.createLogoutCookie());
- }
- }
- }
- return Optional.empty();
- }
-
- private static User createGuest(String requestPath, UserFactory userFactory) {
- User guest = userFactory.createUnregistedUser(UnregisteredUserType.GUEST);
- LOG.info("Created new guest user [" + guest.getUserId() + "] for request to path: /" + requestPath);
- GUEST_CREATION_COUNTER.inc();
- return guest;
- }
-
- private static StateBundle calculateCurrentState(WdkModel wdkModel, SessionProxy session, Optional loginCookie) {
-
- // get the current user in session and determine type
- User wdkUser = (User)session.getAttribute(Utilities.WDK_USER_KEY);
- boolean userPresent = (wdkUser != null);
- boolean isGuestUser = (userPresent ? wdkUser.isGuest() : false);
-
- // figure out what's going on with the cookie
- boolean cookiePresent = loginCookie.isPresent();
- LoginCookieParts cookieParts = null;
- boolean cookieValid = false, cookieMatches = false;
- try {
- if (cookiePresent) {
- LoginCookieFactory auth = new LoginCookieFactory(wdkModel.getModelConfig().getSecretKey());
- cookieParts = LoginCookieFactory.parseCookieValue(loginCookie.get().getValue());
- cookieValid = auth.isValidCookie(cookieParts);
- cookieMatches = cookieValid ? (wdkUser != null && cookieParts.getUsername().equals(wdkUser.getEmail())) : false;
- }
- }
- catch (IllegalArgumentException e) {
- /* negative values already set */
- }
-
- CurrentState state = CurrentState.calculateState(userPresent, isGuestUser, cookiePresent, cookieValid, cookieMatches);
-
- return new StateBundle(state, wdkUser, cookieValid ? cookieParts.getUsername() : null);
- }
-
-}
diff --git a/Model/src/main/java/org/gusdb/wdk/errors/ErrorContext.java b/Model/src/main/java/org/gusdb/wdk/errors/ErrorContext.java
index fbed76f373..58bc2ee09e 100644
--- a/Model/src/main/java/org/gusdb/wdk/errors/ErrorContext.java
+++ b/Model/src/main/java/org/gusdb/wdk/errors/ErrorContext.java
@@ -24,19 +24,16 @@ public static enum ErrorLocation {
private final WdkModel _wdkModel;
private final RequestSnapshot _requestData;
private final ReadOnlyMap _requestAttributeMap;
- private final ReadOnlyMap _sessionAttributeMap;
private final ErrorLocation _errorLocation;
private final ThreadContextBundle _mdcBundle;
private final String _logMarker;
private final Date _date;
public ErrorContext(WdkModel wdkModel, RequestSnapshot requestData,
- ReadOnlyMap sessionAttributeMap,
ErrorLocation errorLocation) {
_wdkModel = wdkModel;
_requestData = requestData;
_requestAttributeMap = requestData.getAttributes();
- _sessionAttributeMap = sessionAttributeMap;
_errorLocation = errorLocation;
_mdcBundle = ThreadLocalLoggingVars.getThreadContextBundle();
_logMarker = UUID.randomUUID().toString();
@@ -46,7 +43,6 @@ public ErrorContext(WdkModel wdkModel, RequestSnapshot requestData,
public WdkModel getWdkModel() { return _wdkModel; }
public RequestSnapshot getRequestData() { return _requestData; }
public ReadOnlyMap getRequestAttributeMap() { return _requestAttributeMap; }
- public ReadOnlyMap getSessionAttributeMap() { return _sessionAttributeMap; }
/**
* A site is considered monitored if the administrator email from adminEmail in the model-config.xml has content.
diff --git a/Model/src/main/java/org/gusdb/wdk/events/NewUserEvent.java b/Model/src/main/java/org/gusdb/wdk/events/NewUserEvent.java
deleted file mode 100644
index c572428ed4..0000000000
--- a/Model/src/main/java/org/gusdb/wdk/events/NewUserEvent.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.gusdb.wdk.events;
-
-import org.gusdb.fgputil.events.Event;
-import org.gusdb.fgputil.web.SessionProxy;
-import org.gusdb.wdk.model.user.User;
-
-public class NewUserEvent extends Event {
-
- private final User _newUser;
- private final User _oldUser;
- private final SessionProxy _session;
-
- public NewUserEvent(User newUser, User oldUser, SessionProxy session) {
- _newUser = newUser;
- _oldUser = oldUser;
- _session = session;
- }
-
- public User getNewUser() {
- return _newUser;
- }
-
- public User getOldUser() {
- return _oldUser;
- }
-
- public SessionProxy getSession() {
- return _session;
- }
-}
diff --git a/Model/src/main/java/org/gusdb/wdk/events/UserProfileUpdateEvent.java b/Model/src/main/java/org/gusdb/wdk/events/UserProfileUpdateEvent.java
index cd9229fb95..2116e36384 100644
--- a/Model/src/main/java/org/gusdb/wdk/events/UserProfileUpdateEvent.java
+++ b/Model/src/main/java/org/gusdb/wdk/events/UserProfileUpdateEvent.java
@@ -1,27 +1,27 @@
package org.gusdb.wdk.events;
-import org.gusdb.fgputil.accountdb.UserProfile;
import org.gusdb.fgputil.events.Event;
import org.gusdb.wdk.model.WdkModel;
+import org.gusdb.wdk.model.user.User;
public class UserProfileUpdateEvent extends Event {
- private final UserProfile _oldProfile;
- private final UserProfile _newProfile;
+ private final User _oldUser;
+ private final User _newUser;
private final WdkModel _wdkModel;
- public UserProfileUpdateEvent(UserProfile oldProfile, UserProfile newProfile, WdkModel wdkModel) {
- _oldProfile = oldProfile;
- _newProfile = newProfile;
+ public UserProfileUpdateEvent(User oldUser, User newUser, WdkModel wdkModel) {
+ _oldUser = oldUser;
+ _newUser = newUser;
_wdkModel = wdkModel;
}
- public UserProfile getOldProfile() {
- return _oldProfile;
+ public User getOldUser() {
+ return _oldUser;
}
- public UserProfile getNewProfile() {
- return _newProfile;
+ public User getNewUser() {
+ return _newUser;
}
public WdkModel getWdkModel() {
diff --git a/Model/src/main/java/org/gusdb/wdk/jmx/mbeans/ModelConfig.java b/Model/src/main/java/org/gusdb/wdk/jmx/mbeans/ModelConfig.java
index d4ce7a0a72..b47b5abac6 100644
--- a/Model/src/main/java/org/gusdb/wdk/jmx/mbeans/ModelConfig.java
+++ b/Model/src/main/java/org/gusdb/wdk/jmx/mbeans/ModelConfig.java
@@ -24,7 +24,6 @@ protected void init() {
org.gusdb.wdk.model.config.QueryMonitor queryMonitor = modelConfig.getQueryMonitor();
org.gusdb.wdk.model.config.ModelConfigUserDB modelConfigUserDB = modelConfig.getUserDB();
org.gusdb.wdk.model.config.ModelConfigAppDB modelConfigAppDB = modelConfig.getAppDB();
- org.gusdb.wdk.model.config.ModelConfigAccountDB modelConfigAccountDB = modelConfig.getAccountDB();
org.gusdb.wdk.model.config.ModelConfigUserDatasetStore
modelConfigUserDatasetStore = modelConfig.getUserDatasetStoreConfig();
@@ -32,7 +31,6 @@ protected void init() {
setValuesFromGetters("queryMonitor", queryMonitor);
setValuesFromGetters("userDb", modelConfigUserDB);
setValuesFromGetters("appDb", modelConfigAppDB);
- setValuesFromGetters("accountDb", modelConfigAccountDB);
setValuesFromGetters("userDatasetStore", modelConfigUserDatasetStore);
}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/ModelXmlParser.java b/Model/src/main/java/org/gusdb/wdk/model/ModelXmlParser.java
index 34c02fc6ad..cdfff9bf1f 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/ModelXmlParser.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/ModelXmlParser.java
@@ -436,9 +436,6 @@ private Map loadProperties(String projectId, URL modelPropURL, M
if (!propMap.containsKey("USER_SCHEMA")) {
propMap.put("USER_SCHEMA", config.getUserDB().getUserSchema());
}
- if (!propMap.containsKey("ACCT_SCHEMA")) {
- propMap.put("ACCT_SCHEMA", config.getAccountDB().getAccountSchema());
- }
return propMap;
}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/Utilities.java b/Model/src/main/java/org/gusdb/wdk/model/Utilities.java
index c5c22e1dc5..921c68038f 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/Utilities.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/Utilities.java
@@ -1,17 +1,11 @@
package org.gusdb.wdk.model;
-import org.apache.log4j.Logger;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import javax.activation.DataHandler;
-import javax.mail.*;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeBodyPart;
-import javax.mail.internet.MimeMessage;
-import javax.mail.internet.MimeMultipart;
-import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.sql.Clob;
import java.sql.SQLException;
import java.util.Date;
@@ -22,6 +16,20 @@
import java.util.regex.Pattern;
import java.util.stream.Stream;
+import javax.activation.DataHandler;
+import javax.mail.Address;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import org.apache.log4j.Logger;
+
/**
* This class provided constants that are shared among different WDK model
* classes. Furthermore, it also provides utility functions to send
@@ -31,16 +39,10 @@
*/
public class Utilities {
- private static final Logger logger = Logger.getLogger(Utilities.class);
+ private static final Logger LOG = Logger.getLogger(Utilities.class);
public static final int TRUNCATE_DEFAULT = 100;
- /**
- * The maximum size for parameter values that will be displayed in thr URL as
- * plain values
- */
- public static final int MAX_PARAM_VALUE_SIZE = 100;
-
/**
* The maximum number of attributes used in sorting an answer
*/
@@ -56,10 +58,6 @@ public class Utilities {
*/
public static final String SYSTEM_PROPERTY_GUS_HOME = "GUS_HOME";
- public static final int MAXIMUM_RECORD_INSTANCES = 10000;
-
- public static final int DEFAULT_PAGE_SIZE = 20;
-
public static final int DEFAULT_SUMMARY_ATTRIBUTE_SIZE = 6;
public static final int DEFAULT_WEIGHT = 10;
@@ -71,8 +69,6 @@ public class Utilities {
*/
public static final int MAX_PK_COLUMN_COUNT = 4;
- public static final int MAX_PK_COLUMN_VALUE_SIZE = 1999;
-
public static final String INTERNAL_PARAM_SET = "InternalParams";
public static final String INTERNAL_QUERY_SET = "InternalQueries";
public static final String INTERNAL_QUESTION_SET = "InternalQuestions";
@@ -99,12 +95,12 @@ public class Utilities {
public static final String COLUMN_DIVIDER = ",";
public static final String WDK_MODEL_KEY = "wdk_model";
- public static final String WDK_MODEL_BEAN_KEY = "wdkModel"; // cannot change this because of JSPs
public static final String WDK_USER_KEY = "wdk_user";
- public static final String WDK_USER_BEAN_KEY = "wdkUser";
+ public static final String BEARER_TOKEN_KEY = "bearer-token";
public static final String WDK_SERVICE_ENDPOINT_KEY = "wdkServiceEndpoint";
+
/*
* Inner class to act as a JAF DataSource to send HTML e-mail content
*/
@@ -164,22 +160,6 @@ public static String[] toArray(String data) {
return data.trim().split("\\s+");
}
- public static String fromArray(String[] data) {
- return fromArray(data, ",");
- }
-
- public static String fromArray(String[] data, String delimiter) {
- if (data == null)
- return null;
- StringBuffer sb = new StringBuffer();
- for (String value : data) {
- if (sb.length() > 0)
- sb.append(delimiter);
- sb.append(value);
- }
- return sb.toString();
- }
-
public static String parseValue(Object objValue) {
if (objValue == null)
return null;
@@ -197,21 +177,6 @@ private static String parseClob(Clob clobValue) {
}
}
- public static String[][] convertContent(String content) throws JSONException {
- JSONArray jsResult = new JSONArray(content);
- JSONArray jsRow = (JSONArray) jsResult.get(0);
- String[][] result = new String[jsResult.length()][jsRow.length()];
- for (int row = 0; row < result.length; row++) {
- jsRow = (JSONArray) jsResult.get(row);
- for (int col = 0; col < result[row].length; col++) {
- Object cell = jsRow.get(col);
- result[row][col] = (cell == null || cell == JSONObject.NULL) ? null
- : cell.toString();
- }
- }
- return result;
- }
-
// sendEmail() method overloading: different number of parameters (max 8), different type for attachments
// 7 parameters (missing bcc, datahandlers instead of attachments)
@@ -258,7 +223,7 @@ public static void sendEmail(String smtpServer, String sendTos, String reply,
String subject, String content, String ccAddresses, String bccAddresses,
Attachment[] attachments) throws WdkModelException {
- logger.debug("Sending message to: " + sendTos + ", bcc to: " + bccAddresses +
+ LOG.debug("Sending message to: " + sendTos + ", bcc to: " + bccAddresses +
",reply: " + reply + ", using SMPT: " + smtpServer);
// create properties and get the session
@@ -317,7 +282,6 @@ public static void sendEmail(String smtpServer, String sendTos, String reply,
}
}
-
public static byte[] readFile(File file) throws IOException {
byte[] buffer = new byte[(int) file.length()];
InputStream stream = new FileInputStream(file);
@@ -326,18 +290,6 @@ public static byte[] readFile(File file) throws IOException {
return buffer;
}
- public static int createHashFromValueMap(Map map) {
- StringBuilder buffer = new StringBuilder("{");
- for (S key : map.keySet()) {
- if (buffer.length() > 1) {
- buffer.append(";");
- }
- buffer.append(key).append(":").append(map.get(key));
- }
- buffer.append("}");
- return buffer.toString().hashCode();
- }
-
public static Map parseSortList(String sortList) throws WdkModelException {
Map sortingMap = new LinkedHashMap();
String[] attrCombines = sortList.split(",");
diff --git a/Model/src/main/java/org/gusdb/wdk/model/WdkModel.java b/Model/src/main/java/org/gusdb/wdk/model/WdkModel.java
index 444a423e57..5bed180490 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/WdkModel.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/WdkModel.java
@@ -23,7 +23,6 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import org.apache.log4j.Logger;
@@ -38,13 +37,13 @@
import org.gusdb.fgputil.functional.FunctionalInterfaces.SupplierWithException;
import org.gusdb.fgputil.runtime.InstanceManager;
import org.gusdb.fgputil.runtime.Manageable;
+import org.gusdb.wdk.model.user.User;
import org.gusdb.wdk.model.analysis.StepAnalysis;
import org.gusdb.wdk.model.analysis.StepAnalysisPlugins;
import org.gusdb.wdk.model.answer.single.SingleRecordQuestion;
import org.gusdb.wdk.model.columntool.ColumnToolBundleMap;
import org.gusdb.wdk.model.columntool.DefaultColumnToolBundleRef;
import org.gusdb.wdk.model.config.ModelConfig;
-import org.gusdb.wdk.model.config.ModelConfigAccountDB;
import org.gusdb.wdk.model.config.ModelConfigAppDB;
import org.gusdb.wdk.model.config.ModelConfigUserDB;
import org.gusdb.wdk.model.config.ModelConfigUserDatasetStore;
@@ -69,8 +68,6 @@
import org.gusdb.wdk.model.user.BasketFactory;
import org.gusdb.wdk.model.user.FavoriteFactory;
import org.gusdb.wdk.model.user.StepFactory;
-import org.gusdb.wdk.model.user.UnregisteredUser.UnregisteredUserType;
-import org.gusdb.wdk.model.user.User;
import org.gusdb.wdk.model.user.UserFactory;
import org.gusdb.wdk.model.user.analysis.StepAnalysisFactory;
import org.gusdb.wdk.model.user.analysis.StepAnalysisFactoryImpl;
@@ -114,10 +111,8 @@ public static WdkModel construct(String projectId, String gusHome) throws WdkMod
private String _projectId;
private long _startupTime;
-
private DatabaseInstance appDb;
private DatabaseInstance userDb;
- private DatabaseInstance accountDb;
private Optional _userDatasetStore;
@@ -179,7 +174,6 @@ public static WdkModel construct(String projectId, String gusHome) throws WdkMod
private File xmlDataDir;
- private UserFactory userFactory;
private StepFactory stepFactory;
private DatasetFactory datasetFactory;
private BasketFactory basketFactory;
@@ -204,7 +198,6 @@ public static WdkModel construct(String projectId, String gusHome) throws WdkMod
private ColumnToolBundleMap columnToolBundleMap = new ColumnToolBundleMap();
private String defaultColumnToolBundleRef;
- private ReentrantLock systemUserLock = new ReentrantLock();
private User systemUser;
private String buildNumber;
@@ -552,14 +545,12 @@ public void configure(ModelConfig modelConfig) throws WdkModelException {
ModelConfigAppDB appDbConfig = modelConfig.getAppDB();
ModelConfigUserDB userDbConfig = modelConfig.getUserDB();
- ModelConfigAccountDB accountDbConfig = modelConfig.getAccountDB();
ModelConfigUserDatasetStore udsConfig = modelConfig.getUserDatasetStoreConfig();
QueryLogger.initialize(modelConfig.getQueryMonitor());
appDb = new DatabaseInstance(appDbConfig, DB_INSTANCE_APP, true);
userDb = new DatabaseInstance(userDbConfig, DB_INSTANCE_USER, true);
- accountDb = new DatabaseInstance(accountDbConfig, DB_INSTANCE_ACCOUNT, true);
// set true to avoid a broken dev irods at build time
if ( udsConfig == null ) {
@@ -569,7 +560,6 @@ public void configure(ModelConfig modelConfig) throws WdkModelException {
_userDatasetStore = Optional.of(udsConfig.getUserDatasetStore(modelConfig.getWdkTempDir()));
}
- userFactory = new UserFactory(this);
stepFactory = new StepFactory(this);
datasetFactory = new DatasetFactory(this);
basketFactory = new BasketFactory(this);
@@ -600,6 +590,8 @@ public void configure(ModelConfig modelConfig) throws WdkModelException {
new UnconfiguredStepAnalysisFactory(this) :
new StepAnalysisFactoryImpl(this));
+ systemUser = new UserFactory(this).createUnregisteredUser().getSecond();
+
LOG.info("WDK Model configured.");
}
@@ -662,7 +654,6 @@ public void close() {
stepAnalysisFactory.shutDown();
releaseDb(appDb);
releaseDb(userDb);
- releaseDb(accountDb);
Events.shutDown();
managedCloseables.close();
LOG.info("WDK Model resources released.");
@@ -702,12 +693,8 @@ public DatabaseInstance getUserDb() {
return userDb;
}
- public DatabaseInstance getAccountDb() {
- return accountDb;
- }
-
public UserFactory getUserFactory() {
- return userFactory;
+ return new UserFactory(this);
}
public StepFactory getStepFactory() {
@@ -1361,17 +1348,6 @@ public String queryParamDisplayName(String paramName) {
}
public User getSystemUser() {
- if (systemUser == null) {
- try {
- systemUserLock.lock();
- if (systemUser == null) {
- systemUser = userFactory.createUnregistedUser(UnregisteredUserType.SYSTEM);
- }
- }
- finally {
- systemUserLock.unlock();
- }
- }
return systemUser;
}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/WdkSqlScriptRunner.java b/Model/src/main/java/org/gusdb/wdk/model/WdkSqlScriptRunner.java
index fc37486c44..8ee52be404 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/WdkSqlScriptRunner.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/WdkSqlScriptRunner.java
@@ -22,11 +22,11 @@
*/
public class WdkSqlScriptRunner {
- private static enum DbType { APP, USER, ACCT }
+ private static enum DbType { APP, USER }
public static void main(String[] args) {
if (args.length != 3 && args.length != 5) {
- System.err.println("USAGE: fgpJava " + WdkSqlScriptRunner.class.getName() + " [APP|USER|ACCT] [ ]");
+ System.err.println("USAGE: fgpJava " + WdkSqlScriptRunner.class.getName() + " [APP|USER] [ ]");
System.exit(1);
}
BufferedReader sqlReader = null;
@@ -46,7 +46,6 @@ public static void main(String[] args) {
ModelConfigDB dbConfig = (
whichDb.equals(DbType.APP) ? modelConf.getAppDB() :
whichDb.equals(DbType.USER) ? modelConf.getUserDB() :
- whichDb.equals(DbType.ACCT) ? modelConf.getAccountDB() :
null ); // should never happen; value already validated
db = new DatabaseInstance(dbConfig);
diff --git a/Model/src/main/java/org/gusdb/wdk/model/answer/AnswerValue.java b/Model/src/main/java/org/gusdb/wdk/model/answer/AnswerValue.java
index 3024bda4f6..7974eb99f4 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/answer/AnswerValue.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/answer/AnswerValue.java
@@ -53,9 +53,9 @@
import org.gusdb.wdk.model.record.Field;
import org.gusdb.wdk.model.record.PrimaryKeyDefinition;
import org.gusdb.wdk.model.record.PrimaryKeyIterator;
-import org.gusdb.wdk.model.record.ResultSetPrimaryKeyIterator;
import org.gusdb.wdk.model.record.RecordClass;
import org.gusdb.wdk.model.record.RecordInstance;
+import org.gusdb.wdk.model.record.ResultSetPrimaryKeyIterator;
import org.gusdb.wdk.model.record.TableField;
import org.gusdb.wdk.model.record.attribute.AttributeField;
import org.gusdb.wdk.model.record.attribute.ColumnAttributeField;
diff --git a/Model/src/main/java/org/gusdb/wdk/model/answer/TransformUtil.java b/Model/src/main/java/org/gusdb/wdk/model/answer/TransformUtil.java
index 88e4ad740c..bbd855c512 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/answer/TransformUtil.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/answer/TransformUtil.java
@@ -12,10 +12,10 @@
import org.gusdb.wdk.model.query.spec.QueryInstanceSpec;
import org.gusdb.wdk.model.question.Question;
import org.gusdb.wdk.model.user.Step;
+import org.gusdb.wdk.model.user.StepContainer.ListStepContainer;
import org.gusdb.wdk.model.user.Strategy;
import org.gusdb.wdk.model.user.User;
import org.gusdb.wdk.model.user.UserCache;
-import org.gusdb.wdk.model.user.StepContainer.ListStepContainer;
/**
* Provides a utility to use transform questions to convert an answer value of
diff --git a/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfig.java b/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfig.java
index 7d70842d8b..af2b74436f 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfig.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfig.java
@@ -11,6 +11,8 @@
import org.gusdb.fgputil.FormatUtil;
import org.gusdb.fgputil.IoUtil;
import org.gusdb.fgputil.Named.NamedObject;
+import org.gusdb.oauth2.client.KeyStoreTrustManager.KeyStoreConfig;
+import org.gusdb.oauth2.client.OAuthConfig;
/**
* An object representation of the {@code model-config.xml} file. It holds all the configuration information
@@ -18,7 +20,7 @@
*
* @author Jerric
*/
-public class ModelConfig implements OAuthConfig {
+public class ModelConfig implements OAuthConfig, KeyStoreConfig {
private static final Logger LOG = Logger.getLogger(ModelConfig.class);
@@ -69,7 +71,6 @@ public String getName() {
private final ModelConfigUserDB _userDB;
private final ModelConfigAppDB _appDB;
- private final ModelConfigAccountDB _accountDB;
private final ModelConfigUserDatasetStore _userDatasetStoreConfig;
@@ -81,6 +82,11 @@ public String getName() {
private final String _projectId;
private final Path _gusHome;
+ /**
+ * enable/disable weight feature in the steps. default enabled.
+ */
+ private final boolean _useWeights;
+
/**
* location of secret key file
*/
@@ -92,11 +98,6 @@ public String getName() {
*/
private String _secretKey;
- /**
- * enable/disable weight feature in the steps. default enabled.
- */
- private final boolean _useWeights;
-
/**
* default regex used by all the stringParams
*/
@@ -146,7 +147,7 @@ public String getName() {
public ModelConfig(String modelName, String projectId, Path gusHome, boolean caching, boolean useWeights,
String paramRegex, Optional secretKeyFile, Path wdkTempDir, String webServiceUrl, String assetsUrl,
String smtpServer, String supportEmail, List adminEmails, String emailSubject,
- String emailContent, ModelConfigUserDB userDB, ModelConfigAppDB appDB, ModelConfigAccountDB accountDB,
+ String emailContent, ModelConfigUserDB userDB, ModelConfigAppDB appDB,
ModelConfigUserDatasetStore userDatasetStoreConfig, QueryMonitor queryMonitor,
boolean monitorBlockedThreads, int blockedThreshold, AuthenticationMethod authenticationMethod,
String oauthUrl, String oauthClientId, String oauthClientSecret, String changePasswordUrl,
@@ -163,8 +164,8 @@ public ModelConfig(String modelName, String projectId, Path gusHome, boolean cac
_paramRegex = paramRegex;
// file locations
- _secretKeyFile = secretKeyFile;
_wdkTempDir = wdkTempDir;
+ _secretKeyFile = secretKeyFile;
// network locations
_webServiceUrl = webServiceUrl;
@@ -180,7 +181,6 @@ public ModelConfig(String modelName, String projectId, Path gusHome, boolean cac
// databases
_userDB = userDB;
_appDB = appDB;
- _accountDB = accountDB;
// user dataset config
_userDatasetStoreConfig = userDatasetStoreConfig;
@@ -293,13 +293,6 @@ public ModelConfigAppDB getAppDB() {
return _appDB;
}
- /**
- * @return the accountDB
- */
- public ModelConfigAccountDB getAccountDB() {
- return _accountDB;
- }
-
/**
* Returns a cached secret key, generated by encrypting the value in the
* configured secret key file. If the configured filename is null or the contents
diff --git a/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigAccountDB.java b/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigAccountDB.java
deleted file mode 100644
index 0307ff8e61..0000000000
--- a/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigAccountDB.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.gusdb.wdk.model.config;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.gusdb.fgputil.accountdb.UserPropertyName;
-import org.gusdb.fgputil.db.platform.DBPlatform;
-
-public class ModelConfigAccountDB extends ModelConfigDB {
-
- private String _accountSchema;
- private List _userPropertyNames = new ArrayList();
-
- public void setAccountSchema(String accountSchema) {
- _accountSchema = DBPlatform.normalizeSchema(accountSchema);
- }
-
- public String getAccountSchema() {
- return _accountSchema;
- }
-
- public void addUserPropertyName(UserPropertyName property) {
- _userPropertyNames.add(property);
- }
-
- public List getUserPropertyNames() {
- return _userPropertyNames;
- }
-}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigBuilder.java b/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigBuilder.java
index a94f09e3ba..ae414d5906 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigBuilder.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigBuilder.java
@@ -45,7 +45,6 @@ public class ModelConfigBuilder {
// databases
private ModelConfigUserDB _userDB;
private ModelConfigAppDB _appDB;
- private ModelConfigAccountDB _accountDB;
// user dataset config
private ModelConfigUserDatasetStore _userDatasetStoreConfig;
@@ -91,7 +90,6 @@ public ModelConfig build() throws WdkModelException {
assertNonNull("supportEmail", _supportEmail);
assertNonNull("userDb", _userDB);
assertNonNull("appDb", _appDB);
- assertNonNull("accountDb", _accountDB);
// TODO: should probably have a default stub for this to avoid NPEs
//assertNonNull("userDatasetStoreConfig", _userDatasetStoreConfig);
@@ -125,7 +123,6 @@ public ModelConfig build() throws WdkModelException {
// databases
_userDB,
_appDB,
- _accountDB,
// user dataset config
_userDatasetStoreConfig,
@@ -248,14 +245,6 @@ public void setAppDB(ModelConfigAppDB appDB) {
_appDB = appDB;
}
- /**
- * @param accountDB
- * the accountDB to set
- */
- public void setAccountDB(ModelConfigAccountDB accountDB) {
- _accountDB = accountDB;
- }
-
/**
* @param secretKeyFile
* the secretKeyFile to set
diff --git a/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigParser.java b/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigParser.java
index 874f876ca1..9a363d7f6e 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigParser.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/config/ModelConfigParser.java
@@ -4,7 +4,6 @@
import java.net.URL;
import org.apache.commons.digester3.Digester;
-import org.gusdb.fgputil.accountdb.UserPropertyName;
import org.gusdb.fgputil.xml.XmlParser;
import org.gusdb.fgputil.xml.XmlValidator;
import org.gusdb.wdk.model.WdkModelException;
@@ -63,10 +62,6 @@ private static Digester configureDigester() {
// load user db
configureNode(digester, "modelConfig/userDb", ModelConfigUserDB.class, "setUserDB");
- // load user db
- configureNode(digester, "modelConfig/accountDb", ModelConfigAccountDB.class, "setAccountDB");
- configureNode(digester, "modelConfig/accountDb/userProperty", UserPropertyName.class, "addUserPropertyName");
-
// userdatasetstore
configureNode(digester, "modelConfig/userDatasetStore", ModelConfigUserDatasetStore.class, "setUserDatasetStore");
configureNode(digester, "modelConfig/userDatasetStore/property", WdkModelText.class, "addProperty");
diff --git a/Model/src/main/java/org/gusdb/wdk/model/config/OAuthConfig.java b/Model/src/main/java/org/gusdb/wdk/model/config/OAuthConfig.java
deleted file mode 100644
index e57c757cd4..0000000000
--- a/Model/src/main/java/org/gusdb/wdk/model/config/OAuthConfig.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.gusdb.wdk.model.config;
-
-public interface OAuthConfig {
-
- /**
- * @return base URL of OAuth2 server to use for authentication
- */
- String getOauthUrl();
-
- /**
- * @return OAuth2 client ID to use for authentication
- */
- String getOauthClientId();
-
- /**
- * @return OAuth2 client secret to use for authentication
- */
- String getOauthClientSecret();
-
- /**
- * @return key store file containing acceptable SSL hosts/certs
- */
- String getKeyStoreFile();
-
- /**
- * @return pass phrase needed to access key store
- */
- String getKeyStorePassPhrase();
-}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/query/param/AbstractEnumParam.java b/Model/src/main/java/org/gusdb/wdk/model/query/param/AbstractEnumParam.java
index 0b26907dc3..dd65553168 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/query/param/AbstractEnumParam.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/query/param/AbstractEnumParam.java
@@ -5,7 +5,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
diff --git a/Model/src/main/java/org/gusdb/wdk/model/query/param/FilterParamNewHandler.java b/Model/src/main/java/org/gusdb/wdk/model/query/param/FilterParamNewHandler.java
index c76242921f..37147634f0 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/query/param/FilterParamNewHandler.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/query/param/FilterParamNewHandler.java
@@ -1,19 +1,23 @@
package org.gusdb.wdk.model.query.param;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
import org.gusdb.fgputil.EncryptionUtil;
import org.gusdb.fgputil.MapBuilder;
import org.gusdb.fgputil.validation.ValidObjectFactory.RunnableObj;
import org.gusdb.wdk.model.WdkModel;
import org.gusdb.wdk.model.WdkModelException;
-import org.gusdb.wdk.model.query.*;
+import org.gusdb.wdk.model.query.Column;
+import org.gusdb.wdk.model.query.Query;
+import org.gusdb.wdk.model.query.QueryInstance;
+import org.gusdb.wdk.model.query.QuerySet;
+import org.gusdb.wdk.model.query.SqlQuery;
import org.gusdb.wdk.model.query.spec.QueryInstanceSpec;
import org.gusdb.wdk.model.user.User;
import org.json.JSONException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
/**
* @author jerric
*/
diff --git a/Model/src/main/java/org/gusdb/wdk/model/query/param/FlatVocabParam.java b/Model/src/main/java/org/gusdb/wdk/model/query/param/FlatVocabParam.java
index 42ccde0263..e9752a5ebd 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/query/param/FlatVocabParam.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/query/param/FlatVocabParam.java
@@ -127,7 +127,7 @@ public EnumParamVocabInstance getVocabInstance(User user, Map de
try {
FlatVocabularyFetcher fetcher = new FlatVocabularyFetcher(user, this);
return (vocabQuery.isCacheable() ?
- CacheMgr.get().getVocabCache().getValue(fetcher.getCacheKey(dependedParamValues), fetcher) :
+ getCachedVocabInstance(fetcher, dependedParamValues) :
fetcher.fetchItem(dependedParamValues));
}
catch (ValueProductionException e) {
@@ -135,6 +135,14 @@ public EnumParamVocabInstance getVocabInstance(User user, Map de
}
}
+ private EnumParamVocabInstance getCachedVocabInstance(
+ FlatVocabularyFetcher fetcher,
+ Map dependedParamValues) throws ValueProductionException {
+ String cacheKey = fetcher.getCacheKey(dependedParamValues);
+ EnumParamVocabInstance vocab = CacheMgr.get().getVocabCache().getValue(cacheKey, fetcher);
+ return vocab;
+ }
+
@Override
public Param clone() {
return new FlatVocabParam(this);
diff --git a/Model/src/main/java/org/gusdb/wdk/model/record/attribute/DerivedAttributeField.java b/Model/src/main/java/org/gusdb/wdk/model/record/attribute/DerivedAttributeField.java
index a460f51864..da41e3e641 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/record/attribute/DerivedAttributeField.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/record/attribute/DerivedAttributeField.java
@@ -19,7 +19,6 @@
import org.gusdb.wdk.model.Utilities;
import org.gusdb.wdk.model.WdkModel;
import org.gusdb.wdk.model.WdkModelException;
-import org.gusdb.wdk.model.WdkModelText;
import org.gusdb.wdk.model.WdkUserException;
/**
diff --git a/Model/src/main/java/org/gusdb/wdk/model/test/ParamValuesFactory.java b/Model/src/main/java/org/gusdb/wdk/model/test/ParamValuesFactory.java
index 06f0e87326..61658146af 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/test/ParamValuesFactory.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/test/ParamValuesFactory.java
@@ -15,9 +15,9 @@
import org.gusdb.wdk.model.WdkModelException;
import org.gusdb.wdk.model.query.Query;
import org.gusdb.wdk.model.query.param.AbstractDependentParam;
+import org.gusdb.wdk.model.query.param.AbstractEnumParam.SelectMode;
import org.gusdb.wdk.model.query.param.Param;
import org.gusdb.wdk.model.query.param.ParamValuesSet;
-import org.gusdb.wdk.model.query.param.AbstractEnumParam.SelectMode;
import org.gusdb.wdk.model.user.User;
public class ParamValuesFactory {
diff --git a/Model/src/main/java/org/gusdb/wdk/model/test/QueryTester.java b/Model/src/main/java/org/gusdb/wdk/model/test/QueryTester.java
index 1d1210bd83..f03ae38d83 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/test/QueryTester.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/test/QueryTester.java
@@ -4,9 +4,9 @@
import java.util.List;
import java.util.Map;
-import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
diff --git a/Model/src/main/java/org/gusdb/wdk/model/test/RecordTester.java b/Model/src/main/java/org/gusdb/wdk/model/test/RecordTester.java
index ae5f34c53d..daf799317a 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/test/RecordTester.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/test/RecordTester.java
@@ -3,9 +3,9 @@
import java.util.LinkedHashMap;
import java.util.Map;
-import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
diff --git a/Model/src/main/java/org/gusdb/wdk/model/test/SummaryTester.java b/Model/src/main/java/org/gusdb/wdk/model/test/SummaryTester.java
index 132341d8e1..9eb1024d1c 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/test/SummaryTester.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/test/SummaryTester.java
@@ -10,9 +10,9 @@
import java.util.Optional;
import java.util.Properties;
-import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
diff --git a/Model/src/main/java/org/gusdb/wdk/model/test/sanity/tests/QuestionTest.java b/Model/src/main/java/org/gusdb/wdk/model/test/sanity/tests/QuestionTest.java
index 2a1b1d85c3..4c4153f124 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/test/sanity/tests/QuestionTest.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/test/sanity/tests/QuestionTest.java
@@ -10,9 +10,9 @@
import org.gusdb.wdk.model.question.Question;
import org.gusdb.wdk.model.record.RecordInstance;
import org.gusdb.wdk.model.record.attribute.AttributeField;
+import org.gusdb.wdk.model.test.sanity.RangeCountTestUtil;
import org.gusdb.wdk.model.test.sanity.SanityTester.ElementTest;
import org.gusdb.wdk.model.test.sanity.SanityTester.Statistics;
-import org.gusdb.wdk.model.test.sanity.RangeCountTestUtil;
import org.gusdb.wdk.model.test.sanity.TestResult;
import org.gusdb.wdk.model.user.StepContainer;
import org.gusdb.wdk.model.user.User;
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/BasicUser.java b/Model/src/main/java/org/gusdb/wdk/model/user/BasicUser.java
new file mode 100644
index 0000000000..7287c039c2
--- /dev/null
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/BasicUser.java
@@ -0,0 +1,41 @@
+package org.gusdb.wdk.model.user;
+
+import org.gusdb.oauth2.client.veupathdb.UserProperty;
+import org.gusdb.wdk.model.WdkModel;
+import org.json.JSONObject;
+
+/**
+ * Represents a VEupathDB user
+ *
+ * @author rdoherty
+ */
+public class BasicUser extends org.gusdb.oauth2.client.veupathdb.BasicUser implements User {
+
+ private final WdkModel _wdkModel;
+
+ public BasicUser(WdkModel wdkModel, long userId, boolean isGuest, String signature, String stableId) {
+ super(userId, isGuest, signature, stableId);
+ _wdkModel = wdkModel;
+ }
+
+ public BasicUser(WdkModel wdkModel, JSONObject json) {
+ super(json);
+ _wdkModel = wdkModel;
+ }
+
+ public BasicUser(User user) {
+ super(user.getUserId(), user.isGuest(), user.getSignature(), user.getStableId());
+ _wdkModel = user.getWdkModel();
+ setEmail(user.getEmail());
+ for (UserProperty prop : USER_PROPERTIES.values()) {
+ prop.setValue(this, prop.getValue(user));
+ }
+ }
+
+ @Override
+ public WdkModel getWdkModel() {
+ return _wdkModel;
+ }
+
+
+}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/BearerTokenUser.java b/Model/src/main/java/org/gusdb/wdk/model/user/BearerTokenUser.java
new file mode 100644
index 0000000000..23e9348f35
--- /dev/null
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/BearerTokenUser.java
@@ -0,0 +1,21 @@
+package org.gusdb.wdk.model.user;
+
+import org.gusdb.oauth2.client.OAuthClient;
+import org.gusdb.oauth2.client.OAuthConfig;
+import org.gusdb.oauth2.client.ValidatedToken;
+import org.gusdb.wdk.model.WdkModel;
+
+public class BearerTokenUser extends org.gusdb.oauth2.client.veupathdb.BearerTokenUser implements User {
+
+ private final WdkModel _wdkModel;
+
+ public BearerTokenUser(WdkModel wdkModel, OAuthClient client, OAuthConfig config, ValidatedToken token) {
+ super(client, config.getOauthUrl(), token);
+ _wdkModel = wdkModel;
+ }
+
+ @Override
+ public WdkModel getWdkModel() {
+ return _wdkModel;
+ }
+}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/FavoriteFactory.java b/Model/src/main/java/org/gusdb/wdk/model/user/FavoriteFactory.java
index f4ceb2d6f2..01fdc3c71a 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/user/FavoriteFactory.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/FavoriteFactory.java
@@ -7,7 +7,7 @@
import static org.gusdb.fgputil.functional.Functions.mapToList;
import static org.gusdb.fgputil.functional.Functions.mapToListWithIndex;
import static org.gusdb.wdk.model.Utilities.COLUMN_PK_PREFIX;
-import static org.gusdb.wdk.model.user.UserFactory.USER_SCHEMA_MACRO;
+import static org.gusdb.wdk.model.user.UserReferenceFactory.USER_SCHEMA_MACRO;
import java.sql.ResultSet;
import java.sql.SQLException;
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/RegisteredUser.java b/Model/src/main/java/org/gusdb/wdk/model/user/RegisteredUser.java
deleted file mode 100644
index f0f3b606b2..0000000000
--- a/Model/src/main/java/org/gusdb/wdk/model/user/RegisteredUser.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.gusdb.wdk.model.user;
-
-import org.gusdb.wdk.model.WdkModel;
-
-public class RegisteredUser extends User {
-
- RegisteredUser(WdkModel wdkModel, long userId, String email, String signature, String stableId) {
- super(wdkModel, userId, email, signature, stableId);
- }
-
- @Override
- public boolean isGuest() {
- return false;
- }
-
- @Override
- public String getDisplayName() {
- return (
- formatNamePart(_properties.get("firstName")) +
- formatNamePart(_properties.get("middleName")) +
- formatNamePart(_properties.get("lastName"))).trim();
- }
-
- private static String formatNamePart(String namePart) {
- return (namePart == null || namePart.isEmpty() ? "" : " " + namePart.trim());
- }
-
-}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/StrategyAnalysis.java b/Model/src/main/java/org/gusdb/wdk/model/user/StrategyAnalysis.java
index 5434c241f3..06c38cbc6f 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/user/StrategyAnalysis.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/StrategyAnalysis.java
@@ -37,8 +37,8 @@ public static void main(String[] args) throws WdkModelException {
!userEmail.isPresent() ?
model.getStepFactory().getAllStrategies(validationLevel, malformedStrats, stratsWithBuildErrors).values() :
model.getStepFactory().getStrategies(
- Optional.ofNullable(model.getUserFactory()
- .getUserByEmail(userEmail.get()))
+ model.getUserFactory()
+ .getUserByEmail(userEmail.get())
.orElseThrow(() -> new WdkModelException(
"Could not find user with email: " + userEmail
))
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/UnregisteredUser.java b/Model/src/main/java/org/gusdb/wdk/model/user/UnregisteredUser.java
deleted file mode 100644
index a84b08ad44..0000000000
--- a/Model/src/main/java/org/gusdb/wdk/model/user/UnregisteredUser.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.gusdb.wdk.model.user;
-
-import org.gusdb.wdk.model.WdkModel;
-
-public class UnregisteredUser extends User {
-
- // -------------------------------------------------------------------------
- // types of unregistered users
- // -------------------------------------------------------------------------
-
- public enum UnregisteredUserType {
- GUEST("WDK_GUEST_"),
- SYSTEM("WDK_GUEST_SYSTEM_");
-
- private final String _stableIdPrefix;
-
- private UnregisteredUserType(String stableIdPrefix) {
- _stableIdPrefix = stableIdPrefix;
- }
-
- public String getStableIdPrefix() {
- return _stableIdPrefix;
- }
- }
-
- UnregisteredUser(WdkModel wdkModel, long userId, String email, String signature, String stableId) {
- super(wdkModel, userId, email, signature, stableId);
- }
-
- @Override
- public boolean isGuest() {
- return true;
- }
-
- @Override
- public String getDisplayName() {
- return "WDK Guest";
- }
-}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/User.java b/Model/src/main/java/org/gusdb/wdk/model/user/User.java
index a0f89c326f..168e7de1c4 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/user/User.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/User.java
@@ -1,251 +1,9 @@
-package org.gusdb.wdk.model.user;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.log4j.Logger;
-import org.gusdb.fgputil.functional.FunctionalInterfaces.FunctionWithException;
-import org.gusdb.wdk.model.WdkModel;
-import org.gusdb.wdk.model.WdkModelException;
-import org.gusdb.wdk.model.record.RecordClass;
-
-/**
- * Represents a WDK user.
- *
- * @see UnregisteredUser for subclass representing guest user
- * @see RegisteredUser for subclass representing registered user
- *
- * @author rdoherty
- */
-public abstract class User {
-
- private static final Logger LOG = Logger.getLogger(User.class);
-
- protected WdkModel _wdkModel;
-
- protected long _userId;
- protected String _email;
- protected String _signature;
- protected String _stableId;
-
- // Holds key/value pairs associated with the user's profile (come from account db)
- protected Map _properties = new HashMap<>();
-
- // Holds key/value pairs associated with the user for this project (come from user db)
- protected UserPreferences _preferences;
-
- /**
- * Temporarily provide display name value until Struts Actions are purged.
- * After that, client will determine what to display
- * TODO: remove once struts is purged
- *
- * @return display name for this user
- */
- public abstract String getDisplayName();
-
- /**
- * Tells whether this user is a guest
- *
- * @return true if guest, else false
- */
- public abstract boolean isGuest();
-
- protected User(WdkModel wdkModel, long userId, String email, String signature, String stableId) {
- _wdkModel = wdkModel;
- _userId = userId;
- _email = email;
- _signature = signature;
- _stableId = stableId;
- _preferences = new UserPreferences();
- }
-
- public long getUserId() {
- return _userId;
- }
-
- public String getEmail() {
- return _email;
- }
-
- public String getSignature() {
- return _signature;
- }
-
- public String getStableId() {
- return _stableId;
- }
-
- public void setEmail(String email) {
- _email = email;
- }
-
- /**
- * Sets the value of the profile property given by the UserProfileProperty enum
- * @param key
- * @param value
- */
- public void setProfileProperty(String key, String value) {
- _properties.put(key, value);
- }
-
- public void setProfileProperties(Map properties) {
- _properties = properties;
- }
-
- /**
- * Return the entire user profile property map
- * @return
- */
- public Map getProfileProperties() {
- return _properties;
- }
-
- /**
- * Removes all existing user profile properties
- */
- public void clearProfileProperties() {
- _properties.clear();
- }
-
- public void setPreferences(UserPreferences preferences) {
- _preferences = preferences;
- }
-
- public UserPreferences getPreferences() {
- return _preferences;
- }
-
- public WdkModel getWdkModel() {
- return _wdkModel;
- }
-
- @Override
- public String toString() {
- return "User #" + getUserId() + " - " + getEmail();
- }
-
- @Override
- public int hashCode() {
- return (int)getUserId();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof User)) {
- return false;
- }
- User other = (User)obj;
- return (
- getUserId() == other.getUserId() &&
- getEmail().equals(other.getEmail()) &&
- getSignature().equals(other.getSignature()) &&
- getStableId().equals(other.getStableId())
- );
- }
-
-/**
- * This is a deprecated "trait" interface containing default methods previously
- * supplied by UserBean. It is necessary since we now expose the User class
- * to JSPs but its getters are limited in scope (callers in Java land should be
- * calling the appropriate factory methods to get a user's data e.g. favorites).
- *
- * Thus this is (hopefully) a temporary interface and can be removed when the
- * strategy-loading branch is merged back and we say good-bye to JSPs/beans.
- */
-
- public String getFirstName() {
- return getProfileProperties().get("firstName");
- }
-
- public String getMiddleName() {
- return getProfileProperties().get("middleName");
- }
-
- public String getLastName() {
- return getProfileProperties().get("lastName");
- }
-
- public String getOrganization() {
- return getProfileProperties().get("organization");
- }
-
- public Map getGlobalPreferences() {
- return getPreferences().getGlobalPreferences();
- }
-
- public Map getProjectPreferences() {
- return getPreferences().getProjectPreferences();
- }
-
- public int getStrategyCount() throws WdkModelException {
- return getWdkModel().getStepFactory().getStrategyCount(getUserId());
- }
-
- public int getPublicCount() throws WdkModelException {
- int count = getWdkModel().getStepFactory().getPublicStrategyCount();
- LOG.debug("Found number of public strats: " + count);
- return count;
- }
-
- public void logFoundStrategies(Map> strategies, String condition) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Loaded map of " + strategies.size() + " " + condition + " strategy categories:");
- int total = 0;
- for (Entry> entry : strategies.entrySet()) {
- LOG.debug(" " + entry.getKey() + ": " + entry.getValue().size() + " strategies.");
- total += entry.getValue().size();
- }
- LOG.debug(" Total: " + total);
- }
- }
-
- public Map getBasketCounts() throws WdkModelException {
- Map counts = getWdkModel().getBasketFactory().getBasketCounts(this);
- Map beans = new LinkedHashMap<>();
- for (RecordClass recordClass : counts.keySet()) {
- int count = counts.get(recordClass);
- beans.put(recordClass, count);
- }
- return beans;
- }
-
- public int getBasketCount() throws WdkModelException {
- Map baskets = getWdkModel().getBasketFactory().getBasketCounts(this);
- int total = 0;
- for (int count : baskets.values()) {
- total += count;
- }
- return total;
- }
-
- static Map exposeAsMap(FunctionWithException getter) {
- return new HashMap() {
- @Override
- public T get(Object objectName) {
- try {
- return getter.apply((String)objectName);
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- };
- }
-
- static Map> convertMap(Map> strategies) {
- Map> category = new LinkedHashMap<>();
- for (String type : strategies.keySet()) {
- List list = strategies.get(type);
- List beans = new ArrayList<>();
- for (Strategy strategy : list) {
- beans.add(strategy);
- }
- category.put(type, beans);
- }
- return category;
- }
-}
+package org.gusdb.wdk.model.user;
+
+import org.gusdb.wdk.model.WdkModel;
+
+public interface User extends org.gusdb.oauth2.client.veupathdb.User {
+
+ WdkModel getWdkModel();
+
+}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/UserCache.java b/Model/src/main/java/org/gusdb/wdk/model/user/UserCache.java
index 326ff7687a..519739b8eb 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/user/UserCache.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/UserCache.java
@@ -28,17 +28,20 @@ public UserCache(User user) {
@Override
public User get(Object id) {
try {
- Long userId = (Long)id;
- if (userId == null) {
+ if (id == null) {
throw new WdkRuntimeException("User ID cannot be null.");
}
+ if (!(id instanceof Long)) {
+ throw new IllegalArgumentException("Only Long objects should be passed to this method, not " + id.getClass().getName());
+ }
+ Long userId = (Long)id;
if (!containsKey(userId)) {
if (_userFactory != null) {
put(userId, _userFactory.getUserById(userId)
- .orElseThrow(() -> new WdkRuntimeException("User with ID " + id + " does not exist.")));
+ .orElseThrow(() -> new WdkRuntimeException("User with ID " + userId + " does not exist.")));
}
else {
- throw new WdkRuntimeException("No-lookup cache does not contain the requested user (" + id + ").");
+ throw new WdkRuntimeException("No-lookup cache does not contain the requested user (" + userId + ").");
}
}
return super.get(userId);
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/UserCreationScript.java b/Model/src/main/java/org/gusdb/wdk/model/user/UserCreationScript.java
deleted file mode 100644
index 87093118a6..0000000000
--- a/Model/src/main/java/org/gusdb/wdk/model/user/UserCreationScript.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package org.gusdb.wdk.model.user;
-
-import static org.gusdb.fgputil.FormatUtil.NL;
-import static org.gusdb.fgputil.FormatUtil.TAB;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import org.gusdb.fgputil.FormatUtil;
-import org.gusdb.fgputil.accountdb.UserPropertyName;
-import org.gusdb.fgputil.runtime.GusHome;
-import org.gusdb.wdk.model.WdkModel;
-import org.gusdb.wdk.model.WdkModelException;
-
-public class UserCreationScript {
-
- public static class UserLine {
-
- private final boolean _shouldWriteUser;
- private final String _email;
- private final Map _globalUserPrefs;
- private final Map _userProperties;
-
- public UserLine(boolean shouldWriteUser, String email,
- Map globalUserPrefs, Map userProperties) {
- _shouldWriteUser = shouldWriteUser;
- _email = email;
- _globalUserPrefs = globalUserPrefs;
- _userProperties = userProperties;
- }
-
- public boolean shouldWriteUser() { return _shouldWriteUser; }
- public String getEmail() { return _email; }
- public Map getGlobalUserPrefs() { return _globalUserPrefs; }
- public Map getUserProperties() { return _userProperties; }
-
- public String getAttributesString() { return getEmail() + ", " +
- FormatUtil.prettyPrint(_userProperties) + ", " +
- FormatUtil.prettyPrint(_globalUserPrefs); }
-
- @Override
- public String toString() {
- return shouldWriteUser() + ", " + getAttributesString();
- }
- }
-
- public static void main(String[] args) throws WdkModelException, IOException {
- if (!(args.length == 1 || (args.length == 2 && args[1].equalsIgnoreCase("test")))) {
- System.err.println(NL +
- "USAGE: fgpJava " + UserCreationScript.class.getName() + " [test]" + NL + NL +
- "This script will read tab-delimited user properties from stdin" + NL +
- "Passed project_id value is used only to look up account-db access information in gus_home" + NL +
- "If 'test' is specified as a second argument, no records will be written to the DB; " +
- "instead diagnostics will be printed to stdout" + NL);
- System.exit(1);
- }
- boolean testOnly = args.length == 2;
- try (WdkModel model = WdkModel.construct(args[0], GusHome.getGusHome());
- BufferedReader in = new BufferedReader(new InputStreamReader(System.in))) {
- List userProps = model.getModelConfig().getAccountDB().getUserPropertyNames();
- int newUserCount = 0, modifiedUserCount = 0, invalidLineCount = 0;
- String line;
- while ((line = in.readLine()) != null) {
- UserLine parsedLine = parseLine(line, userProps);
- if (parsedLine.shouldWriteUser()) {
- try {
- // create or edit user
- User user = model.getUserFactory().getUserByEmail(parsedLine.getEmail());
- if (user == null) {
- newUserCount++;
- if (testOnly) {
- System.out.println("Would create user: " + parsedLine.getAttributesString());
- }
- else {
- // create new user and assign preferences
- user = model.getUserFactory().createUser(
- parsedLine.getEmail(), parsedLine.getUserProperties(),
- parsedLine.getGlobalUserPrefs(), Collections.emptyMap(), true, false);
- System.out.println("Created user with ID " + user.getUserId() + " and email " + user.getEmail());
- }
- }
- else {
- modifiedUserCount++;
- String message = "User with email " + user.getEmail() +
- " exists; %s preferences " + FormatUtil.prettyPrint(parsedLine.getGlobalUserPrefs());
- if (testOnly) {
- System.out.println(String.format(message, "would add"));
- }
- else {
- // user exists already; simply add preferences
- UserPreferences userPrefs = user.getPreferences();
- for (Entry newPref : parsedLine.getGlobalUserPrefs().entrySet()) {
- userPrefs.setGlobalPreference(newPref.getKey(), newPref.getValue());
- }
- user.setPreferences(userPrefs);
- model.getUserFactory().savePreferences(user);
- System.out.println(String.format(message, "adding"));
- }
- }
- }
- catch (InvalidUsernameOrEmailException e) {
- System.err.println("Invalid email '" + parsedLine.getEmail() + "': " + e.getMessage());
- invalidLineCount++;
- }
- }
- else {
- invalidLineCount++;
- }
- }
- System.out.println("Number of new users: " + newUserCount);
- System.out.println("Number of existing users we added preferences to (could be more than one project): " + modifiedUserCount);
- System.out.println("Number of lines with invalid input: " + invalidLineCount);
- }
- }
-
- static UserLine parseLine(
- String line, List userProps) {
- String[] tokens = line.split(TAB);
- if (tokens.length == 0 || tokens[0].trim().isEmpty()) {
- System.err.println("Required value [email] missing on line: " + line);
- return new UserLine(false, null, null, null);
- }
- String email = tokens[0];
-
- // next token is project_ids user wants emails from
- Map globalUserPrefs = (tokens.length > 1 ?
- getEmailPrefsFromProjectIds(tokens[1]) : Collections.emptyMap());
-
- boolean valid = true;
- Map propertyMap = new LinkedHashMap<>();
- for (int i = 0; i < userProps.size(); i++) {
- UserPropertyName propName = userProps.get(i);
- // split will trim off trailing empty tokens, so backfill
- String nextValue = tokens.length > i + 2 ? tokens[i + 2].trim() : "";
- if (propName.isRequired() && nextValue.isEmpty()) {
- System.err.println("Required value [" + propName.getName() + "] missing on line: " + line);
- valid = false;
- }
- propertyMap.put(userProps.get(i).getName(), nextValue);
- }
- return new UserLine(valid, email, globalUserPrefs, propertyMap);
- }
-
- private static Map getEmailPrefsFromProjectIds(String commaDelimitedListOfProjectIds) {
- String[] projectIds = commaDelimitedListOfProjectIds.trim().isEmpty() ?
- new String[0] : commaDelimitedListOfProjectIds.split(",");
- return Arrays.stream(projectIds)
- .filter(projectId -> !projectId.trim().isEmpty())
- .map(projectId -> "preference_global_email_" + projectId.trim().toLowerCase())
- .collect(Collectors.toMap(Function.identity(), val -> "on"));
-
- }
-}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/UserFactory.java b/Model/src/main/java/org/gusdb/wdk/model/user/UserFactory.java
index caa5b3e004..f885ebc554 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/user/UserFactory.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/UserFactory.java
@@ -1,30 +1,32 @@
package org.gusdb.wdk.model.user;
-import java.sql.Timestamp;
-import java.sql.Types;
-import java.util.Date;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.Random;
-import java.util.regex.Matcher;
+import java.util.Set;
+import java.util.stream.Collectors;
import org.apache.log4j.Logger;
-import org.gusdb.fgputil.accountdb.AccountManager;
-import org.gusdb.fgputil.accountdb.UserProfile;
-import org.gusdb.fgputil.db.pool.DatabaseInstance;
-import org.gusdb.fgputil.db.runner.SQLRunner;
-import org.gusdb.fgputil.db.runner.SingleLongResultSetHandler;
-import org.gusdb.fgputil.db.runner.SingleLongResultSetHandler.Status;
+import org.gusdb.fgputil.Tuples.TwoTuple;
import org.gusdb.fgputil.events.Events;
+import org.gusdb.oauth2.client.OAuthClient;
+import org.gusdb.oauth2.client.OAuthConfig;
+import org.gusdb.oauth2.client.ValidatedToken;
+import org.gusdb.oauth2.client.veupathdb.OAuthQuerier;
+import org.gusdb.oauth2.client.veupathdb.UserProperty;
+import org.gusdb.oauth2.exception.ConflictException;
+import org.gusdb.oauth2.exception.ExpiredTokenException;
+import org.gusdb.oauth2.exception.InvalidPropertiesException;
+import org.gusdb.oauth2.exception.InvalidTokenException;
+import org.gusdb.oauth2.shared.IdTokenFields;
import org.gusdb.wdk.events.UserProfileUpdateEvent;
-import org.gusdb.wdk.model.Utilities;
import org.gusdb.wdk.model.WdkModel;
import org.gusdb.wdk.model.WdkModelException;
-import org.gusdb.wdk.model.WdkRuntimeException;
-import org.gusdb.wdk.model.WdkUserException;
-import org.gusdb.wdk.model.config.ModelConfig;
-import org.gusdb.wdk.model.config.ModelConfigAccountDB;
-import org.gusdb.wdk.model.user.UnregisteredUser.UnregisteredUserType;
+import org.json.JSONObject;
+
+import io.prometheus.client.Counter;
/**
* Manages persistence of user profile and preferences and creation and
@@ -38,302 +40,148 @@ public class UserFactory {
@SuppressWarnings("unused")
private static Logger LOG = Logger.getLogger(UserFactory.class);
- // -------------------------------------------------------------------------
- // database table and column definitions
- // -------------------------------------------------------------------------
-
- public static final String TABLE_USERS = "users";
- public static final String COL_USER_ID = "user_id";
- public static final String COL_IS_GUEST = "is_guest";
- public static final String COL_FIRST_ACCESS = "first_access";
-
- // -------------------------------------------------------------------------
- // sql and sql macro definitions
- // -------------------------------------------------------------------------
-
- static final String USER_SCHEMA_MACRO = "$$USER_SCHEMA$$";
- private static final String IS_GUEST_VALUE_MACRO = "$$IS_GUEST$$";
-
- private static final String COUNT_USER_REF_BY_ID_SQL =
- "select count(*)" +
- " from " + USER_SCHEMA_MACRO + TABLE_USERS +
- " where " + COL_USER_ID + " = ?";
- private static final Integer[] COUNT_USER_REF_BY_ID_PARAM_TYPES = { Types.BIGINT };
-
- private static final String INSERT_USER_REF_SQL =
- "insert into " + USER_SCHEMA_MACRO + TABLE_USERS +
- " (" + COL_USER_ID + "," + COL_IS_GUEST + "," + COL_FIRST_ACCESS +")" +
- " values (?, " + IS_GUEST_VALUE_MACRO + ", ?)";
- private static final Integer[] INSERT_USER_REF_PARAM_TYPES = { Types.BIGINT, Types.TIMESTAMP };
-
- private static final String SELECT_GUEST_USER_REF_BY_ID_SQL =
- "select " + COL_FIRST_ACCESS +
- " from " + USER_SCHEMA_MACRO + TABLE_USERS +
- " where " + COL_IS_GUEST + " = " + IS_GUEST_VALUE_MACRO + " and " + COL_USER_ID + " = ?";
- private static final Integer[] SELECT_GUEST_USER_REF_BY_ID_PARAM_TYPES = { Types.BIGINT };
+ private static final Counter GUEST_CREATION_COUNTER = Counter.build()
+ .name("wdk_guest_creation_count")
+ .help("Number of guest users created by WDK services")
+ .register();
// -------------------------------------------------------------------------
- // the macros used by the registration email
- // -------------------------------------------------------------------------
-
- private static final String EMAIL_MACRO_USER_NAME = "USER_NAME";
- private static final String EMAIL_MACRO_EMAIL = "EMAIL";
- private static final String EMAIL_MACRO_PASSWORD = "PASSWORD";
-
- // -------------------------------------------------------------------------
- // member variables
+ // member fields
// -------------------------------------------------------------------------
private final WdkModel _wdkModel;
- private final DatabaseInstance _userDb;
- private final String _userSchema;
- private final AccountManager _accountManager;
- private final UserPreferenceFactory _preferenceFactory;
+ private final UserReferenceFactory _userRefFactory;
+ private final UserPasswordEmailer _emailer;
+ private final OAuthConfig _config;
+ private final OAuthClient _client;
// -------------------------------------------------------------------------
// constructor
// -------------------------------------------------------------------------
public UserFactory(WdkModel wdkModel) {
+ // save model for populating new users
_wdkModel = wdkModel;
- _preferenceFactory = new UserPreferenceFactory(wdkModel);
- _userDb = wdkModel.getUserDb();
- ModelConfig modelConfig = wdkModel.getModelConfig();
- _userSchema = modelConfig.getUserDB().getUserSchema();
- ModelConfigAccountDB accountDbConfig = modelConfig.getAccountDB();
- _accountManager = new AccountManager(wdkModel.getAccountDb(),
- accountDbConfig.getAccountSchema(), accountDbConfig.getUserPropertyNames());
+ _userRefFactory = new UserReferenceFactory(wdkModel);
+ _emailer = new UserPasswordEmailer(wdkModel);
+ _config = wdkModel.getModelConfig();
+ _client = new OAuthClient(OAuthClient.getTrustManager(wdkModel.getModelConfig()));
}
// -------------------------------------------------------------------------
- // methods
+ // methods to manage tokens
// -------------------------------------------------------------------------
- public User createUser(String email,
- Map profileProperties,
- Map globalPreferences,
- Map projectPreferences)
- throws WdkModelException, InvalidUsernameOrEmailException {
- String dontEmailProp = _wdkModel.getProperties().get("DONT_EMAIL_NEW_USER");
- boolean sendWelcomeEmail = (dontEmailProp == null || !dontEmailProp.equals("true"));
- return createUser(email, profileProperties, globalPreferences, projectPreferences, true, sendWelcomeEmail);
+ public ValidatedToken getBearerTokenFromAuthCode(String authCode, String redirectUri) throws InvalidPropertiesException {
+ return _client.getBearerTokenFromAuthCode(_config, authCode, redirectUri);
}
- public User createUser(String email,
- Map profileProperties,
- Map globalPreferences,
- Map projectPreferences,
- boolean addUserDbReference, boolean sendWelcomeEmail)
- throws WdkModelException, InvalidUsernameOrEmailException {
- try {
- // check email for uniqueness and format
- email = validateAndFormatEmail(email, _accountManager);
-
- // if user supplied a username, make sure it is unique
- if (profileProperties.containsKey(AccountManager.USERNAME_PROPERTY_KEY)) {
- String username = profileProperties.get(AccountManager.USERNAME_PROPERTY_KEY);
- // check whether the username exists in the database already; if so, the operation fails
- if (_accountManager.getUserProfileByUsername(username) != null) {
- throw new InvalidUsernameOrEmailException("The username '" + username + "' is already in use. " + "Please choose another one.");
- }
- }
-
- // generate temporary password for user
- String password = generateTemporaryPassword();
-
- // add user to account DB
- UserProfile profile = _accountManager.createAccount(email, password, profileProperties);
-
- // add user to this user DB (will be added to other user DBs as needed during login)
- if (addUserDbReference) {
- addUserReference(profile.getUserId(), false);
- }
-
- // create new user object and add profile properties
- RegisteredUser user = new RegisteredUser(_wdkModel, profile.getUserId(),
- profile.getEmail(), profile.getSignature(), profile.getStableId());
- user.setProfileProperties(profile.getProperties());
-
- // set and save preferences
- UserPreferences prefs = new UserPreferences();
- if (globalPreferences != null) prefs.setGlobalPreferences(globalPreferences);
- if (projectPreferences != null) prefs.setProjectPreferences(projectPreferences);
- user.setPreferences(prefs);
- _preferenceFactory.savePreferences(user);
-
- // if needed, send user temporary password via email
- if (sendWelcomeEmail) {
- emailTemporaryPassword(user, password, _wdkModel.getModelConfig());
- }
-
- return user;
- }
- catch (WdkModelException | InvalidUsernameOrEmailException e) {
- // do not wrap known exceptions
- throw e;
- }
- catch (Exception e) {
- // wrap unknown exceptions with WdkModelException
- throw new WdkModelException("Could not completely create new user", e);
- }
+ public ValidatedToken getBearerTokenFromCredentials(String email, String password, String redirectUrl) throws InvalidPropertiesException {
+ return _client.getBearerTokenFromUsernamePassword(_config, email, password, redirectUrl);
}
- public void savePreferences(User user) throws WdkModelException {
- _preferenceFactory.savePreferences(user);
+ public ValidatedToken validateBearerToken(String rawToken) throws InvalidTokenException, ExpiredTokenException {
+ return _client.getValidatedEcdsaSignedToken(_config.getOauthUrl(), rawToken);
}
- private void addUserReference(Long userId, boolean isGuest) {
- Timestamp insertedOn = new Timestamp(new Date().getTime());
- String sql = INSERT_USER_REF_SQL
- .replace(USER_SCHEMA_MACRO, _userSchema)
- .replace(IS_GUEST_VALUE_MACRO, _userDb.getPlatform().convertBoolean(isGuest).toString());
- new SQLRunner(_userDb.getDataSource(), sql, "insert-user-ref")
- .executeStatement(new Object[]{ userId, insertedOn }, INSERT_USER_REF_PARAM_TYPES);
- }
+ // -------------------------------------------------------------------------
+ // methods to manage users
+ // -------------------------------------------------------------------------
- private boolean hasUserReference(long userId) {
- String sql = COUNT_USER_REF_BY_ID_SQL.replace(USER_SCHEMA_MACRO, _userSchema);
- SingleLongResultSetHandler handler = new SingleLongResultSetHandler();
- new SQLRunner(_userDb.getDataSource(), sql, "check-user-ref")
- .executeQuery(new Object[]{ userId }, COUNT_USER_REF_BY_ID_PARAM_TYPES, handler);
- if (handler.getStatus().equals(Status.NON_NULL_VALUE)) {
- switch (handler.getRetrievedValue().intValue()) {
- case 0: return false;
- case 1: return true;
- default: throw new IllegalStateException("More than one user reference in userDb for user " + userId);
- }
- }
- throw new WdkRuntimeException("User reference count query did not return count for user id " +
- userId + ". Status = " + handler.getStatus() + ", sql = " + sql);
+ public User convertToUser(ValidatedToken token) throws WdkModelException {
+ User user = new BearerTokenUser(_wdkModel, _client, _config, token);
+ _userRefFactory.addUserReference(user);
+ return user;
}
- private Date getGuestUserRefFirstAccess(long userId) {
- String sql = SELECT_GUEST_USER_REF_BY_ID_SQL
- .replace(USER_SCHEMA_MACRO, _userSchema)
- .replace(IS_GUEST_VALUE_MACRO, _userDb.getPlatform().convertBoolean(true).toString());
- return new SQLRunner(_userDb.getDataSource(), sql, "get-guest-user-ref")
- .executeQuery(new Object[]{ userId }, SELECT_GUEST_USER_REF_BY_ID_PARAM_TYPES, rs ->
- !rs.next() ? null : new Date(rs.getTimestamp(COL_FIRST_ACCESS).getTime()));
+ public TwoTuple createUnregisteredUser() throws WdkModelException {
+ ValidatedToken token = _client.getNewGuestToken(_config);
+ GUEST_CREATION_COUNTER.inc();
+ return new TwoTuple<>(token, convertToUser(token));
}
- private static void emailTemporaryPassword(User user, String password,
- ModelConfig modelConfig) throws WdkModelException {
-
- String smtpServer = modelConfig.getSmtpServer();
- String supportEmail = modelConfig.getSupportEmail();
- String emailSubject = modelConfig.getEmailSubject();
-
- // populate email content macros with user data
- String emailContent = modelConfig.getEmailContent()
- .replaceAll("\\$\\$" + EMAIL_MACRO_USER_NAME + "\\$\\$",
- Matcher.quoteReplacement(user.getDisplayName()))
- .replaceAll("\\$\\$" + EMAIL_MACRO_EMAIL + "\\$\\$",
- Matcher.quoteReplacement(user.getEmail()))
- .replaceAll("\\$\\$" + EMAIL_MACRO_PASSWORD + "\\$\\$",
- Matcher.quoteReplacement(password));
-
- Utilities.sendEmail(smtpServer, user.getEmail(), supportEmail, emailSubject, emailContent);
- }
+ public User createUser(String email, Map profileProperties)
+ throws WdkModelException, InvalidPropertiesException, InvalidUsernameOrEmailException {
+ try {
- private static String validateAndFormatEmail(String email, AccountManager accountMgr) throws InvalidUsernameOrEmailException {
- // trim and validate passed email address and extract stable name
- if (email == null)
- throw new InvalidUsernameOrEmailException("The user's email cannot be empty.");
- // format the info
- email = AccountManager.trimAndLowercase(email);
- if (email.isEmpty())
- throw new InvalidUsernameOrEmailException("The user's email cannot be empty.");
- int atSignIndex = email.indexOf("@");
- if (atSignIndex < 1) // must be present and not the first char
- throw new InvalidUsernameOrEmailException("The user's email address is invalid.");
- // check whether the user exist in the database already; if email exists, the operation fails
- if (accountMgr.getUserProfileByEmail(email) != null)
- throw new InvalidUsernameOrEmailException("The email '" + email + "' has already been registered. " + "Please choose another one.");
- return email;
- }
+ // contact OAuth server to create a new user with the passed props
+ Map allProps = new HashMap<>(profileProperties);
+ allProps.put(IdTokenFields.email.name(), email);
+ TwoTuple userTuple = parseExpandedUserJson(_client.createNewUser(_config, allProps));
- private static String generateTemporaryPassword() {
- // generate a random password of 8 characters long, the range will be
- // [0-9A-Za-z]
- StringBuilder buffer = new StringBuilder();
- Random rand = new Random();
- for (int i = 0; i < 8; i++) {
- int value = rand.nextInt(36);
- if (value < 10) { // number
- buffer.append(value);
- } else { // lower case letters
- buffer.append((char) ('a' + value - 10));
+ User user = userTuple.getFirst();
+ String password = userTuple.getSecond();
+
+ // add user to this user DB (will be added to other user DBs as needed during login)
+ _userRefFactory.addUserReference(user);
+
+ // if needed, send user temporary password via email
+ if (_emailer.isSendWelcomeEmail()) {
+ _emailer.emailTemporaryPassword(user, password);
}
+
+ return user;
}
- return buffer.toString();
+ catch (ConflictException e) {
+ throw new InvalidUsernameOrEmailException(e.getMessage());
+ }
+ }
+
+ private TwoTuple parseExpandedUserJson(JSONObject userJson) {
+ User user = new BasicUser(_wdkModel, userJson);
+ String password = userJson.getString(IdTokenFields.password.name());
+ return new TwoTuple<>(user, password);
}
/**
- * Create an unregistered user of the specified type and persist in the database
+ * Save the basic information of a user
*
- * @param userType unregistered user type to persist
- * @return new unregistered user with remaining fields populated
- * @throws WdkRuntimeException if unable to persist temporary user
+ * @param user
+ * @param newUser
+ * @throws InvalidPropertiesException
*/
- public UnregisteredUser createUnregistedUser(UnregisteredUserType userType) throws WdkRuntimeException {
+ public User saveUser(User oldUser, User newUser, ValidatedToken authorizationToken) throws InvalidUsernameOrEmailException, InvalidPropertiesException {
try {
- UserProfile profile = _accountManager.createGuestAccount(userType.getStableIdPrefix());
- addUserReference(profile.getUserId(), true);
- return new UnregisteredUser(_wdkModel, profile.getUserId(), profile.getEmail(), profile.getSignature(), profile.getStableId());
- }
- catch (Exception e) {
- throw new WdkRuntimeException("Unable to save temporary user", e);
- }
- }
+ // build map of user props + email to send to OAuth
+ Map props = new HashMap<>();
+ props.put(IdTokenFields.email.name(), newUser.getEmail());
+ for (UserProperty prop : User.USER_PROPERTIES.values()) {
+ props.put(prop.getName(), prop.getValue(newUser));
+ }
- private User completeLogin(User user) {
- if (user == null)
- return user;
+ // build a user from the response
+ User savedUser = new BasicUser(_wdkModel, _client.modifyUser(_config, authorizationToken, props));
- // make sure user has reference in this user DB (needs to happen before merging)
- if (!hasUserReference(user.getUserId())) {
- addUserReference(user.getUserId(), false);
+ Events.trigger(new UserProfileUpdateEvent(oldUser, savedUser, _wdkModel));
+ return savedUser;
+ }
+ catch (ConflictException e) {
+ throw new InvalidUsernameOrEmailException(e.getMessage());
}
-
- // update user active timestamp
- _accountManager.updateLastLogin(user.getUserId());
-
- return user;
}
- public User login(User guest, String email, String password)
- throws WdkUserException, WdkModelException {
- // make sure the guest is really a guest
- if (!guest.isGuest())
- throw new WdkUserException("User has been logged in.");
+ public void resetPassword(String loginName) throws InvalidUsernameOrEmailException, WdkModelException {
+ try {
+ TwoTuple user = parseExpandedUserJson(_client.resetPassword(_config, loginName));
- // authenticate the user; if fails, a WdkUserException will be thrown out
- User user = authenticate(email, password);
- if (user == null) {
- throw new WdkUserException("Invalid email or password.");
+ // email user new password
+ _emailer.emailTemporaryPassword(user.getFirst(), user.getSecond());
+ }
+ catch (InvalidPropertiesException e) {
+ throw new InvalidUsernameOrEmailException(e.getMessage());
}
- return completeLogin(user);
}
- public User login(long userId) throws WdkModelException {
- return completeLogin(getUserById(userId)
- .orElseThrow(() -> new WdkModelException("User with ID " + userId + " could not be found.")));
- }
+ // -------------------------------------------------------------------------
+ // methods to query users
+ // -------------------------------------------------------------------------
- /**
- * Returns whether email and password are a correct credentials combination.
- *
- * @param usernameOrEmail user email
- * @param password user password
- * @return true email corresponds to user and password is correct, else false
- * @throws WdkModelException if error occurs while determining result
- */
- public boolean isCorrectPassword(String usernameOrEmail, String password) throws WdkModelException {
- return authenticate(usernameOrEmail, password) != null;
+ public Map getUsersById(List userIds) {
+ return OAuthQuerier.getUsersById(_client, _config, userIds, json -> new BasicUser(_wdkModel, json));
}
- private User authenticate(String usernameOrEmail, String password) throws WdkModelException {
- return populateRegisteredUser(_accountManager.getUserProfile(usernameOrEmail, password));
+ public Map getUsersByEmail(List emails) {
+ return OAuthQuerier.getUsersByEmail(_client, _config, emails, json -> new BasicUser(_wdkModel, json));
}
/**
@@ -344,119 +192,15 @@ private User authenticate(String usernameOrEmail, String password) throws WdkMod
* @throws WdkModelException if an error occurs in the attempt
*/
public Optional getUserById(long userId) throws WdkModelException {
- UserProfile profile = _accountManager.getUserProfile(userId);
- if (profile != null) {
- // found registered user in account DB; create RegisteredUser and populate
- return Optional.of(populateRegisteredUser(profile));
- }
- else {
- // cannot find user in account DB; however, the passed ID may represent a guest local to this userDb
- Date accessDate = getGuestUserRefFirstAccess(userId);
- if (accessDate != null) {
- // guest user was found in local user Db; create UnregisteredUser and populate
- profile = AccountManager.createGuestProfile(UnregisteredUserType.GUEST.getStableIdPrefix(), userId, accessDate);
- return Optional.of(new UnregisteredUser(_wdkModel, profile.getUserId(),
- profile.getEmail(), profile.getSignature(), profile.getStableId()));
-
- }
- else {
- // user does not exist in account or user DBs
- return Optional.empty();
- }
- }
+ return Optional.ofNullable(getUsersById(List.of(userId)).get(userId));
}
- public User getUserByEmail(String email) throws WdkModelException {
- return populateRegisteredUser(_accountManager.getUserProfileByEmail(email));
- }
-
- private User getUserProfileByUsernameOrEmail(String usernameOrEmail) throws WdkModelException {
- return populateRegisteredUser(_accountManager.getUserProfileByUsernameOrEmail(usernameOrEmail));
- }
-
- public User getUserBySignature(String signature) throws WdkModelException, WdkUserException {
- User user = populateRegisteredUser(_accountManager.getUserProfileBySignature(signature));
- if (user == null) {
- // signature is rarely sent in by user; if User cannot be found, it's probably an error
- throw new WdkUserException("Unable to find user with signature: " + signature);
- }
- return user;
- }
-
- private User populateRegisteredUser(UserProfile profile) throws WdkModelException {
- if (profile == null) return null;
- User user = new RegisteredUser(_wdkModel, profile.getUserId(), profile.getEmail(),
- profile.getSignature(), profile.getStableId());
- user.setProfileProperties(profile.getProperties());
- user.setPreferences(_preferenceFactory.getPreferences(user));
- return user;
- }
-
- /**
- * Save the basic information of a user
- *
- * @param user
- */
- public void saveUser(User user) throws WdkModelException, InvalidUsernameOrEmailException {
- try {
-
- // Three integrity checks:
-
- // 1. Check if user exists in the database. if not, fail and ask to create the user first
- UserProfile oldProfile = _accountManager.getUserProfile(user.getUserId());
- if (oldProfile == null) {
- throw new WdkModelException("Cannot update user; no user exists with ID " + user.getUserId());
- }
-
- // 2. Check if another user exists with this email (PK will protect us but want better message)
- UserProfile emailUser = _accountManager.getUserProfileByEmail(user.getEmail());
- if (emailUser != null && emailUser.getUserId() != user.getUserId()) {
- throw new InvalidUsernameOrEmailException("This email is already in use by another account. Please choose another.");
- }
-
- // 3. Check if another user exists with this username (if supplied)
- if (user.getProfileProperties().containsKey(AccountManager.USERNAME_PROPERTY_KEY)) {
- String username = user.getProfileProperties().get(AccountManager.USERNAME_PROPERTY_KEY);
-
- UserProfile usernameUser = _accountManager.getUserProfileByUsername(username);
- if (usernameUser != null && user.getUserId() != usernameUser.getUserId()) {
- throw new InvalidUsernameOrEmailException("The username '" + username + "' is already in use. " + "Please choose another one.");
- }
- }
-
- // save off other data to user profile
- _accountManager.saveUserProfile(user.getUserId(), user.getEmail(), user.getProfileProperties());
-
- // get updated profile and trigger profile update event
- UserProfile newProfile = _accountManager.getUserProfile(user.getUserId());
- Events.trigger(new UserProfileUpdateEvent(oldProfile, newProfile, _wdkModel));
-
- // save preferences
- _preferenceFactory.savePreferences(user);
- }
- catch (InvalidUsernameOrEmailException e) {
- throw e;
- }
- // wrap any other exception in WdkModelException
- catch (Exception e) {
- throw new WdkModelException("Unable to update user profile for ID " + user.getUserId(), e);
- }
- }
-
- public void resetPassword(String emailOrLoginName) throws WdkUserException, WdkModelException {
- User user = getUserProfileByUsernameOrEmail(emailOrLoginName);
- if (user == null) {
- throw new WdkUserException("Cannot find user with email or login name: " + emailOrLoginName);
- }
- // create new temporary password
- String newPassword = generateTemporaryPassword();
- // set new password on user
- _accountManager.updatePassword(user.getUserId(), newPassword);
- // email user new password
- emailTemporaryPassword(user, newPassword, _wdkModel.getModelConfig());
+ public Optional getUserByEmail(String email) {
+ return Optional.ofNullable(getUsersByEmail(List.of(email)).get(email));
}
- public void changePassword(long userId, String newPassword) {
- _accountManager.updatePassword(userId, newPassword);
+ public Map verifyUserids(Set userIds) {
+ Map userMap = getUsersById(new ArrayList<>(userIds));
+ return userIds.stream().collect(Collectors.toMap(id -> id, id -> userMap.get(id) != null));
}
}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/UserPasswordEmailer.java b/Model/src/main/java/org/gusdb/wdk/model/user/UserPasswordEmailer.java
new file mode 100644
index 0000000000..7a083f7060
--- /dev/null
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/UserPasswordEmailer.java
@@ -0,0 +1,51 @@
+package org.gusdb.wdk.model.user;
+
+import java.util.regex.Matcher;
+
+import org.gusdb.wdk.model.Utilities;
+import org.gusdb.wdk.model.WdkModel;
+import org.gusdb.wdk.model.WdkModelException;
+import org.gusdb.wdk.model.config.ModelConfig;
+
+public class UserPasswordEmailer {
+
+ // -------------------------------------------------------------------------
+ // the macros used by the registration email
+ // -------------------------------------------------------------------------
+
+ private static final String EMAIL_MACRO_USER_NAME = "USER_NAME";
+ private static final String EMAIL_MACRO_EMAIL = "EMAIL";
+ private static final String EMAIL_MACRO_PASSWORD = "PASSWORD";
+
+ private final WdkModel _wdkModel;
+
+ public UserPasswordEmailer(WdkModel wdkModel) {
+ _wdkModel = wdkModel;
+ }
+
+ public boolean isSendWelcomeEmail() {
+ // whether or not WDK is configured to send a welcome email to new registered users (defaults to true)
+ String dontEmailProp = _wdkModel.getProperties().get("DONT_EMAIL_NEW_USER");
+ return dontEmailProp == null || !dontEmailProp.equals("true");
+ }
+
+ public void emailTemporaryPassword(User user, String password) throws WdkModelException {
+ if (!isSendWelcomeEmail()) return;
+
+ ModelConfig wdkModelConfig = _wdkModel.getModelConfig();
+ String smtpServer = wdkModelConfig.getSmtpServer();
+ String supportEmail = wdkModelConfig.getSupportEmail();
+ String emailSubject = wdkModelConfig.getEmailSubject();
+
+ // populate email content macros with user data
+ String emailContent = wdkModelConfig.getEmailContent()
+ .replaceAll("\\$\\$" + EMAIL_MACRO_USER_NAME + "\\$\\$",
+ Matcher.quoteReplacement(user.getDisplayName()))
+ .replaceAll("\\$\\$" + EMAIL_MACRO_EMAIL + "\\$\\$",
+ Matcher.quoteReplacement(user.getEmail()))
+ .replaceAll("\\$\\$" + EMAIL_MACRO_PASSWORD + "\\$\\$",
+ Matcher.quoteReplacement(password));
+
+ Utilities.sendEmail(smtpServer, user.getEmail(), supportEmail, emailSubject, emailContent);
+ }
+}
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/UserPreferenceFactory.java b/Model/src/main/java/org/gusdb/wdk/model/user/UserPreferenceFactory.java
index e5a75ba7f8..4cd071bde1 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/user/UserPreferenceFactory.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/UserPreferenceFactory.java
@@ -39,15 +39,14 @@ public UserPreferenceFactory(WdkModel wdkModel) {
_userSchema = wdkModel.getModelConfig().getUserDB().getUserSchema();
}
- public void savePreferences(User user) throws WdkModelException {
+ public void savePreferences(long userId, UserPreferences newPrefs) throws WdkModelException {
// get old preferences and determine what to delete, update, insert
- long userId = user.getUserId();
- UserPreferences oldPreferences = getPreferences(user);
+ UserPreferences oldPreferences = getPreferences(userId);
Map oldGlobal = oldPreferences.getGlobalPreferences();
- Map newGlobal = user.getPreferences().getGlobalPreferences();
+ Map newGlobal = newPrefs.getGlobalPreferences();
updatePreferences(userId, GLOBAL_PREFERENCE_KEY, oldGlobal, newGlobal);
Map oldSpecific = oldPreferences.getProjectPreferences();
- Map newSpecific = user.getPreferences().getProjectPreferences();
+ Map newSpecific = newPrefs.getProjectPreferences();
updatePreferences(userId, _wdkModel.getProjectId(), oldSpecific, newSpecific);
}
@@ -82,52 +81,59 @@ private void updatePreferences(long userId, String prefProjectId,
PreparedStatement psDelete = null, psInsert = null, psUpdate = null;
try {
+
// delete preferences
- String sqlDelete = "DELETE FROM " + _userSchema + "preferences "
- + " WHERE user_id = ? AND project_id = ? "
- + " AND preference_name = ?";
- psDelete = SqlUtils.getPreparedStatement(_userDb.getDataSource(), sqlDelete);
- long start = System.currentTimeMillis();
- for (String key : toDelete) {
- psDelete.setLong(1, userId);
- psDelete.setString(2, prefProjectId);
- psDelete.setString(3, key);
- psDelete.addBatch();
+ if (!toDelete.isEmpty()) {
+ String sqlDelete = "DELETE FROM " + _userSchema + "preferences "
+ + " WHERE user_id = ? AND project_id = ? "
+ + " AND preference_name = ?";
+ psDelete = SqlUtils.getPreparedStatement(_userDb.getDataSource(), sqlDelete);
+ long start = System.currentTimeMillis();
+ for (String key : toDelete) {
+ psDelete.setLong(1, userId);
+ psDelete.setString(2, prefProjectId);
+ psDelete.setString(3, key);
+ psDelete.addBatch();
+ }
+ psDelete.executeBatch();
+ QueryLogger.logEndStatementExecution(sqlDelete, "wdk-user-delete-preference", start);
}
- psDelete.executeBatch();
- QueryLogger.logEndStatementExecution(sqlDelete, "wdk-user-delete-preference", start);
// insert preferences
- String sqlInsert = "INSERT INTO " + _userSchema + "preferences "
- + " (user_id, project_id, preference_name, " + " preference_value)"
- + " VALUES (?, ?, ?, ?)";
- psInsert = SqlUtils.getPreparedStatement(_userDb.getDataSource(), sqlInsert);
- start = System.currentTimeMillis();
- for (String key : toInsert.keySet()) {
- psInsert.setLong(1, userId);
- psInsert.setString(2, prefProjectId);
- psInsert.setString(3, key);
- psInsert.setString(4, toInsert.get(key));
- psInsert.addBatch();
+ if (!toInsert.isEmpty()) {
+ String sqlInsert = "INSERT INTO " + _userSchema + "preferences "
+ + " (user_id, project_id, preference_name, " + " preference_value)"
+ + " VALUES (?, ?, ?, ?)";
+ psInsert = SqlUtils.getPreparedStatement(_userDb.getDataSource(), sqlInsert);
+ long start = System.currentTimeMillis();
+ for (String key : toInsert.keySet()) {
+ psInsert.setLong(1, userId);
+ psInsert.setString(2, prefProjectId);
+ psInsert.setString(3, key);
+ psInsert.setString(4, toInsert.get(key));
+ psInsert.addBatch();
+ }
+ psInsert.executeBatch();
+ QueryLogger.logEndStatementExecution(sqlInsert, "wdk-user-insert-preference", start);
}
- psInsert.executeBatch();
- QueryLogger.logEndStatementExecution(sqlInsert, "wdk-user-insert-preference", start);
// update preferences
- String sqlUpdate = "UPDATE " + _userSchema + "preferences "
- + " SET preference_value = ? WHERE user_id = ? "
- + " AND project_id = ? AND preference_name = ?";
- psUpdate = SqlUtils.getPreparedStatement(_userDb.getDataSource(), sqlUpdate);
- start = System.currentTimeMillis();
- for (String key : toUpdate.keySet()) {
- psUpdate.setString(1, toUpdate.get(key));
- psUpdate.setLong(2, userId);
- psUpdate.setString(3, prefProjectId);
- psUpdate.setString(4, key);
- psUpdate.addBatch();
+ if (!toUpdate.isEmpty()) {
+ String sqlUpdate = "UPDATE " + _userSchema + "preferences "
+ + " SET preference_value = ? WHERE user_id = ? "
+ + " AND project_id = ? AND preference_name = ?";
+ psUpdate = SqlUtils.getPreparedStatement(_userDb.getDataSource(), sqlUpdate);
+ long start = System.currentTimeMillis();
+ for (String key : toUpdate.keySet()) {
+ psUpdate.setString(1, toUpdate.get(key));
+ psUpdate.setLong(2, userId);
+ psUpdate.setString(3, prefProjectId);
+ psUpdate.setString(4, key);
+ psUpdate.addBatch();
+ }
+ psUpdate.executeBatch();
+ QueryLogger.logEndStatementExecution(sqlUpdate, "wdk-user-update-preference", start);
}
- psUpdate.executeBatch();
- QueryLogger.logEndStatementExecution(sqlUpdate, "wdk-user-update-preference", start);
}
catch (SQLException e) {
throw new WdkModelException("Unable to update user (id=" + userId
@@ -145,12 +151,12 @@ private void updatePreferences(long userId, String prefProjectId,
* @return a list of 2 elements, the first is a map of global preferences, the
* second is a map of project-specific preferences.
*/
- public UserPreferences getPreferences(User user) throws WdkModelException {
+ public UserPreferences getPreferences(long userId) throws WdkModelException {
try {
String sql = "SELECT * FROM " + _userSchema + "preferences WHERE user_id = ?";
return new SQLRunner(_userDb.getDataSource(), sql, "wdk-user-select-preference")
.executeQuery(
- new Object[]{ user.getUserId() },
+ new Object[]{ userId },
new Integer[]{ Types.BIGINT },
rs -> {
UserPreferences prefs = new UserPreferences();
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/UserPreferences.java b/Model/src/main/java/org/gusdb/wdk/model/user/UserPreferences.java
index 4c4633befd..c448c48cd2 100644
--- a/Model/src/main/java/org/gusdb/wdk/model/user/UserPreferences.java
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/UserPreferences.java
@@ -23,12 +23,16 @@ public class UserPreferences {
* the preferences for the user: . It only contains the preferences for the current
* project
*/
- private final Map _globalPreferences;
- private final Map _projectPreferences;
+ private final Map _globalPreferences = new LinkedHashMap<>();
+ private final Map _projectPreferences = new LinkedHashMap<>();
- public UserPreferences() {
- _globalPreferences = new LinkedHashMap();
- _projectPreferences = new LinkedHashMap();
+ public UserPreferences() { }
+
+ public UserPreferences(
+ Map globalPreferences,
+ Map projectPreferences) {
+ if (globalPreferences != null) setGlobalPreferences(globalPreferences);
+ if (projectPreferences != null) setProjectPreferences(projectPreferences);
}
public void setProjectPreference(String prefName, String prefValue) {
diff --git a/Model/src/main/java/org/gusdb/wdk/model/user/UserReferenceFactory.java b/Model/src/main/java/org/gusdb/wdk/model/user/UserReferenceFactory.java
new file mode 100644
index 0000000000..2673c9cc65
--- /dev/null
+++ b/Model/src/main/java/org/gusdb/wdk/model/user/UserReferenceFactory.java
@@ -0,0 +1,113 @@
+package org.gusdb.wdk.model.user;
+
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.Date;
+import java.util.Optional;
+
+import org.gusdb.fgputil.Tuples.ThreeTuple;
+import org.gusdb.fgputil.db.pool.DatabaseInstance;
+import org.gusdb.fgputil.db.runner.SQLRunner;
+import org.gusdb.fgputil.db.runner.SQLRunnerException;
+import org.gusdb.wdk.model.WdkModel;
+import org.gusdb.wdk.model.WdkModelException;
+
+class UserReferenceFactory {
+
+ // -------------------------------------------------------------------------
+ // database table and column definitions
+ // -------------------------------------------------------------------------
+
+ public static final String TABLE_USERS = "users";
+ public static final String COL_USER_ID = "user_id";
+ public static final String COL_IS_GUEST = "is_guest";
+ public static final String COL_FIRST_ACCESS = "first_access";
+
+ // -------------------------------------------------------------------------
+ // sql and sql macro definitions
+ // -------------------------------------------------------------------------
+
+ public static final String USER_SCHEMA_MACRO = "$$USER_SCHEMA$$";
+ private static final String IS_GUEST_VALUE_MACRO = "$$IS_GUEST$$";
+
+ // SQL and types to insert previously unknown user refs into the users table
+ private static final String INSERT_USER_REF_SQL =
+ "insert" +
+ " when not exists (select 1 from " + USER_SCHEMA_MACRO + TABLE_USERS + " where " + COL_USER_ID + " = ?)" +
+ " then" +
+ " into " + USER_SCHEMA_MACRO + TABLE_USERS + " (" + COL_USER_ID + "," + COL_IS_GUEST + "," + COL_FIRST_ACCESS +")" +
+ " select ?, " + IS_GUEST_VALUE_MACRO + ", ? from dual";
+
+ private static final Integer[] INSERT_USER_REF_PARAM_TYPES = { Types.BIGINT, Types.BIGINT, Types.TIMESTAMP };
+
+ // SQL and types to select user ref by ID
+ private static final String SELECT_USER_REF_BY_ID_SQL =
+ "select " + COL_USER_ID + ", " + COL_IS_GUEST + ", " + COL_FIRST_ACCESS +
+ " from " + USER_SCHEMA_MACRO + TABLE_USERS +
+ " where " + COL_USER_ID + " = ?";
+
+ private static final Integer[] SELECT_USER_REF_BY_ID_PARAM_TYPES = { Types.BIGINT };
+
+ // TODO: decide if this is actually needed/desired anywhere. UserRef lookups are not currently used.
+ public static class UserReference extends ThreeTuple {
+ public UserReference(Long userId, Boolean isGuest, Date firstAccess) {
+ super(userId, isGuest, firstAccess);
+ }
+ public Long getUserId() { return getFirst(); }
+ public Boolean isGuest() { return getSecond(); }
+ public Date getFirstAccess() { return getThird(); }
+ }
+
+ private final DatabaseInstance _userDb;
+ private final String _userSchema;
+
+ public UserReferenceFactory(WdkModel wdkModel) {
+ _userDb = wdkModel.getUserDb();
+ _userSchema = wdkModel.getModelConfig().getUserDB().getUserSchema();
+ }
+
+ /**
+ * Adds a user reference row to the UserDB users table if one does not exist.
+ * This is for tracking and for foreign keys on other user DB tables.
+ * Note is_guest and first_access are immutable fields and once set will not be
+ * changed by this code.
+ *
+ * @param user user to add
+ * @throws WdkModelException
+ */
+ public int addUserReference(User user) throws WdkModelException {
+ try {
+ long userId = user.getUserId();
+ boolean isGuest = user.isGuest();
+ Timestamp insertedOn = new Timestamp(new Date().getTime());
+ String sql = INSERT_USER_REF_SQL
+ .replace(USER_SCHEMA_MACRO, _userSchema)
+ .replace(IS_GUEST_VALUE_MACRO, _userDb.getPlatform().convertBoolean(isGuest).toString());
+ return new SQLRunner(_userDb.getDataSource(), sql, "insert-user-ref")
+ .executeUpdate(new Object[]{ userId, userId, insertedOn }, INSERT_USER_REF_PARAM_TYPES);
+ }
+ catch (SQLRunnerException e) {
+ throw WdkModelException.translateFrom(e);
+ }
+ }
+
+ // FIXME: see if this is actually needed anywhere? E.g. do we ever need to look up user refs by user ID to find last login?
+ public Optional getUserReference(long userId) throws WdkModelException {
+ try {
+ String sql = SELECT_USER_REF_BY_ID_SQL.replace(USER_SCHEMA_MACRO, _userSchema);
+ return new SQLRunner(_userDb.getDataSource(), sql, "get-user-ref").executeQuery(
+ new Object[]{ userId },
+ SELECT_USER_REF_BY_ID_PARAM_TYPES,
+ rs ->
+ !rs.next()
+ ? Optional.empty()
+ : Optional.of(new UserReference(
+ rs.getLong(COL_USER_ID),
+ rs.getBoolean(COL_IS_GUEST),
+ new Date(rs.getTimestamp(COL_FIRST_ACCESS).getTime()))));
+ }
+ catch (SQLRunnerException e) {
+ throw WdkModelException.translateFrom(e);
+ }
+ }
+}
diff --git a/Model/src/main/java/org/gusdb/wdk/session/OAuthClient.java b/Model/src/main/java/org/gusdb/wdk/session/OAuthClient.java
deleted file mode 100644
index dd56f0f0c7..0000000000
--- a/Model/src/main/java/org/gusdb/wdk/session/OAuthClient.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package org.gusdb.wdk.session;
-
-import static org.gusdb.fgputil.FormatUtil.NL;
-
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.Map.Entry;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedHashMap;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-
-import org.apache.log4j.Logger;
-import org.glassfish.jersey.client.ClientConfig;
-import org.gusdb.fgputil.FormatUtil;
-import org.gusdb.fgputil.IoUtil;
-import org.gusdb.wdk.model.WdkModelException;
-import org.gusdb.wdk.model.config.OAuthConfig;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.impl.TextCodec;
-
-public class OAuthClient {
-
- private static final Logger LOG = Logger.getLogger(OAuthClient.class);
-
- private final String _oauthServerBase;
- private final String _clientId;
- private final String _clientSecret;
- private final TrustManager _trustManager;
-
- public OAuthClient(OAuthConfig config) throws WdkModelException {
- _oauthServerBase = config.getOauthUrl();
- _clientId = config.getOauthClientId();
- _clientSecret = config.getOauthClientSecret();
- _trustManager = getTrustManager(config);
- }
-
- private static TrustManager getTrustManager(OAuthConfig config) throws WdkModelException {
- String keyStoreFile = config.getKeyStoreFile();
- return (keyStoreFile.isEmpty() ? new WdkTrustManager() :
- new WdkTrustManager(Paths.get(keyStoreFile), config.getKeyStorePassPhrase()));
- }
-
- public long getUserIdFromAuthCode(String authCode, String redirectUri) throws WdkModelException {
-
- try {
- String oauthUrl = _oauthServerBase + "/token";
-
- // build form parameters for token request
- MultivaluedMap formData = new MultivaluedHashMap<>();
- formData.add("grant_type", "authorization_code");
- formData.add("code", authCode);
- formData.add("redirect_uri", redirectUri);
- formData.add("client_id", _clientId);
- formData.add("client_secret", _clientSecret);
-
- SSLContext sslContext = SSLContext.getInstance("SSL");
- sslContext.init(null, new TrustManager[]{ _trustManager }, null);
-
- LOG.info("Building token request with the following URL: " + oauthUrl +
- " and params: " + dumpMultiMap(formData));
-
- // build request and get token response
- Response response = ClientBuilder.newBuilder()
- .withConfig(new ClientConfig())
- .sslContext(sslContext)
- .build()
- .target(oauthUrl)
- .request(MediaType.APPLICATION_JSON)
- .post(Entity.form(formData));
-
- if (response.getStatus() == 200) {
- // Success! Read result into buffer and convert to JSON
- InputStream resultStream = (InputStream)response.getEntity();
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- IoUtil.transferStream(buffer, resultStream);
- JSONObject json = new JSONObject(new String(buffer.toByteArray()));
- LOG.debug("Response received from OAuth server for token request: " + json.toString(2));
- // get id_token from object and decode to user ID
- String idToken = json.getString("id_token");
- return getUserIdFromIdToken(idToken, _clientSecret);
- }
- else {
- // Failure; throw exception
- throw new WdkModelException("OAuth2 token request failed with status " +
- response.getStatus() + ": " + response.getStatusInfo().getReasonPhrase() + NL + response.getEntity());
- }
- }
- catch(WdkModelException e) {
- throw e;
- }
- catch(Exception e) {
- throw new WdkModelException("Unable to complete OAuth token request to fetch user id", e);
- }
- }
-
- private static long getUserIdFromIdToken(String idToken, String clientSecret) throws WdkModelException {
- try {
- LOG.debug("Attempting parse of id token [" + idToken + "] using client secret '" + clientSecret +"'");
- String encodedKey = TextCodec.BASE64.encode(clientSecret);
- Claims claims = Jwts.parser().setSigningKey(encodedKey).parseClaimsJws(idToken).getBody();
- // TODO: verify additional claims for security
- String userIdStr = claims.getSubject();
- LOG.debug("Received token for sub '" + userIdStr + "' and preferred_username '" + claims.get("preferred_username"));
- if (FormatUtil.isInteger(userIdStr)) {
- return Long.valueOf(userIdStr);
- }
- throw new WdkModelException("Subject returned by OAuth server [" + userIdStr + "] is not a valid user ID.");
- }
- catch (JSONException e) {
- throw new WdkModelException("JWT body returned is not a valid JSON object.");
- }
- }
-
- private static String dumpMultiMap(MultivaluedMap formData) {
- StringBuilder str = new StringBuilder("{").append(NL);
- for (Entry> entry : formData.entrySet()) {
- str.append(" ").append(entry.getKey()).append(": ")
- .append(FormatUtil.arrayToString(entry.getValue().toArray())).append(NL);
- }
- return str.append("}").append(NL).toString();
- }
-}
diff --git a/Model/src/main/java/org/gusdb/wdk/session/OAuthUtil.java b/Model/src/main/java/org/gusdb/wdk/session/OAuthUtil.java
deleted file mode 100644
index 7036e3d770..0000000000
--- a/Model/src/main/java/org/gusdb/wdk/session/OAuthUtil.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.gusdb.wdk.session;
-
-import java.util.Date;
-import java.util.UUID;
-
-import org.gusdb.fgputil.EncryptionUtil;
-import org.gusdb.wdk.model.WdkModel;
-import org.gusdb.wdk.model.WdkModelException;
-
-public class OAuthUtil {
-
- public static final String STATE_TOKEN_KEY = "OAUTH_STATE_TOKEN";
-
- /**
- * Generates a new state token based on the current time, a random UUID, and
- * WDK model's current secret key value. This value should be added to the
- * session when a user is about to attempt a login; it will then be checked
- * against the state token accompanying the authentication token returned by
- * the OAuth server after the user has been authenticated. This is to prevent
- * cross-site request forgery attacks.
- *
- * @param wdkModel WDK Model (used to fetch secret key)
- * @return generated state token
- * @throws WdkModelException if unable to access secret key
- */
- public static String generateStateToken(WdkModel wdkModel) throws WdkModelException {
- String saltedString =
- UUID.randomUUID() + ":::" +
- String.valueOf(new Date().getTime()) + ":::" +
- wdkModel.getModelConfig().getSecretKey();
- return EncryptionUtil.encrypt(saltedString);
- }
-
-}
diff --git a/Model/src/main/java/org/gusdb/wdk/session/WdkTrustManager.java b/Model/src/main/java/org/gusdb/wdk/session/WdkTrustManager.java
deleted file mode 100644
index e0c2e79f2b..0000000000
--- a/Model/src/main/java/org/gusdb/wdk/session/WdkTrustManager.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package org.gusdb.wdk.session;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.Socket;
-import java.nio.file.Path;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509ExtendedTrustManager;
-
-import org.apache.log4j.Logger;
-import org.gusdb.wdk.model.WdkModelException;
-
-/**
- * Implementation of SSL trust manager that uses a Java key store for the basis
- * of certification checks. Failures are simply logged. An alternate
- * constructor creates a "dummy" trust manager that allows anything (i.e. no
- * security at all). This can be used when the keystore file is unknown,
- * unavailable, or unconfigured.
- *
- * This code was adapted from a sample and explanation here:
- * https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html
- *
- * To see the certs (probably) loaded by this class by EuPathDB, run:
- * > keytool -list -v -keystore /etc/pki/java/cacerts
- *
- * @author rdoherty
- */
-public class WdkTrustManager extends X509ExtendedTrustManager {
-
- private static final Logger LOG = Logger.getLogger(WdkTrustManager.class);
-
- /**
- * The default PKIX X509ExtendedTrustManager. We'll delegate decisions to it,
- * and fall back to the logic in this class if the default
- * X509ExtendedTrustManager doesn't trust it.
- */
- private final X509ExtendedTrustManager _pkixTrustManager;
-
- public WdkTrustManager() {
- // do nothing; this constructor creates a trust manager that allows anything
- _pkixTrustManager = null;
- }
-
- public WdkTrustManager(Path keyStoreFile, String passPhrase) throws WdkModelException {
- try (InputStream fileStream = new FileInputStream(keyStoreFile.toAbsolutePath().toString())) {
- // create a "default" JSSE X509ExtendedTrustManager
- KeyStore ks = KeyStore.getInstance("JKS");
- ks.load(fileStream, (passPhrase == null || passPhrase.isEmpty() ? null : passPhrase.toCharArray()));
-
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
- tmf.init(ks);
-
- TrustManager[] tms = tmf.getTrustManagers();
-
- /*
- * Iterate over the returned trust managers, look for an instance of X509TrustManager. If found, use that
- * as our "default" trust manager.
- */
- for (int i = 0; i < tms.length; i++) {
- if (tms[i] instanceof X509ExtendedTrustManager) {
- _pkixTrustManager = (X509ExtendedTrustManager) tms[i];
- return;
- }
- }
-
- // Can't find a valid trust manager in the factory
- throw new WdkModelException("Couldn't initialize trust manager using key store file " + keyStoreFile);
- }
- catch (IOException | NoSuchAlgorithmException | CertificateException | KeyStoreException e) {
- throw new WdkModelException("Couldn't initialize trust manager using key store file " + keyStoreFile, e);
- }
- }
-
- /*
- * Delegate to the default trust manager.
- */
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- try {
- if (_pkixTrustManager != null) _pkixTrustManager.checkClientTrusted(chain, authType);
- }
- catch (CertificateException e) {
- LOG.error("SSL validation check failed.", e);
- throw e;
- }
- }
-
- /*
- * Delegate to the default trust manager.
- */
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- try {
- if (_pkixTrustManager != null) _pkixTrustManager.checkServerTrusted(chain, authType);
- }
- catch (CertificateException e) {
- // Possibly pop up a dialog box asking whether to trust the cert chain?
- LOG.error("SSL validation check failed.", e);
- throw e;
- }
- }
-
- /*
- * Connection-sensitive verification.
- */
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket)
- throws CertificateException {
- try {
- if (_pkixTrustManager != null) _pkixTrustManager.checkClientTrusted(chain, authType, socket);
- }
- catch (CertificateException e) {
- LOG.error("SSL validation check failed.", e);
- throw e;
- }
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine)
- throws CertificateException {
- try {
- if (_pkixTrustManager != null) _pkixTrustManager.checkClientTrusted(chain, authType, engine);
- }
- catch (CertificateException e) {
- LOG.error("SSL validation check failed.", e);
- throw e;
- }
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket)
- throws CertificateException {
- try {
- if (_pkixTrustManager != null) _pkixTrustManager.checkServerTrusted(chain, authType, socket);
- }
- catch (CertificateException e) {
- LOG.error("SSL validation check failed.", e);
- throw e;
- }
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine)
- throws CertificateException {
- try {
- if (_pkixTrustManager != null) _pkixTrustManager.checkServerTrusted(chain, authType, engine);
- }
- catch (CertificateException e) {
- LOG.error("SSL validation check failed.", e);
- throw e;
- }
- }
-
- /*
- * Merely pass this through.
- */
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return _pkixTrustManager == null ?
- new X509Certificate[]{} :
- _pkixTrustManager.getAcceptedIssuers();
- }
-}
diff --git a/Model/src/test/java/org/gusdb/wdk/model/user/UserCreationScriptTest.java b/Model/src/test/java/org/gusdb/wdk/model/user/UserCreationScriptTest.java
deleted file mode 100644
index 3fece5e659..0000000000
--- a/Model/src/test/java/org/gusdb/wdk/model/user/UserCreationScriptTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.gusdb.wdk.model.user;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.gusdb.fgputil.accountdb.UserPropertyName;
-import org.gusdb.wdk.model.user.UserCreationScript.UserLine;
-import org.junit.Test;
-
-public class UserCreationScriptTest {
-
- private static final String[] TEST_CASES = {
- "\ta\tb\tc\td",
- "email\ta\t\tc\td",
- "email\t\tb\tc\td",
- "email\ta\tb\t\t\t\t"
- };
-
- private static final UserPropertyName[] USER_PROPS = {
- new UserPropertyName("firstName", null, true),
- new UserPropertyName("middleName", null, false),
- new UserPropertyName("lastName", null, true),
- new UserPropertyName("organization", null, true)
- };
-
- @Test
- public void testParsing() {
- List userProps = Arrays.asList(USER_PROPS);
- for (String testCase : TEST_CASES) {
- UserLine userLine = UserCreationScript.parseLine(testCase, userProps);
- System.out.println(userLine);
- }
- }
-}
diff --git a/Service/pom.xml b/Service/pom.xml
index 4b89378b8f..85c1b2a16f 100644
--- a/Service/pom.xml
+++ b/Service/pom.xml
@@ -38,17 +38,17 @@
org.gusdb
- fgputil-accountdb
+ fgputil-server
org.gusdb
- fgputil-server
+ fgputil-client
org.gusdb
- fgputil-client
+ oauth2-client
diff --git a/Service/src/main/java/org/gusdb/wdk/service/WdkServiceApplication.java b/Service/src/main/java/org/gusdb/wdk/service/WdkServiceApplication.java
index e070526544..891ae04041 100644
--- a/Service/src/main/java/org/gusdb/wdk/service/WdkServiceApplication.java
+++ b/Service/src/main/java/org/gusdb/wdk/service/WdkServiceApplication.java
@@ -20,7 +20,6 @@
import org.gusdb.wdk.service.provider.JsonSchemaProvider;
import org.gusdb.wdk.service.service.AnswerService;
import org.gusdb.wdk.service.service.ClientErrorReportingService;
-import org.gusdb.wdk.service.service.OAuthService;
import org.gusdb.wdk.service.service.OntologyService;
import org.gusdb.wdk.service.service.ProjectService;
import org.gusdb.wdk.service.service.PublicStrategyService;
@@ -82,7 +81,6 @@ public Set> getClasses() {
// add service classes
.add(ProjectService.class)
.add(SystemService.class)
- .add(OAuthService.class)
.add(ProfileService.class)
.add(PreferenceService.class)
.add(RecordService.class)
diff --git a/Service/src/main/java/org/gusdb/wdk/service/filter/CheckLoginFilter.java b/Service/src/main/java/org/gusdb/wdk/service/filter/CheckLoginFilter.java
index d4ea31b860..10ba972bcb 100644
--- a/Service/src/main/java/org/gusdb/wdk/service/filter/CheckLoginFilter.java
+++ b/Service/src/main/java/org/gusdb/wdk/service/filter/CheckLoginFilter.java
@@ -1,14 +1,13 @@
package org.gusdb.wdk.service.filter;
import java.io.IOException;
-import java.util.Map;
-import java.util.Optional;
import javax.annotation.Priority;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
@@ -16,24 +15,40 @@
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+import org.apache.log4j.Logger;
import org.glassfish.grizzly.http.server.Request;
+import org.gusdb.fgputil.Tuples.TwoTuple;
import org.gusdb.fgputil.web.ApplicationContext;
import org.gusdb.fgputil.web.CookieBuilder;
-import org.gusdb.fgputil.web.LoginCookieFactory;
import org.gusdb.fgputil.web.RequestData;
+import org.gusdb.oauth2.client.OAuthClient;
+import org.gusdb.oauth2.client.ValidatedToken;
+import org.gusdb.oauth2.exception.ExpiredTokenException;
+import org.gusdb.oauth2.exception.InvalidTokenException;
import org.gusdb.wdk.controller.ContextLookup;
-import org.gusdb.wdk.controller.filter.CheckLoginFilterShared;
+import org.gusdb.wdk.model.Utilities;
+import org.gusdb.wdk.model.WdkModelException;
+import org.gusdb.wdk.model.WdkRuntimeException;
+import org.gusdb.wdk.model.user.User;
+import org.gusdb.wdk.model.user.UserFactory;
+import org.gusdb.wdk.service.service.SessionService;
import org.gusdb.wdk.service.service.SystemService;
@Priority(30)
public class CheckLoginFilter implements ContainerRequestFilter, ContainerResponseFilter {
- public static final String SESSION_COOKIE_TO_SET = "sessionCookieToSet";
+ private static final Logger LOG = Logger.getLogger(CheckLoginFilter.class);
+
+ private static final String TOKEN_COOKIE_VALUE_TO_SET = "tokenCookieValueToSet";
+
+ private static final String LEGACY_WDK_LOGIN_COOKIE_NAME = "wdk_check_auth";
@Context
- protected
- ServletContext _servletContext;
+ protected ServletContext _servletContext;
@Inject
protected Provider _servletRequest;
@@ -43,23 +58,75 @@ public class CheckLoginFilter implements ContainerRequestFilter, ContainerRespon
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
-
- // skip certain endpoints to avoid a guest user being created for those endpoints
+ // skip endpoints which do not require a user; prevents guests from being unnecessarily created
String requestPath = requestContext.getUriInfo().getPath();
if (isPathToSkip(requestPath)) return;
ApplicationContext context = ContextLookup.getApplicationContext(_servletContext);
RequestData request = ContextLookup.getRequest(_servletRequest.get(), _grizzlyRequest.get());
+ UserFactory factory = ContextLookup.getWdkModel(context).getUserFactory();
+
+ // try to find submitted bearer token
+ String rawToken = findRawBearerToken(request, requestContext);
+
+ try {
+ if (rawToken == null) {
+ // no credentials submitted; automatically create a guest to use on this request
+ useNewGuest(factory, request, requestContext, requestPath);
+ }
+ else {
+ try {
+ // validate submitted token
+ ValidatedToken token = factory.validateBearerToken(rawToken);
+ User user = factory.convertToUser(token);
+ setRequestAttributes(request, token, user);
+ LOG.info("Validated successfully. Request will be processed for user " + user.getUserId() + " / " + user.getEmail());
+ }
+ catch (ExpiredTokenException e) {
+ // token is expired; use guest token for now which should inspire them to log back in
+ useNewGuest(factory, request, requestContext, requestPath);
+ }
+ catch (InvalidTokenException e) {
+ // passed token is invalid; throw 401
+ LOG.warn("Received invalid bearer token for auth: " + rawToken);
+ throw new NotAuthorizedException(Response.noContent().build());
+ }
+ }
+ }
+ catch (Exception e) {
+ // any other exception is fatal, but log first
+ LOG.error("Unable to authenticate with Authorization header " + rawToken, e);
+ throw e instanceof RuntimeException ? (RuntimeException)e : new WdkRuntimeException(e);
+ }
+ }
- Optional newCookie =
- CheckLoginFilterShared.calculateUserActions(
- findLoginCookie(requestContext.getCookies()),
- ContextLookup.getWdkModel(context),
- request.getSession(), requestPath);
+ private void useNewGuest(UserFactory factory, RequestData request, ContainerRequestContext requestContext, String requestPath) throws WdkModelException {
+ TwoTuple guestPair = factory.createUnregisteredUser();
+ ValidatedToken token = guestPair.getFirst();
+ User user = guestPair.getSecond();
+ setRequestAttributes(request, token, user);
- if (newCookie.isPresent()) {
- requestContext.setProperty(SESSION_COOKIE_TO_SET, newCookie.get().toJaxRsCookie().toString());
+ LOG.info("Created new guest user [" + user.getUserId() + "] for request to path: /" + requestPath);
+
+ // set flag indicating that cookies should be added to response containing the new token
+ requestContext.setProperty(TOKEN_COOKIE_VALUE_TO_SET, token.getTokenValue());
+ }
+
+ private void setRequestAttributes(RequestData request, ValidatedToken token, User user) {
+ // set creds and user on the request object for use by this request's processing
+ request.setAttribute(Utilities.BEARER_TOKEN_KEY, token);
+ request.setAttribute(Utilities.WDK_USER_KEY, user);
+ }
+
+ private String findRawBearerToken(RequestData request, ContainerRequestContext requestContext) {
+ String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
+ if (authHeader != null) {
+ LOG.info("Recieved Authorization header with value: " + authHeader + "; trying bearer token validation.");
+ return OAuthClient.getTokenFromAuthHeader(authHeader);
}
+ // otherwise try Authorization cookie
+ Cookie cookie = requestContext.getCookies().get(HttpHeaders.AUTHORIZATION);
+ return cookie == null ? null : cookie.getValue();
}
protected boolean isPathToSkip(String path) {
@@ -67,16 +134,22 @@ protected boolean isPathToSkip(String path) {
return SystemService.PROMETHEUS_ENDPOINT_PATH.equals(path);
}
- protected Optional findLoginCookie(Map cookies) {
- return Optional.ofNullable(cookies.get(LoginCookieFactory.WDK_LOGIN_COOKIE_NAME))
- .map(cookie -> new CookieBuilder(cookie.getName(), cookie.getValue()));
- }
-
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
- if (requestContext.getPropertyNames().contains(SESSION_COOKIE_TO_SET)) {
- responseContext.getHeaders().add(HttpHeaders.SET_COOKIE, requestContext.getProperty(SESSION_COOKIE_TO_SET));
+ MultivaluedMap headers = responseContext.getHeaders();
+ if (requestContext.getPropertyNames().contains(TOKEN_COOKIE_VALUE_TO_SET)) {
+ String tokenValue = (String)requestContext.getProperty(TOKEN_COOKIE_VALUE_TO_SET);
+
+ // set cookie value for both Authorization cookie
+ NewCookie authCookie = SessionService.getAuthCookie(tokenValue);
+ headers.add(HttpHeaders.SET_COOKIE, authCookie.toString());
}
+
+ // unset legacy WDK check auth cookie in case it is present
+ CookieBuilder cookie = new CookieBuilder(LEGACY_WDK_LOGIN_COOKIE_NAME, "");
+ cookie.setMaxAge(0);
+ cookie.setPath("/");
+ headers.add(HttpHeaders.SET_COOKIE, cookie.toJaxRsCookie().toString());
}
}
diff --git a/Service/src/main/java/org/gusdb/wdk/service/filter/LoggingContextFilter.java b/Service/src/main/java/org/gusdb/wdk/service/filter/LoggingContextFilter.java
index 866b8ff6ca..71fe96a65e 100644
--- a/Service/src/main/java/org/gusdb/wdk/service/filter/LoggingContextFilter.java
+++ b/Service/src/main/java/org/gusdb/wdk/service/filter/LoggingContextFilter.java
@@ -40,7 +40,6 @@ public void filter(ContainerRequestContext requestContext) throws IOException {
ThreadLocalLoggingVars.setIpAddress(request.getRemoteIpAddress());
ThreadLocalLoggingVars.setRequestedDomain(request.getServerName());
ThreadLocalLoggingVars.setRequestId(String.valueOf(requestId.getAndIncrement()));
- ThreadLocalLoggingVars.setSessionId(request.getSession().getId());
}
diff --git a/Service/src/main/java/org/gusdb/wdk/service/formatter/ProjectFormatter.java b/Service/src/main/java/org/gusdb/wdk/service/formatter/ProjectFormatter.java
index 466fcae614..d0abea4be9 100644
--- a/Service/src/main/java/org/gusdb/wdk/service/formatter/ProjectFormatter.java
+++ b/Service/src/main/java/org/gusdb/wdk/service/formatter/ProjectFormatter.java
@@ -1,9 +1,12 @@
package org.gusdb.wdk.service.formatter;
-import org.gusdb.fgputil.accountdb.UserPropertyName;
+import java.util.Optional;
+
+import org.gusdb.oauth2.client.veupathdb.UserProperty;
import org.gusdb.wdk.core.api.JsonKeys;
import org.gusdb.wdk.model.WdkModel;
import org.gusdb.wdk.model.config.ModelConfig;
+import org.gusdb.wdk.model.user.User;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -47,7 +50,7 @@ public static JSONObject getWdkProjectInfo(WdkModel wdkModel, String serviceEndp
// create profile property config sub-array
JSONArray userProfileProps = new JSONArray();
- for (UserPropertyName prop : wdkModel.getModelConfig().getAccountDB().getUserPropertyNames()) {
+ for (UserProperty prop : User.USER_PROPERTIES.values()) {
userProfileProps.put(new JSONObject()
.put(JsonKeys.NAME, prop.getName())
.put(JsonKeys.DISPLAY_NAME, prop.getDisplayName())
@@ -57,8 +60,7 @@ public static JSONObject getWdkProjectInfo(WdkModel wdkModel, String serviceEndp
}
return new JSONObject()
- .put(JsonKeys.DESCRIPTION, wdkModel.getIntroduction() == null ?
- WELCOME_MESSAGE : wdkModel.getIntroduction())
+ .put(JsonKeys.DESCRIPTION, Optional.ofNullable(wdkModel.getIntroduction()).orElse(WELCOME_MESSAGE))
.put(JsonKeys.DISPLAY_NAME, wdkModel.getDisplayName())
.put(JsonKeys.PROJECT_ID, wdkModel.getProjectId())
.put(JsonKeys.BUILD_NUMBER, wdkModel.getBuildNumber())
diff --git a/Service/src/main/java/org/gusdb/wdk/service/formatter/StrategyFormatter.java b/Service/src/main/java/org/gusdb/wdk/service/formatter/StrategyFormatter.java
index 4eac4458b1..9d27a70947 100644
--- a/Service/src/main/java/org/gusdb/wdk/service/formatter/StrategyFormatter.java
+++ b/Service/src/main/java/org/gusdb/wdk/service/formatter/StrategyFormatter.java
@@ -45,7 +45,7 @@ private static JSONObject getListingStrategyJson(Strategy strategy, boolean incl
.put(JsonKeys.IS_VALID, strategy.isValid())
.put(JsonKeys.IS_DELETED, strategy.isDeleted())
.put(JsonKeys.IS_EXAMPLE, strategy.isExample())
- .put(JsonKeys.ORGANIZATION, strategy.getUser().getProfileProperties().get("organization"))
+ .put(JsonKeys.ORGANIZATION, strategy.getUser().getOrganization())
.put(JsonKeys.ESTIMATED_SIZE, StepFormatter.translateEstimatedSize(strategy.getEstimatedSize()))
.put(JsonKeys.NAME_OF_FIRST_STEP, strategy.getMostPrimaryLeafStep().getDisplayName())
.put(JsonKeys.LEAF_AND_TRANSFORM_STEP_COUNT, strategy.getLeafAndTransformStepCount())
diff --git a/Service/src/main/java/org/gusdb/wdk/service/formatter/UserFormatter.java b/Service/src/main/java/org/gusdb/wdk/service/formatter/UserFormatter.java
index 7967c2978d..476f17d2dd 100644
--- a/Service/src/main/java/org/gusdb/wdk/service/formatter/UserFormatter.java
+++ b/Service/src/main/java/org/gusdb/wdk/service/formatter/UserFormatter.java
@@ -1,9 +1,8 @@
package org.gusdb.wdk.service.formatter;
-import java.util.List;
-import java.util.Map;
+import java.util.Optional;
-import org.gusdb.fgputil.accountdb.UserPropertyName;
+import org.gusdb.oauth2.client.veupathdb.UserProperty;
import org.gusdb.wdk.core.api.JsonKeys;
import org.gusdb.wdk.model.user.User;
import org.gusdb.wdk.model.user.UserPreferences;
@@ -29,27 +28,26 @@
public class UserFormatter {
public static JSONObject getUserJson(User user, boolean isOwner,
- boolean includePreferences, List propDefs) throws JSONException {
+ Optional userPreferences) throws JSONException {
JSONObject json = new JSONObject()
.put(JsonKeys.ID, user.getUserId())
.put(JsonKeys.IS_GUEST, user.isGuest());
// private fields viewable only by owner
if (isOwner) {
json.put(JsonKeys.EMAIL, user.getEmail());
- json.put(JsonKeys.PROPERTIES, getPropertiesJson(user.getProfileProperties(), propDefs, isOwner));
- if (includePreferences) {
- json.put(JsonKeys.PREFERENCES, getPreferencesJson(user.getPreferences()));
- }
+ json.put(JsonKeys.PROPERTIES, getPropertiesJson(user, isOwner));
+ userPreferences.ifPresent(prefs ->
+ json.put(JsonKeys.PREFERENCES, getPreferencesJson(prefs)));
}
return json;
}
- private static JSONObject getPropertiesJson(Map props, List propDefs, boolean isOwner) {
+ private static JSONObject getPropertiesJson(User user, boolean isOwner) {
JSONObject propsJson = new JSONObject();
- for (UserPropertyName definedProperty : propDefs) {
+ for (UserProperty definedProperty : User.USER_PROPERTIES.values()) {
if (isOwner || definedProperty.isPublic()) {
String key = definedProperty.getName();
- String value = (props.containsKey(key) ? props.get(key) : "");
+ String value = Optional.ofNullable(definedProperty.getValue(user)).orElse("");
propsJson.put(key, value);
}
}
diff --git a/Service/src/main/java/org/gusdb/wdk/service/request/user/UserCreationRequest.java b/Service/src/main/java/org/gusdb/wdk/service/request/user/UserCreationRequest.java
index 96d5a6a96f..aea61375f7 100644
--- a/Service/src/main/java/org/gusdb/wdk/service/request/user/UserCreationRequest.java
+++ b/Service/src/main/java/org/gusdb/wdk/service/request/user/UserCreationRequest.java
@@ -1,8 +1,8 @@
package org.gusdb.wdk.service.request.user;
-import java.util.List;
+import java.util.Collection;
-import org.gusdb.fgputil.accountdb.UserPropertyName;
+import org.gusdb.oauth2.client.veupathdb.UserProperty;
import org.gusdb.wdk.core.api.JsonKeys;
import org.gusdb.wdk.service.request.exception.DataValidationException;
import org.gusdb.wdk.service.request.exception.RequestMisformatException;
@@ -15,7 +15,7 @@ public class UserCreationRequest {
private final UserPreferencesRequest _globalPreferencesRequest;
private final UserPreferencesRequest _projectPreferencesRequest;
- public static UserCreationRequest createFromJson(JSONObject requestJson, List configuredProps)
+ public static UserCreationRequest createFromJson(JSONObject requestJson, Collection configuredProps)
throws RequestMisformatException, DataValidationException {
try {
JSONObject userRequest = requestJson.getJSONObject(JsonKeys.USER);
@@ -34,7 +34,6 @@ public UserCreationRequest(UserProfileRequest profileRequest, UserPreferencesReq
_profileRequest = profileRequest;
_globalPreferencesRequest = globalPreferencesRequest;
_projectPreferencesRequest = projectPreferencesRequest;
-
}
public UserProfileRequest getProfileRequest() {
@@ -44,6 +43,7 @@ public UserProfileRequest getProfileRequest() {
public UserPreferencesRequest getGlobalPreferencesRequest() {
return _globalPreferencesRequest;
}
+
public UserPreferencesRequest getProjectPreferencesRequest() {
return _projectPreferencesRequest;
}
diff --git a/Service/src/main/java/org/gusdb/wdk/service/request/user/UserDatasetShareRequest.java b/Service/src/main/java/org/gusdb/wdk/service/request/user/UserDatasetShareRequest.java
index e3a1968567..4bd5208b76 100644
--- a/Service/src/main/java/org/gusdb/wdk/service/request/user/UserDatasetShareRequest.java
+++ b/Service/src/main/java/org/gusdb/wdk/service/request/user/UserDatasetShareRequest.java
@@ -12,10 +12,8 @@
import org.apache.log4j.Logger;
import org.gusdb.fgputil.FormatUtil;
-import org.gusdb.fgputil.accountdb.AccountManager;
import org.gusdb.wdk.model.WdkModel;
-import org.gusdb.wdk.model.config.ModelConfig;
-import org.gusdb.wdk.model.config.ModelConfigAccountDB;
+import org.gusdb.wdk.model.user.UserFactory;
import org.gusdb.wdk.service.request.exception.DataValidationException;
import org.gusdb.wdk.service.request.exception.RequestMisformatException;
import org.json.JSONArray;
@@ -26,18 +24,18 @@
import com.fasterxml.jackson.databind.type.CollectionType;
/**
- * Parses the JSON object returned by either a PATCH REST request for
- * managing user dataset sharing
+ * Parses the JSON object returned by either a PATCH REST request for managing user dataset sharing
+ *
* @author crisl-adm
*
*/
public class UserDatasetShareRequest {
-
+
private static Logger LOG = Logger.getLogger(UserDatasetShareRequest.class);
-
- public static final List SHARE_TYPES = new ArrayList<>(Arrays.asList("add","delete"));
-
- private AccountManager _accountManager;
+
+ public static final List SHARE_TYPES = new ArrayList<>(Arrays.asList("add", "delete"));
+
+ private final UserFactory _userFactory;
private Map>> _userDatasetShareMap;
private List