/*
* Copyright 2015-2016 OpenCB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.opencb.opencga.catalog.managers;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
import org.opencb.commons.datastore.core.ObjectMap;
import org.opencb.commons.datastore.core.Query;
import org.opencb.commons.datastore.core.QueryOptions;
import org.opencb.commons.datastore.core.QueryResult;
import org.opencb.opencga.catalog.audit.AuditManager;
import org.opencb.opencga.catalog.audit.AuditRecord;
import org.opencb.opencga.catalog.auth.authentication.AuthenticationManager;
import org.opencb.opencga.catalog.auth.authentication.CatalogAuthenticationManager;
import org.opencb.opencga.catalog.auth.authentication.LDAPAuthenticationManager;
import org.opencb.opencga.catalog.auth.authorization.AuthorizationManager;
import org.opencb.opencga.catalog.config.AuthenticationOrigin;
import org.opencb.opencga.catalog.config.Configuration;
import org.opencb.opencga.catalog.db.DBAdaptorFactory;
import org.opencb.opencga.catalog.db.api.UserDBAdaptor;
import org.opencb.opencga.catalog.exceptions.CatalogDBException;
import org.opencb.opencga.catalog.exceptions.CatalogException;
import org.opencb.opencga.catalog.exceptions.CatalogIOException;
import org.opencb.opencga.catalog.io.CatalogIOManagerFactory;
import org.opencb.opencga.catalog.managers.api.IUserManager;
import org.opencb.opencga.catalog.models.Account;
import org.opencb.opencga.catalog.models.File;
import org.opencb.opencga.catalog.models.Session;
import org.opencb.opencga.catalog.models.User;
import org.opencb.opencga.catalog.utils.ParamUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* @author Jacobo Coll <jacobo167@gmail.com>
*/
public class UserManager extends AbstractManager implements IUserManager {
private String INTERNAL_AUTHORIZATION = "internal";
private Map<String, AuthenticationManager> authenticationManagerMap;
protected static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
+ "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
// private final SessionManager sessionManager;
protected static final Pattern EMAILPATTERN = Pattern.compile(EMAIL_PATTERN);
protected static Logger logger = LoggerFactory.getLogger(UserManager.class);
// protected final Policies.UserCreation creationUserPolicy;
public UserManager(AuthorizationManager authorizationManager, AuditManager auditManager, CatalogManager catalogManager,
DBAdaptorFactory catalogDBAdaptorFactory, CatalogIOManagerFactory ioManagerFactory,
Configuration configuration) {
super(authorizationManager, auditManager, catalogManager, catalogDBAdaptorFactory, ioManagerFactory, configuration);
authenticationManagerMap = new HashMap<>();
if (configuration.getAuthenticationOrigins() != null) {
for (AuthenticationOrigin authenticationOrigin : configuration.getAuthenticationOrigins()) {
if (authenticationOrigin.getId() != null) {
switch (authenticationOrigin.getType()) {
case LDAP:
authenticationManagerMap.put(authenticationOrigin.getId(),
new LDAPAuthenticationManager(authenticationOrigin.getHost()));
break;
// case OPENCGA:
default:
// authenticationManagerMap.put(authenticationOrigin.getId(),
// new CatalogAuthenticationManager(catalogDBAdaptorFactory, catalogConfiguration));
// INTERNAL_AUTHORIZATION = authenticationOrigin.getId();
break;
}
}
}
}
// Even if internal authentication is not present in the configuration file, create it
authenticationManagerMap.putIfAbsent(INTERNAL_AUTHORIZATION,
new CatalogAuthenticationManager(catalogDBAdaptorFactory, configuration));
AuthenticationOrigin authenticationOrigin = new AuthenticationOrigin();
if (configuration.getAuthenticationOrigins() == null) {
configuration.setAuthenticationOrigins(Arrays.asList(authenticationOrigin));
} else {
// Check if OPENCGA authentication is already present in catalog configuration
boolean catalogPresent = false;
for (AuthenticationOrigin origin : configuration.getAuthenticationOrigins()) {
if (AuthenticationOrigin.AuthenticationType.OPENCGA == origin.getType()) {
catalogPresent = true;
break;
}
}
if (!catalogPresent) {
List<AuthenticationOrigin> linkedList = new LinkedList<>();
linkedList.addAll(configuration.getAuthenticationOrigins());
linkedList.add(authenticationOrigin);
configuration.setAuthenticationOrigins(linkedList);
}
}
}
static void checkEmail(String email) throws CatalogException {
if (email == null || !EMAILPATTERN.matcher(email).matches()) {
throw new CatalogException("email not valid");
}
}
@Override
public String getId(String sessionId) throws CatalogException {
return authenticationManagerMap.get(INTERNAL_AUTHORIZATION).getUserId(sessionId);
// if (sessionId == null || sessionId.isEmpty() || sessionId.equalsIgnoreCase("anonymous")) {
// return "anonymous";
// }
// return userDBAdaptor.getUserIdBySessionId(sessionId);
}
@Override
public void changePassword(String userId, String oldPassword, String newPassword) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
// checkParameter(sessionId, "sessionId");
ParamUtils.checkParameter(oldPassword, "oldPassword");
ParamUtils.checkParameter(newPassword, "newPassword");
if (oldPassword == newPassword) {
throw new CatalogException("New password is the same as the old password.");
}
userDBAdaptor.checkId(userId);
String authOrigin = getAuthenticationOriginId(userId);
authenticationManagerMap.get(authOrigin).changePassword(userId, oldPassword, newPassword);
userDBAdaptor.updateUserLastModified(userId);
}
private String getAuthenticationOriginId(String userId) throws CatalogException {
QueryResult<User> user = userDBAdaptor.get(userId, new QueryOptions(), "");
if (user == null || user.getNumResults() == 0) {
throw new CatalogException(userId + " user not found");
}
return user.first().getAccount().getAuthOrigin();
}
private AuthenticationOrigin getAuthenticationOrigin(String authOrigin) {
if (configuration.getAuthenticationOrigins() != null) {
for (AuthenticationOrigin authenticationOrigin : configuration.getAuthenticationOrigins()) {
if (authOrigin.equals(authenticationOrigin.getId())) {
return authenticationOrigin;
}
}
}
return null;
}
@Override
public QueryResult<User> create(String id, String name, String email, String password, String organization, Long quota, String
accountType, QueryOptions options) throws CatalogException {
// Check if the users can be registered publicly or just the admin.
if (!catalogDBAdaptorFactory.getCatalogMetaDBAdaptor().isRegisterOpen()) {
String adminPassword = configuration.getAdmin().getPassword();
if (adminPassword != null && !adminPassword.isEmpty()) {
authenticationManagerMap.get(INTERNAL_AUTHORIZATION).authenticate("admin", adminPassword, true);
} else {
throw new CatalogException("The registration is closed to the public: Please talk to your administrator.");
}
}
ParamUtils.checkParameter(id, "id");
ParamUtils.checkParameter(password, "password");
ParamUtils.checkParameter(name, "name");
checkEmail(email);
organization = organization != null ? organization : "";
checkUserExists(id);
User user = new User(id, name, email, "", organization, User.UserStatus.READY);
user.getAccount().setAuthOrigin(INTERNAL_AUTHORIZATION);
// Check account type
if (accountType != null) {
if (!Account.FULL.equalsIgnoreCase(accountType) && !Account.GUEST.equalsIgnoreCase(accountType)) {
throw new CatalogException("The account type specified does not correspond with any of the valid ones. Valid account types:"
+ Account.FULL + " and " + Account.GUEST);
}
user.getAccount().setType(accountType);
}
if (quota != null && quota > 0L) {
user.setQuota(quota);
}
String userId = id;
try {
catalogIOManagerFactory.getDefault().createUser(user.getId());
QueryResult<User> queryResult = userDBAdaptor.insert(user, options);
// auditManager.recordCreation(AuditRecord.Resource.user, user.getId(), userId, queryResult.first(), null, null);
auditManager.recordAction(AuditRecord.Resource.user, AuditRecord.Action.create, AuditRecord.Magnitude.low, user.getId(), userId,
null, queryResult.first(), null, null);
authenticationManagerMap.get(INTERNAL_AUTHORIZATION).newPassword(user.getId(), password);
return queryResult;
} catch (CatalogIOException | CatalogDBException e) {
if (!userDBAdaptor.exists(user.getId())) {
logger.error("ERROR! DELETING USER! " + user.getId());
catalogIOManagerFactory.getDefault().deleteUser(user.getId());
}
throw e;
}
}
@Override
public List<QueryResult<User>> importFromExternalAuthOrigin(String authOrigin, String accountType, ObjectMap params,
String adminPassword) throws CatalogException, NamingException {
// Validate the admin password.
ParamUtils.checkParameter(adminPassword, "Admin password or session id");
authenticationManagerMap.get(INTERNAL_AUTHORIZATION).authenticate("admin", adminPassword, true);
if (INTERNAL_AUTHORIZATION.equals(authOrigin)) {
throw new CatalogException("Cannot import users from catalog. Authentication origin should be external.");
}
// Obtain the authentication origin parameters
AuthenticationOrigin authenticationOrigin = getAuthenticationOrigin(authOrigin);
if (authenticationOrigin == null) {
throw new CatalogException("The authentication origin id " + authOrigin + " does not correspond with any id in our database.");
}
// Check account type
if (accountType != null) {
if (!Account.FULL.equalsIgnoreCase(accountType) && !Account.GUEST.equalsIgnoreCase(accountType)) {
throw new CatalogException("The account type specified does not correspond with any of the valid ones. Valid account types:"
+ Account.FULL + " and " + Account.GUEST);
}
}
String type;
if (Account.GUEST.equalsIgnoreCase(accountType)) {
type = Account.GUEST;
} else {
type = Account.FULL;
}
List<String> users = params.getAsStringList("users");
if (users == null || users.size() == 0) {
throw new CatalogException("Cannot import users. List of users is empty.");
}
String userFilter;
if (users.size() == 1) {
userFilter = "(uid=" + users.get(0) + ")";
} else {
userFilter = StringUtils.join(users.toArray(), ")(uid=");
userFilter = "(|(uid=" + userFilter + "))";
}
// Obtain users from external origin
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, authenticationOrigin.getHost());
DirContext dctx = new InitialDirContext(env);
String base = ((String) authenticationOrigin.getOptions().get(AuthenticationOrigin.USERS_SEARCH));
String[] attributeFilter = { "displayname", "mail", "uid", "gecos"};
SearchControls sc = new SearchControls();
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
sc.setReturningAttributes(attributeFilter);
NamingEnumeration<SearchResult> search = dctx.search(base, userFilter, sc);
QueryOptions queryOptions = new QueryOptions();
List<QueryResult<User>> resultList = new LinkedList();
while (search.hasMore()) {
SearchResult sr = search.next();
Attributes attrs = sr.getAttributes();
String displayname = (String) attrs.get("displayname").get(0);
String mail = (String) attrs.get("mail").get(0);
String uid = (String) attrs.get("uid").get(0);
String rdn = (String) attrs.get("gecos").get(0);
// Check if the user already exists in catalog
if (userDBAdaptor.exists(uid)) {
resultList.add(new QueryResult<>(uid, -1, 0, 0, "", "User " + uid + " already exists", Collections.emptyList()));
// TODO: If the account of the user is the same, check the groups
continue;
}
// Create the users in catalog
Account account = new Account().setType(type).setAuthOrigin(authOrigin);
// TODO: Parse expiration date
// if (params.get("expirationDate") != null) {
// account.setExpirationDate(...);
// }
Map<String, Object> attributes = new HashMap<>();
attributes.put("LDAP_RDN", rdn);
User user = new User(uid, displayname, mail, "", base, account, User.UserStatus.READY, "", -1, -1, new ArrayList<>(),
new ArrayList<>(), new ArrayList<>(), new HashMap<>(), attributes);
QueryResult<User> userQueryResult = userDBAdaptor.insert(user, queryOptions);
userQueryResult.setId(uid);
resultList.add(userQueryResult);
}
return resultList;
}
private void checkGroupsFromExternalUser(String userId, List<String> groupIds, List<String> studyIds) throws CatalogException {
for (String studyStr : studyIds) {
long studyId = catalogManager.getStudyManager().getId(userId, studyStr);
if (studyId < 1) {
throw new CatalogException("Study " + studyStr + " not found.");
}
// TODO: What do we do with admin session id when logging in? We will need to update the groups.
//catalogManager.getSessionManager().createToken("admin", "private")
// for (String groupId : groupIds) {
// try {
// catalogManager.getStudyManager().updateGroup(Long.toString(studyId), groupId, userId, null, null, )
// } catch (CatalogDBException e) {
// // The user already belonged to the group.
// } catch (CatalogException e) {
// // The group does not exist.
// }
// }
}
}
@Override
public QueryResult<User> get(String userId, QueryOptions options, String sessionId) throws CatalogException {
return get(userId, null, options, sessionId);
}
@Override
public QueryResult<User> get(String userId, String lastModified, QueryOptions options, String sessionId)
throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
checkSessionId(userId, sessionId);
options = ParamUtils.defaultObject(options, QueryOptions::new);
if (!options.containsKey(QueryOptions.INCLUDE) || options.get(QueryOptions.INCLUDE) == null) {
List<String> excludeList;
if (options.containsKey(QueryOptions.EXCLUDE)) {
List<String> asStringList = options.getAsStringList(QueryOptions.EXCLUDE, ",");
excludeList = new ArrayList<>(asStringList.size() + 3);
excludeList.addAll(asStringList);
} else {
excludeList = new ArrayList<>(3);
}
excludeList.add(UserDBAdaptor.QueryParams.SESSIONS.key());
excludeList.add(UserDBAdaptor.QueryParams.PASSWORD.key());
if (!excludeList.contains(UserDBAdaptor.QueryParams.PROJECTS.key())) {
excludeList.add("projects.studies.variableSets");
}
options.put(QueryOptions.EXCLUDE, excludeList);
}
QueryResult<User> user = userDBAdaptor.get(userId, options, lastModified);
return user;
}
@Override
public QueryResult<User> get(Query query, QueryOptions options, String sessionId) throws CatalogException {
throw new UnsupportedOperationException();
}
/**
* Modify some params from the user profile.
* name
* email
* organization
* attributes
*
* @throws CatalogException
*/
@Override
public QueryResult<User> update(String userId, ObjectMap parameters, QueryOptions options, String sessionId)
throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkObj(parameters, "parameters");
if (sessionId != null && !sessionId.isEmpty()) {
ParamUtils.checkParameter(sessionId, "sessionId");
checkSessionId(userId, sessionId);
for (String s : parameters.keySet()) {
if (!s.matches("name|email|organization|attributes")) {
throw new CatalogDBException("Parameter '" + s + "' can't be changed");
}
}
} else {
if (configuration.getAdmin().getPassword() == null || configuration.getAdmin().getPassword().isEmpty()) {
throw new CatalogException("Nor the administrator password nor the session id could be found. The user could not be "
+ "updated.");
}
authenticationManagerMap.get(INTERNAL_AUTHORIZATION).authenticate("admin", configuration.getAdmin().getPassword(), true);
}
if (parameters.containsKey("email")) {
checkEmail(parameters.getString("email"));
}
userDBAdaptor.updateUserLastModified(userId);
QueryResult<User> queryResult = userDBAdaptor.update(userId, parameters);
auditManager.recordUpdate(AuditRecord.Resource.user, userId, userId, parameters, null, null);
return queryResult;
}
@Override
public List<QueryResult<User>> delete(String userIdList, QueryOptions options, String sessionId) throws CatalogException {
ParamUtils.checkParameter(userIdList, "userIdList");
List<String> userIds = Arrays.asList(userIdList.split(","));
List<QueryResult<User>> deletedUsers = new ArrayList<>(userIds.size());
for (String userId : userIds) {
if (sessionId != null && !sessionId.isEmpty()) {
ParamUtils.checkParameter(sessionId, "sessionId");
checkSessionId(userId, sessionId);
} else {
if (configuration.getAdmin().getPassword() == null || configuration.getAdmin().getPassword().isEmpty()) {
throw new CatalogException("Nor the administrator password nor the session id could be found. The user could not be "
+ "deleted.");
}
authenticationManagerMap.get(INTERNAL_AUTHORIZATION)
.authenticate("admin", configuration.getAdmin().getPassword(), true);
}
QueryResult<User> deletedUser = userDBAdaptor.delete(userId, options);
auditManager.recordDeletion(AuditRecord.Resource.user, userId, userId, deletedUser.first(), null, null);
deletedUsers.add(deletedUser);
}
return deletedUsers;
}
@Override
public List<QueryResult<User>> delete(Query query, QueryOptions options, String sessionId) throws CatalogException, IOException {
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, UserDBAdaptor.QueryParams.ID.key());
QueryResult<User> userQueryResult = userDBAdaptor.get(query, queryOptions);
List<String> userIds = userQueryResult.getResult().stream().map(User::getId).collect(Collectors.toList());
String userIdStr = StringUtils.join(userIds, ",");
return delete(userIdStr, options, sessionId);
}
@Override
public List<QueryResult<User>> restore(String ids, QueryOptions options, String sessionId) throws CatalogException {
throw new UnsupportedOperationException();
}
@Override
public List<QueryResult<User>> restore(Query query, QueryOptions options, String sessionId) throws CatalogException {
throw new UnsupportedOperationException();
}
@Override
public QueryResult rank(Query query, String field, int numResults, boolean asc, String sessionId) throws CatalogException {
throw new UnsupportedOperationException("User: Operation not supported.");
}
@Override
public QueryResult groupBy(Query query, String field, QueryOptions options, String sessionId) throws CatalogException {
throw new UnsupportedOperationException("User: Operation not supported.");
}
@Override
public QueryResult groupBy(Query query, List<String> fields, QueryOptions options, String sessionId) throws CatalogException {
throw new UnsupportedOperationException("User: Operation not supported.");
}
@Override
public void setStatus(String id, String status, String message, String sessionId) throws CatalogException {
throw new NotImplementedException("User: Operation not yet supported");
}
@Override
public QueryResult resetPassword(String userId, String sessionId) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
checkSessionId(userId, sessionId);
String authOrigin = getAuthenticationOriginId(userId);
return authenticationManagerMap.get(authOrigin).resetPassword(userId);
}
@Override
public void validatePassword(String userId, String password, boolean throwException) throws CatalogException {
if (userId.equalsIgnoreCase("admin")) {
authenticationManagerMap.get(INTERNAL_AUTHORIZATION).authenticate("admin", password, throwException);
} else {
String authOrigin = getAuthenticationOriginId(userId);
authenticationManagerMap.get(authOrigin).authenticate(userId, password, throwException);
}
}
@Deprecated
@Override
public QueryResult<ObjectMap> loginAsAnonymous(String sessionIp)
throws CatalogException, IOException {
ParamUtils.checkParameter(sessionIp, "sessionIp");
Session session = new Session(sessionIp, 20);
String userId = "anonymous_" + session.getId();
// TODO sessionID should be created here
catalogIOManagerFactory.getDefault().createAnonymousUser(userId);
try {
return userDBAdaptor.loginAsAnonymous(session);
} catch (CatalogDBException e) {
catalogIOManagerFactory.getDefault().deleteUser(userId);
throw e;
}
}
@Override
public QueryResult<Session> login(String userId, String password, String sessionIp) throws CatalogException, IOException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(password, "password");
ParamUtils.checkParameter(sessionIp, "sessionIp");
String authId;
QueryResult<User> user = null;
if (!userId.equals("admin")) {
user = userDBAdaptor.get(userId, new QueryOptions(), null);
if (user.getNumResults() == 0) {
throw new CatalogException("The user id " + userId + " does not exist.");
}
// Check that the authentication id is valid
authId = getAuthenticationOriginId(userId);
} else {
authId = INTERNAL_AUTHORIZATION;
}
AuthenticationOrigin authenticationOrigin = getAuthenticationOrigin(authId);
if (authenticationOrigin == null) {
throw new CatalogException("Could not find authentication origin " + authId + " for user " + userId);
}
if (AuthenticationOrigin.AuthenticationType.LDAP == authenticationOrigin.getType()) {
if (user == null) {
throw new CatalogException("Internal error: This error should never happen.");
}
authenticationManagerMap.get(authId).authenticate(((String) user.first().getAttributes().get("LDAP_RDN")), password, true);
} else {
authenticationManagerMap.get(authId).authenticate(userId, password, true);
}
QueryResult<Session> sessionTokenQueryResult;
try {
sessionTokenQueryResult = catalogManager.getSessionManager().createToken(userId, sessionIp, Session.Type.USER);
} catch (CatalogException e) {
auditManager.recordAction(AuditRecord.Resource.user, AuditRecord.Action.login, AuditRecord.Magnitude.high, userId, userId,
null, null, "Unsuccessfully login attempt", null);
throw e;
}
auditManager.recordAction(AuditRecord.Resource.user, AuditRecord.Action.login, AuditRecord.Magnitude.low, userId, userId, null,
sessionTokenQueryResult.first(), "User successfully logged in", null);
return sessionTokenQueryResult;
}
@Override
public QueryResult<Session> getNewUserSession(String sessionId, String userId) throws CatalogException {
authenticationManagerMap.get(INTERNAL_AUTHORIZATION).authenticate("admin", sessionId, true);
return catalogManager.getSessionManager().createToken(userId, "localhost", Session.Type.SYSTEM);
}
@Override
public QueryResult logout(String userId, String sessionId) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
checkSessionId(userId, sessionId);
QueryResult<Session> logout;
try {
logout = userDBAdaptor.logout(userId, sessionId);
} catch (CatalogDBException e) {
auditManager.recordAction(AuditRecord.Resource.user, AuditRecord.Action.logout, AuditRecord.Magnitude.high, userId, userId,
null, null, "Unsuccessfully logout attempt", null);
throw e;
}
auditManager.recordAction(AuditRecord.Resource.user, AuditRecord.Action.logout, AuditRecord.Magnitude.low, userId, userId,
logout.first(), null, "User successfully logged out", null);
return logout;
// switch (authorizationManager.getUserRole(userId)) {
// case ANONYMOUS:
// return logoutAnonymous(sessionId);
// default:
//// List<Session> sessions = Collections.singletonList(sessionManager.logout(userId, sessionId));
//// return new QueryResult<>("logout", 0, 1, 1, "", "", sessions);
// return userDBAdaptor.logout(userId, sessionId);
// }
}
@Deprecated
@Override
public QueryResult logoutAnonymous(String sessionId) throws CatalogException {
ParamUtils.checkParameter(sessionId, "sessionId");
String userId = getId(sessionId);
ParamUtils.checkParameter(userId, "userId");
checkSessionId(userId, sessionId);
logger.info("logout anonymous user. userId: " + userId + " sesionId: " + sessionId);
catalogIOManagerFactory.getDefault().deleteAnonymousUser(userId);
return userDBAdaptor.logoutAnonymous(sessionId);
}
@Override
public QueryResult<User.Filter> addFilter(String userId, String sessionId, String name, String description, File.Bioformat bioformat,
Query query, QueryOptions queryOptions) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
ParamUtils.checkParameter(name, "name");
ParamUtils.checkObj(bioformat, "bioformat");
ParamUtils.checkObj(query, "Query");
ParamUtils.checkObj(queryOptions, "QueryOptions");
if (description == null) {
description = "";
}
String userIdAux = getId(sessionId);
userDBAdaptor.checkId(userId);
if (!userId.equals(userIdAux)) {
throw new CatalogException("User " + userIdAux + " is not authorised to store filters for user " + userId);
}
Query queryExists = new Query()
.append(UserDBAdaptor.QueryParams.ID.key(), userId)
.append(UserDBAdaptor.QueryParams.CONFIGS_FILTERS_NAME.key(), name);
if (userDBAdaptor.count(queryExists).first() > 0) {
throw new CatalogException("There already exists a filter called " + name + " for user " + userId);
}
User.Filter filter = new User.Filter(name, description, bioformat, query, queryOptions);
return userDBAdaptor.addFilter(userId, filter);
}
@Override
public QueryResult<User.Filter> updateFilter(String userId, String sessionId, String name, ObjectMap params) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
ParamUtils.checkParameter(name, "name");
String userIdAux = getId(sessionId);
userDBAdaptor.checkId(userId);
if (!userId.equals(userIdAux)) {
throw new CatalogException("User " + userIdAux + " is not authorised to update filters for user " + userId);
}
Query queryExists = new Query()
.append(UserDBAdaptor.QueryParams.ID.key(), userId)
.append(UserDBAdaptor.QueryParams.CONFIGS_FILTERS_NAME.key(), name);
if (userDBAdaptor.count(queryExists).first() == 0) {
throw new CatalogException("There is no filter called " + name + " for user " + userId);
}
QueryResult<Long> queryResult = userDBAdaptor.updateFilter(userId, name, params);
User.Filter filter = getFilter(userId, name);
if (filter == null) {
throw new CatalogException("Internal error: The filter " + name + " could not be found.");
}
return new QueryResult<>("Update filter", queryResult.getDbTime(), 1, 1, queryResult.getWarningMsg(), queryResult.getErrorMsg(),
Arrays.asList(filter));
}
@Override
public QueryResult<User.Filter> deleteFilter(String userId, String sessionId, String name) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
ParamUtils.checkParameter(name, "name");
String userIdAux = getId(sessionId);
userDBAdaptor.checkId(userId);
if (!userId.equals(userIdAux)) {
throw new CatalogException("User " + userIdAux + " is not authorised to delete filters for user " + userId);
}
User.Filter filter = getFilter(userId, name);
if (filter == null) {
throw new CatalogException("There is no filter called " + name + " for user " + userId);
}
QueryResult<Long> queryResult = userDBAdaptor.deleteFilter(userId, name);
return new QueryResult<>("Delete filter", queryResult.getDbTime(), 1, 1, queryResult.getWarningMsg(), queryResult.getErrorMsg(),
Arrays.asList(filter));
}
@Override
public QueryResult<User.Filter> getFilter(String userId, String sessionId, String name) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
ParamUtils.checkParameter(name, "name");
String userIdAux = getId(sessionId);
userDBAdaptor.checkId(userId);
if (!userId.equals(userIdAux)) {
throw new CatalogException("User " + userIdAux + " is not authorised to get filters from user " + userId);
}
User.Filter filter = getFilter(userId, name);
if (filter == null) {
return new QueryResult<>("Get filter", 0, 0, 0, "", "Filter not found", Arrays.asList());
} else {
return new QueryResult<>("Get filter", 0, 1, 1, "", "", Arrays.asList(filter));
}
}
@Override
public QueryResult<User.Filter> getAllFilters(String userId, String sessionId) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
String userIdAux = getId(sessionId);
userDBAdaptor.checkId(userId);
if (!userId.equals(userIdAux)) {
throw new CatalogException("User " + userIdAux + " is not authorised to get filters from user " + userId);
}
Query query = new Query()
.append(UserDBAdaptor.QueryParams.ID.key(), userId);
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, UserDBAdaptor.QueryParams.CONFIGS.key());
QueryResult<User> userQueryResult = userDBAdaptor.get(query, queryOptions);
if (userQueryResult.getNumResults() != 1) {
throw new CatalogException("Internal error: User " + userId + " not found.");
}
List<User.Filter> filters = userQueryResult.first().getConfigs().getFilters();
return new QueryResult<>("Get filters", 0, filters.size(), filters.size(), "", "", filters);
}
@Override
public QueryResult setConfig(String userId, String sessionId, String name, ObjectMap config) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
ParamUtils.checkParameter(name, "name");
ParamUtils.checkObj(config, "ObjectMap");
String userIdAux = getId(sessionId);
userDBAdaptor.checkId(userId);
if (!userId.equals(userIdAux)) {
throw new CatalogException("User " + userIdAux + " is not authorised to set configuration for user " + userId);
}
return userDBAdaptor.setConfig(userId, name, config);
}
@Override
public QueryResult deleteConfig(String userId, String sessionId, String name) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
ParamUtils.checkParameter(name, "name");
String userIdAux = getId(sessionId);
userDBAdaptor.checkId(userId);
if (!userId.equals(userIdAux)) {
throw new CatalogException("User " + userIdAux + " is not authorised to delete the configuration of user " + userId);
}
QueryOptions options = new QueryOptions(QueryOptions.INCLUDE, UserDBAdaptor.QueryParams.CONFIGS.key());
QueryResult<User> userQueryResult = userDBAdaptor.get(userId, options, "");
if (userQueryResult.getNumResults() == 0) {
throw new CatalogException("Internal error: Could not get user " + userId);
}
User.UserConfiguration configs = userQueryResult.first().getConfigs();
if (configs == null) {
throw new CatalogException("Internal error: Configuration object is null.");
}
if (configs.get(name) == null) {
throw new CatalogException("Error: Cannot delete configuration with name " + name + ". Configuration name not found.");
}
QueryResult<Long> queryResult = userDBAdaptor.deleteConfig(userId, name);
return new QueryResult("Delete configuration", queryResult.getDbTime(), 1, 1, "", "", Arrays.asList(configs.get(name)));
}
@Override
public QueryResult getConfig(String userId, String sessionId, String name) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(sessionId, "sessionId");
ParamUtils.checkParameter(name, "name");
String userIdAux = getId(sessionId);
userDBAdaptor.checkId(userId);
if (!userId.equals(userIdAux)) {
throw new CatalogException("User " + userIdAux + " is not authorised to fetch the configuration of user " + userId);
}
QueryOptions options = new QueryOptions(QueryOptions.INCLUDE, UserDBAdaptor.QueryParams.CONFIGS.key());
QueryResult<User> userQueryResult = userDBAdaptor.get(userId, options, "");
if (userQueryResult.getNumResults() == 0) {
throw new CatalogException("Internal error: Could not get user " + userId);
}
User.UserConfiguration configs = userQueryResult.first().getConfigs();
if (configs == null) {
throw new CatalogException("Internal error: Configuration object is null.");
}
if (configs.get(name) == null) {
throw new CatalogException("Error: Cannot fetch configuration with name " + name + ". Configuration name not found.");
}
return new QueryResult("Get configuration", userQueryResult.getDbTime(), 1, 1, userQueryResult.getWarningMsg(),
userQueryResult.getErrorMsg(), Arrays.asList(configs.get(name)));
}
private User.Filter getFilter(String userId, String name) throws CatalogException {
Query query = new Query()
.append(UserDBAdaptor.QueryParams.ID.key(), userId);
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, UserDBAdaptor.QueryParams.CONFIGS.key());
QueryResult<User> userQueryResult = userDBAdaptor.get(query, queryOptions);
if (userQueryResult.getNumResults() != 1) {
throw new CatalogException("Internal error: User " + userId + " not found.");
}
for (User.Filter filter : userQueryResult.first().getConfigs().getFilters()) {
if (name.equals(filter.getName())) {
return filter;
}
}
return null;
}
private void checkSessionId(String userId, String sessionId) throws CatalogException {
String userIdBySessionId = userDBAdaptor.getUserIdBySessionId(sessionId);
if (!userIdBySessionId.equals(userId)) {
throw new CatalogException("Invalid sessionId for user: " + userId);
}
}
private void checkUserExists(String userId) throws CatalogException {
if (userId.toLowerCase().equals("admin")) {
throw new CatalogException("Permission denied: It is not allowed the creation of another admin user.");
} else if (userId.toLowerCase().equals("anonymous") || userId.toLowerCase().equals("daemon") || userId.equals("*")) {
throw new CatalogException("Permission denied: Cannot create users with special treatments in catalog.");
}
if (userDBAdaptor.exists(userId)) {
throw new CatalogException("The user already exists in our database. Please, choose a different one.");
}
}
}