Skip to content

Commit

Permalink
Open Access without login (#136)
Browse files Browse the repository at this point in the history
[ALS-4793] By pass Fence for Open Access
[ALS-4793] Fix User Roles
[ALS-4793] Remove unnecessary logging
[ALS-4793] Tmp Solution to potential security hole
[ALS-4793] Remove error message
[ALS-4793] Modify PSAMA to bypass fence
[ALS-4356] Support for open datasets
[ALS-4981] Validate the fence code
[ALS-4981] Handle Medium Security Findings
  • Loading branch information
Gcolon021 committed Oct 10, 2023
1 parent 44833bd commit e1cd09b
Show file tree
Hide file tree
Showing 9 changed files with 319 additions and 153 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@


import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.MapType;
import edu.harvard.hms.dbmi.avillach.auth.data.entity.Connection;
import edu.harvard.hms.dbmi.avillach.auth.data.entity.Privilege;
import edu.harvard.hms.dbmi.avillach.auth.data.entity.Role;
Expand All @@ -11,7 +10,6 @@
import edu.harvard.hms.dbmi.avillach.auth.data.repository.RoleRepository;
import edu.harvard.hms.dbmi.avillach.auth.rest.TokenService;
import io.swagger.jaxrs.config.BeanConfig;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
Expand All @@ -28,13 +26,10 @@
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.SecurityContext;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import javax.net.ssl.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static edu.harvard.hms.dbmi.avillach.auth.utils.AuthNaming.AuthRoleNaming.ADMIN;
import static edu.harvard.hms.dbmi.avillach.auth.utils.AuthNaming.AuthRoleNaming.SUPER_ADMIN;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,152 +13,198 @@
import javax.persistence.NonUniqueResultException;
import javax.persistence.criteria.*;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;

/**
* <p>Provides operations for the User entity to interact with a database.</p>
*
* @see User
*/
@Transactional
@ApplicationScoped
public class UserRepository extends BaseRepository<User, UUID> {

private Logger logger = LoggerFactory.getLogger(UserRepository.class);

protected UserRepository() {
super(User.class);
}

public User findBySubject(String subject) {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();
return em.createQuery(query
.where(
eq(cb, queryRoot, "subject", subject)))
.getSingleResult();
}

public User findBySubjectAndConnection(String subject, String connectionId){
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();
try {
private Logger logger = LoggerFactory.getLogger(UserRepository.class);

protected UserRepository() {
super(User.class);
}

public User findBySubject(String subject) {
try {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();
return em.createQuery(query
.where(
eq(cb, queryRoot, "subject", subject)))
.getSingleResult();
} catch (NoResultException e) {
return null;
}
}

public User findBySubjectAndConnection(String subject, String connectionId) {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();
try {
return em.createQuery(query
.where(
cb.and(
cb.equal(queryRoot.join("connection")
.get("id"), connectionId),
eq(cb, queryRoot, "subject", subject))))
.where(
cb.and(
cb.equal(queryRoot.join("connection")
.get("id"), connectionId),
eq(cb, queryRoot, "subject", subject))))
.getSingleResult();
} catch (NoResultException e){
return null;
} catch (NoResultException e) {
return null;
}
}

public List<User> listUnmatchedByConnectionId(Connection connection) {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();
return em.createQuery(query
.where(
cb.and(
eq(cb, queryRoot, "connection", connection),
eq(cb, queryRoot, "matched", false))))
.getResultList();
}

/**
* @return
*/
public User findOrCreate(User inputUser) {
User user = null;
String subject = inputUser.getSubject();
try {
user = findBySubject(subject);
logger.info("findOrCreate(), trying to find user: {subject: " + subject +
"}, and found a user with uuid: " + user.getUuid()
+ ", subject: " + user.getSubject());
} catch (NoResultException e) {
logger.debug("findOrCreate() subject " + subject +
" could not be found by `entityManager`, going to create a new user.");
user = createUser(inputUser);
} catch (NonUniqueResultException e) {
logger.error("findOrCreate() " + e.getClass().getSimpleName() + ": " + e.getMessage());
}
return user;
}

private User createUser(User inputUser) {
String subject = inputUser.getSubject();
logger.debug("createUser() creating user, subject: " + subject + " ......");
em().persist(inputUser);

User result = getById(inputUser.getUuid());
if (result != null)
logger.info("createUser() created user, uuid: " + result.getUuid()
+ ", subject: " + subject
+ ", role: " + result.getRoleString()
+ ", privilege: " + result.getPrivilegeString());

return result;
}

public User changeRole(User user, Set<Role> roles) {
logger.info("Starting changing the role of user: " + user.getUuid()
+ ", with subject: " + user.getSubject() + ", to " + roles.stream().map(role -> role.getName()).collect(Collectors.joining(",")));
user.setRoles(roles);
em().merge(user);
User updatedUser = getById(user.getUuid());
logger.info("User: " + updatedUser.getUuid() + ", with subject: " +
updatedUser.getSubject() + ", now has a new role: " + updatedUser.getRoleString());
return updatedUser;
}

@Override
public void persist(User user) {
findOrCreate(user);
}

public User findByEmail(String email) {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();
return em.createQuery(query
.where(
eq(cb, queryRoot, "email", email)))
.getSingleResult();
}

public boolean checkAgainstTOSDate(String userId) {
CriteriaQuery<User> query = cb().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();

Subquery<Date> subquery = query.subquery(Date.class);
Root<TermsOfService> tosRoot = subquery.from(TermsOfService.class);
subquery.select(cb.greatest(tosRoot.<Date>get("dateUpdated")));

return !em.createQuery(query
.where(
cb.and(
eq(cb, queryRoot, "subject", userId),
cb.greaterThanOrEqualTo(queryRoot.get("acceptedTOS"), subquery))))
.getResultList().isEmpty();
}

/**
* @param uuid the uuid of the user to find
* @return the user with the given uuid, or null if no user is found
*/
public User findByUUID(UUID uuid) {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();
try {
return em.createQuery(query
.where(
eq(cb, queryRoot, "uuid", uuid)))
.getSingleResult();
} catch (NoResultException e) {
logger.error("findByUUID() " + e.getClass().getSimpleName() + ": " + e.getMessage());
}
}

public List<User> listUnmatchedByConnectionId(Connection connection) {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();
return em.createQuery(query
.where(
cb.and(
eq(cb, queryRoot, "connection", connection),
eq(cb, queryRoot, "matched", false))))
.getResultList();
}

/**
*
* @return
*/
public User findOrCreate(User inputUser) {
User user = null;
String subject = inputUser.getSubject();
try{
user = findBySubject(subject);
logger.info("findOrCreate(), trying to find user: {subject: " + subject+
"}, and found a user with uuid: " + user.getUuid()
+ ", subject: " + user.getSubject());
} catch (NoResultException e) {
logger.debug("findOrCreate() subject " + subject +
" could not be found by `entityManager`, going to create a new user.");
user = createUser(inputUser);
}catch(NonUniqueResultException e){
logger.error("findOrCreate() " + e.getClass().getSimpleName() + ": " + e.getMessage());
}
return user;
}

private User createUser(User inputUser) {
String subject = inputUser.getSubject();
// if (subject == null && userId == null){
// logger.error("createUser() cannot create user when both subject and userId are null");
// return null;
// }
logger.debug("createUser() creating user, subject: " + subject + " ......");
em().persist(inputUser);

User result = getById(inputUser.getUuid());
if (result != null)
logger.info("createUser() created user, uuid: " + result.getUuid()
+ ", subject: " + subject
+ ", role: " + result.getRoleString()
+ ", privilege: "+ result.getPrivilegeString());

return result;
}

public User changeRole(User user, Set<Role> roles){
logger.info("Starting changing the role of user: " + user.getUuid()
+ ", with subject: " + user.getSubject() + ", to " + roles.stream().map(role -> role.getName()).collect(Collectors.joining(",")));
user.setRoles(roles);
em().merge(user);
User updatedUser = getById(user.getUuid());
logger.info("User: " + updatedUser.getUuid() + ", with subject: " +
updatedUser.getSubject() + ", now has a new role: " + updatedUser.getRoleString());
return updatedUser;
}

@Override
public void persist(User user) {
findOrCreate(user);
}

public User findByEmail(String email) {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();
return em.createQuery(query
.where(
eq(cb, queryRoot, "email", email)))
.getSingleResult();
}

public boolean checkAgainstTOSDate(String userId){
CriteriaQuery<User> query = cb().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();

Subquery<Date> subquery = query.subquery(Date.class);
Root<TermsOfService> tosRoot = subquery.from(TermsOfService.class);
subquery.select(cb.greatest(tosRoot.<Date>get("dateUpdated")));

return !em.createQuery(query
.where(
cb.and(
eq(cb, queryRoot, "subject", userId),
cb.greaterThanOrEqualTo(queryRoot.get("acceptedTOS"), subquery))))
.getResultList().isEmpty();
}

return null;
}

/**
* Creates a user with a subject of "open_access|{uuid}"
* and an email of "{uuid}@open_access.com"
*
* @return the created user
*/
public User createOpenAccessUser(Role openAccessRole) {
User user = new User();
em().persist(user);

user = getById(user.getUuid());
user.setSubject("open_access|" + user.getUuid().toString());
if (openAccessRole != null) {
user.setRoles(new HashSet<>(List.of(openAccessRole)));
} else {
logger.error("createOpenAccessUser() openAccessRole is null");
user.setRoles(new HashSet<>());
}
user.setEmail(user.getUuid() + "@open_access.com");
em().merge(user);

logger.info("createOpenAccessUser() created user, uuid: " + user.getUuid()
+ ", subject: " + user.getSubject()
+ ", role: " + user.getRoleString()
+ ", privilege: " + user.getPrivilegeString()
+ ", email: " + user.getEmail());
return user;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ public class AuthService {

private Logger logger = LoggerFactory.getLogger(this.getClass());

@Inject
AuthorizationService authorizationService;

@Inject
AuthenticationService authenticationService;

Expand Down
Loading

0 comments on commit e1cd09b

Please sign in to comment.