Skip to content

Commit

Permalink
Merge branch 'hotfix-1.4.9'
Browse files Browse the repository at this point in the history
  • Loading branch information
arteymix committed Feb 20, 2022
2 parents f1716bd + eb930ff commit a45b701
Show file tree
Hide file tree
Showing 24 changed files with 239 additions and 126 deletions.
8 changes: 2 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>ubc.pavlab</groupId>
<artifactId>rdp</artifactId>
<version>1.4.8</version>
<version>1.4.9</version>

<developers>
<developer>
Expand Down Expand Up @@ -52,7 +52,6 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

<!-- Spring Framework Caching Support -->
Expand All @@ -69,13 +68,11 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-docs</artifactId>
<optional>true</optional>
</dependency>

<!-- JPA Data (We are going to use Repositories, Entities, Hibernate, etc...) -->
Expand Down Expand Up @@ -122,7 +119,6 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>

<dependency>
Expand All @@ -135,7 +131,7 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
<version>2.11.0</version>
</dependency>

<!-- Testing Support -->
Expand Down
21 changes: 10 additions & 11 deletions src/main/java/ubc/pavlab/rdp/controllers/ApiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import ubc.pavlab.rdp.settings.SiteSettings;

import javax.servlet.http.HttpServletRequest;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -116,12 +115,12 @@ public Object getUsers( @RequestHeader(value = HttpHeaders.AUTHORIZATION, requir
checkAuth( authorizationHeader, auth );
if ( applicationSettings.getPrivacy().isEnableAnonymizedSearchResults() ) {
final Authentication auth2 = SecurityContextHolder.getContext().getAuthentication();
return userService.findAllByIsEnabledNoAuth( pageable )
return userService.findByEnabledTrueNoAuth( pageable )
.map( user -> permissionEvaluator.hasPermission( auth2, user, "read" ) ? user : userService.anonymizeUser( user ) )
.map( user -> initUser( user, locale ) );

} else {
return userService.findAllByPrivacyLevel( PrivacyLevelType.PUBLIC, pageable ).map( user -> initUser( user, locale ) );
return userService.findByEnabledTrueAndPrivacyLevelNoAuth( PrivacyLevelType.PUBLIC, pageable ).map( user -> initUser( user, locale ) );
}
}

Expand All @@ -138,11 +137,11 @@ public Object getGenes( @RequestHeader(value = HttpHeaders.AUTHORIZATION, requir
checkAuth( authorizationHeader, auth );
if ( applicationSettings.getPrivacy().isEnableAnonymizedSearchResults() ) {
final Authentication auth2 = SecurityContextHolder.getContext().getAuthentication();
return userGeneService.findAllNoAuth( pageable )
return userGeneService.findByUserEnabledTrueNoAuth( pageable )
.map( userGene -> permissionEvaluator.hasPermission( auth2, userGene, "read" ) ? userGene : userService.anonymizeUserGene( userGene ) )
.map( userGene -> initUserGene( userGene, locale ) );
} else {
return userGeneService.findAllByPrivacyLevel( PrivacyLevelType.PUBLIC, pageable ).map( userGene -> initUserGene( userGene, locale ) );
return userGeneService.findByUserEnabledTrueAndPrivacyLevelNoAuth( PrivacyLevelType.PUBLIC, pageable ).map( userGene -> initUserGene( userGene, locale ) );
}
}

Expand Down Expand Up @@ -197,13 +196,13 @@ public Object searchUsersByGeneSymbol( @RequestParam String symbol,
Taxon taxon = taxonService.findById( taxonId );

if ( taxon == null ) {
return ResponseEntity.notFound().build();
throw new ApiException( HttpStatus.NOT_FOUND, String.format( locale, "Unknown taxon ID: %s.", taxonId ) );
}

GeneInfo gene = geneService.findBySymbolAndTaxon( symbol, taxon );

if ( gene == null ) {
return ResponseEntity.notFound().build();
throw new ApiException( HttpStatus.NOT_FOUND, String.format( locale, "Unknown gene with symbol: %s.", symbol ) );
}

if ( tiers == null ) {
Expand All @@ -217,7 +216,7 @@ public Object searchUsersByGeneSymbol( @RequestParam String symbol,

// Check if there is an ortholog request for a different taxon than the original gene
if ( orthologTaxon != null && !orthologTaxon.equals( gene.getTaxon() ) && orthologs.isEmpty() ) {
return new ResponseEntity<>( messageSource.getMessage( "ApiController.noOrthologsWithGivenParameters", null, locale ), null, HttpStatus.NOT_FOUND );
throw new ApiException( HttpStatus.NOT_FOUND, messageSource.getMessage( "ApiController.noOrthologsWithGivenParameters", null, locale ) );
}

return initUserGenes( userGeneService.handleGeneSearch( gene, restrictTiers( tiers ), orthologTaxon, researcherPositions, researcherCategories, organsFromUberonIds( organUberonIds ) ), locale );
Expand Down Expand Up @@ -251,7 +250,7 @@ public Object searchUsersByGeneSymbol( @RequestParam String symbol,
tiers = EnumSet.of( TierType.valueOf( tier ) );
} catch ( IllegalArgumentException e ) {
log.error( "Could not parse tier type.", e );
return ResponseEntity.badRequest().body( MessageFormat.format( "Unknown tier {0}.", tier ) );
throw new ApiException( HttpStatus.BAD_REQUEST, String.format( locale, "Unknown tier: %s.", tier ), e );
}
}

Expand All @@ -267,7 +266,7 @@ public Object getUserById( @PathVariable Integer userId,
checkAuth( authorizationHeader, auth );
User user = userService.findUserById( userId );
if ( user == null ) {
return ResponseEntity.notFound().build();
throw new ApiException( HttpStatus.NOT_FOUND, String.format( locale, "Unknown user with ID: %d.", userId ) );
}
return initUser( user, locale );
}
Expand All @@ -282,7 +281,7 @@ public Object getUserByAnonymousId( @PathVariable UUID anonymousId,
checkAuth( authorizationHeader, auth );
User user = userService.findUserByAnonymousIdNoAuth( anonymousId );
if ( user == null ) {
return ResponseEntity.notFound().build();
throw new ApiException( HttpStatus.NOT_FOUND, String.format( "Unknown user with anonymous ID: %s.", anonymousId ) );
}
if ( permissionEvaluator.hasPermission( SecurityContextHolder.getContext().getAuthentication(), user, "read" ) ) {
return initUser( user, locale );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,9 @@ public ModelAndView searchOrthologsForGene( @RequestParam String symbol,
return modelAndView;
}

SortedMap<Taxon, Set<GeneInfo>> orthologMap = orthologs.stream()
.collect( Collectors.groupingBy( GeneInfo::getTaxon, TreeMap::new, Collectors.toSet() ) );
Map<Taxon, Set<GeneInfo>> orthologMap = orthologs.stream()
.sorted( Comparator.comparing( GeneInfo::getTaxon, Taxon.getComparator() ) )
.collect( Collectors.groupingBy( GeneInfo::getTaxon, LinkedHashMap::new, Collectors.toSet() ) );

modelAndView.addObject( "orthologs", orthologMap );

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/ubc/pavlab/rdp/exception/ApiException.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ public ApiException( HttpStatus status, String message ) {
super( message );
this.status = status;
}

public ApiException( HttpStatus status, String message, Throwable cause ) {
super( message, cause );
this.status = status;
}
}
8 changes: 8 additions & 0 deletions src/main/java/ubc/pavlab/rdp/model/Taxon.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import javax.persistence.*;
import java.io.Serializable;
import java.net.URL;
import java.util.Comparator;

/**
* Created by mjacobson on 17/01/18.
Expand All @@ -24,6 +25,13 @@
@ToString(of = { "id", "scientificName" })
public class Taxon implements Serializable {

public static Comparator<Taxon> getComparator() {
// taxon are ordered by the ordering field, however the ordering field is not set for remote users
// because it is ignored in JSON serialization
return Comparator.comparing( Taxon::getOrdering, Comparator.nullsLast( Comparator.naturalOrder() ) )
.thenComparing( Taxon::getCommonName );
}

@Id
@Column(name = "taxon_id")
private Integer id;
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/ubc/pavlab/rdp/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ public interface ValidationUserAccount {
public interface ValidationServiceAccount {
}

public static Comparator<User> getComparator() {
return Comparator.comparing( u -> u.getProfile().getFullName() );
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_id")
Expand Down Expand Up @@ -162,10 +166,7 @@ public boolean hasTaxon( @NonNull Taxon taxon ) {
public Set<Taxon> getTaxons() {
return this.getUserGenes().values().stream()
.map( UserGene::getTaxon )
// taxon are ordered by the ordering field, however the ordering field is not set for remote users
// because it is ignored in JSON serialization
.sorted( Comparator.comparing( Taxon::getOrdering, Comparator.nullsLast( Comparator.naturalOrder() ) )
.thenComparing( Taxon::getCommonName ) )
.sorted( Taxon.getComparator() )
.collect( Collectors.toCollection( LinkedHashSet::new ) );
}

Expand Down
20 changes: 20 additions & 0 deletions src/main/java/ubc/pavlab/rdp/model/UserGene.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@

import javax.persistence.*;
import java.text.MessageFormat;
import java.util.Comparator;
import java.util.Optional;
import java.util.UUID;

import static java.util.Comparator.*;
import static java.util.Comparator.naturalOrder;

/**
* Created by mjacobson on 17/01/18.
*/
Expand All @@ -36,6 +40,22 @@
@ToString(of = { "user", "tier", "privacyLevel" }, callSuper = true)
public class UserGene extends Gene implements UserContent {

/**
* Obtain a comparator for comparing {@link UserGene}.
*
* <ul>
* <li>by anonymity, anonymous users are displayed after</li>
* <li>by taxon, see {@link Taxon#getComparator()}</li>
* <li>by tier</li>
* <li>by user, see {@link User#getComparator()}</li>
* </ul>
*/
public static Comparator<UserGene> getComparator() {
return Comparator.comparing( UserGene::getTaxon, Taxon.getComparator() )
.thenComparing( UserGene::getTier )
.thenComparing( UserGene::getUser, User.getComparator() );
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,15 @@ public interface UserGeneRepository extends JpaRepository<UserGene, Integer> {
/**
* Find all genes from enabled users.
*/
Page<UserGene> findAllByUserEnabled( Pageable pageable );
Page<UserGene> findByUserEnabledTrue( Pageable pageable );

/**
* Select all user genes that fall within a given privacy level.
* Find all user genes that fall within a given privacy level amonng enabled users.
* <p>
* If the user gene privacy level is less strict than the profile value or null, then the profile value is taken.
*
* @param privacyLevel
* @param pageable
* @return
*/
@Query("select ug from UserGene as ug join ug.user where (case when ug.privacyLevel is null or ug.privacyLevel > ug.user.profile.privacyLevel then ug.user.profile.privacyLevel else ug.privacyLevel end) = :privacyLevel")
Page<UserGene> findAllByPrivacyLevelAndUserProfilePrivacyLevel( @Param("privacyLevel") PrivacyLevelType privacyLevel, Pageable pageable );
@Query("select ug from UserGene as ug join ug.user where ug.user.enabled is true and (case when ug.privacyLevel is null or ug.privacyLevel > ug.user.profile.privacyLevel then ug.user.profile.privacyLevel else ug.privacyLevel end) = :privacyLevel")
Page<UserGene> findByPrivacyLevelAndUserEnabledTrueAndUserProfilePrivacyLevel( @Param("privacyLevel") PrivacyLevelType privacyLevel, Pageable pageable );

@QueryHints(@QueryHint(name = "org.hibernate.cacheable", value = "true"))
UserGene findById( int id );
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ubc/pavlab/rdp/repositories/UserRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public interface UserRepository extends JpaRepository<User, Integer> {
/**
* Find all enabled users.
*/
Page<User> findAllByEnabled( Pageable pageable );
Page<User> findByEnabledTrue( Pageable pageable );

Page<User> findAllByProfilePrivacyLevel( PrivacyLevelType privacyLevel, Pageable pageable );
Page<User> findByEnabledTrueAndProfilePrivacyLevel( PrivacyLevelType privacyLevel, Pageable pageable );

@Query("select user from User user left join fetch user.roles where lower(user.email) = lower(:email)")
User findByEmailIgnoreCase( @Param("email") String email );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,17 @@ public boolean hasPermission( Authentication authentication, Object targetDomain
return privacyService.checkUserCanSearch( user, false );
} else if ( permission.equals( "international-search" ) ) {
return privacyService.checkUserCanSearch( user, true );
} else if ( targetDomainObject instanceof UserContent ) {
if ( permission.equals( "read" ) ) {
return privacyService.checkUserCanSee( user, (UserContent) targetDomainObject );
} else if ( permission.equals( "update" ) ) {
return privacyService.checkUserCanUpdate( user, (UserContent) targetDomainObject );
}
} else if ( permission.equals( "read" ) && targetDomainObject == null ) {
// null objects must be let through, so they can be handled as a 404 if necessary
return true;
} else if ( permission.equals( "read" ) && targetDomainObject instanceof UserContent ) {
return privacyService.checkUserCanSee( user, (UserContent) targetDomainObject );
} else if ( permission.equals( "update" ) && targetDomainObject instanceof UserContent ) {
return privacyService.checkUserCanUpdate( user, (UserContent) targetDomainObject );
} else {
throw new UnsupportedOperationException( "Permission " + permission + " is not supported." );
}

throw new UnsupportedOperationException( "Permission " + permission + " is not supported." );
}

@Override
Expand Down
14 changes: 7 additions & 7 deletions src/main/java/ubc/pavlab/rdp/services/RemoteResourceService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
import ubc.pavlab.rdp.model.enums.TierType;

import java.net.URI;
import java.util.Collection;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.*;

/**
* Interface for remote resource methods. These mirror methods from UserService and UserGeneService, but the implementation
Expand All @@ -33,23 +30,26 @@ public interface RemoteResourceService {
/**
* Find users by name among all partner registries.
*
* @return matching users sorted according to {@link UserService#getUserComparator()}.
* @see ApiController#searchUsersByName(String, Boolean, Set, Set, Set, String, String, Locale)
*/
Collection<User> findUsersByLikeName( String nameLike, Boolean prefix, Set<ResearcherPosition> researcherPositions, Collection<ResearcherCategory> researcherTypes, Collection<String> organUberonIds );
List<User> findUsersByLikeName( String nameLike, Boolean prefix, Set<ResearcherPosition> researcherPositions, Collection<ResearcherCategory> researcherTypes, Collection<String> organUberonIds );

/**
* Find users by description among all partner registries.
*
* @return matching users sorted according to {@link UserService#getUserComparator()}.
* @see ApiController#searchUsersByDescription(String, Set, Set, Set, String, String, Locale)
*/
Collection<User> findUsersByDescription( String descriptionLike, Set<ResearcherPosition> researcherPositions, Collection<ResearcherCategory> researcherTypes, Collection<String> organUberonIds );
List<User> findUsersByDescription( String descriptionLike, Set<ResearcherPosition> researcherPositions, Collection<ResearcherCategory> researcherTypes, Collection<String> organUberonIds );

/**
* Find genes by symbol among all partner registries.
*
* @return matching genes sorted according to {@link UserGeneService#getUserGeneComparator()}.
* @see ApiController#searchUsersByGeneSymbol(String, Integer, Set, Integer, Set, Set, Set, String, String, Locale)
*/
Collection<UserGene> findGenesBySymbol( String symbol, Taxon taxon, Set<TierType> tier, Integer orthologTaxonId, Set<ResearcherPosition> researcherPositions, Set<ResearcherCategory> researcherTypes, Set<String> organUberonIds );
List<UserGene> findGenesBySymbol( String symbol, Taxon taxon, Set<TierType> tier, Integer orthologTaxonId, Set<ResearcherPosition> researcherPositions, Set<ResearcherCategory> researcherTypes, Set<String> organUberonIds );

/**
* Retrieve a user from a specific registry.
Expand Down
Loading

0 comments on commit a45b701

Please sign in to comment.