Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/token manager v2 #9

Merged
merged 27 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
16edd95
Update Token Manager Service
arturofigueroabim Jan 5, 2024
11a0113
Added: Token Manager services
djuarezgf Jan 5, 2024
8d27fac
Added: Recreate Services in Token Manager
djuarezgf Jan 5, 2024
7c95205
Fixed: Token Manager Logic
arturofigueroabim Jan 9, 2024
fde8b41
Update new endpoints
arturofigueroabim Jan 18, 2024
d9ea459
Added: Token Manager: Send Token and Check Status
djuarezgf Jan 23, 2024
eaa61d4
Added: Token Manager: fetch authentication script
djuarezgf Jan 23, 2024
8dbf121
Added: removeTokens
djuarezgf Jan 23, 2024
3ab9d29
Update TM Requests
arturofigueroabim Jan 30, 2024
e993acd
Added: HttpStatus in notifications of token manager
djuarezgf Jan 30, 2024
21e8f3c
Added: DataSHIELD Token Manager Job
djuarezgf Jan 31, 2024
de65a50
Added: Check Expired Active Projects Job
djuarezgf Feb 1, 2024
29669cb
Bugfix: DataSHIELD Token Manager Job
djuarezgf Feb 1, 2024
ee0cca3
Added: Check if session scope is active before creating a notificatio…
djuarezgf Feb 1, 2024
49b24e2
Add fetchTokenStatus
arturofigueroabim Feb 1, 2024
9a5fece
Added: Fetch token status and project status of token manager
djuarezgf Feb 1, 2024
81f4485
Update TM Requests
arturofigueroabim Feb 2, 2024
62689e2
Bugfix
djuarezgf Feb 2, 2024
e5fe310
Bugfix
djuarezgf Feb 2, 2024
1153e23
Added: New email if authentication script for DataSHIELD has changed
djuarezgf Feb 2, 2024
d86511b
Added: Explorer URL in CORS
djuarezgf Feb 6, 2024
ea12840
Bugfix
djuarezgf Feb 6, 2024
65c5606
Changed: Rename controller parameters constants
djuarezgf Feb 7, 2024
eccdf4b
Bugfix: getByProjectTypeAndNotProjectState
djuarezgf Feb 7, 2024
f235989
Bugfix: EmailProject
djuarezgf Feb 8, 2024
49fef76
Update Delete Requests
arturofigueroabim Feb 8, 2024
47d9113
Bugfix
djuarezgf Feb 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [0.0.1 - 2024-01-29]
## [0.0.1 - 2024-02-02]
### Added
- First version of the project
- Spring Application
Expand Down Expand Up @@ -71,6 +71,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fetch all actions
- Accept, Reject and request changes in project results
- Notification Service
- Token Manager services
- Integration in Focus and Beam
- Frontend DTO
- Email as Mime message
Expand All @@ -86,3 +87,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fetch Project States
- Fetch registered bridgeheads for project manager admin
- Add notifications for services: document, project bridgehead, project event, project, query, user
- DataSHIELD Token Manager Job
- Check Expired Active Projects Job
- Check if session scope is active before creating a notification for changing project state
- Fetch token status and project status of token manager
- New email if authentication script for DataSHIELD has changed
- Explorer URL in CORS
35 changes: 34 additions & 1 deletion src/main/java/de/samply/app/ProjectManagerConst.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public class ProjectManagerConst {
public final static String FETCH_PROJECT_ACTION = "FETCH_PROJECT_ACTION";
public final static String FETCH_PROJECT_STATES_ACTION = "FETCH_PROJECT_STATES";
public final static String FETCH_ALL_REGISTERED_BRIDGEHEADS_ACTION = "FETCH_ALL_REGISTERED_BRIDGEHEADS";
public final static String FETCH_DATASHIELD_STATUS_ACTION = "FETCH_DATASHIELD_STATUS";


// REST Services
Expand Down Expand Up @@ -125,6 +126,7 @@ public class ProjectManagerConst {
public final static String SAVE_QUERY_IN_BRIDGEHEAD = "/save-query-in-bridgehead";
public final static String SAVE_AND_EXECUTE_QUERY_IN_BRIDGEHEAD = "/save-and-execute-query-in-bridgehead";
public final static String FETCH_AUTHENTICATION_SCRIPT = "/authentication-script";
public final static String FETCH_DATASHIELD_STATUS = "/datashield-status";
public final static String FETCH_PUBLICATIONS = "/publications";
public final static String FETCH_OTHER_DOCUMENTS = "/other-documents";
public final static String FETCH_NOTIFICATIONS = "/notifications";
Expand Down Expand Up @@ -154,7 +156,7 @@ public class ProjectManagerConst {
public final static String OUTPUT_FORMAT = "output-format";
public final static String TEMPLATE_ID = "template-id";
public final static String HUMAN_READABLE = "human-readable";
public final static String EXPLORER_URL = "explorer-url";
public final static String REDIRECT_EXPLORER_URL = "explorer-url";
public final static String QUERY_CONTEXT = "query-context";

// Email context properties
Expand Down Expand Up @@ -189,6 +191,23 @@ public class ProjectManagerConst {
public final static String FOCUS_METADATA_PROJECT = "exporter";
public final static String FOCUS_TASK = "/v1/tasks";

// Token Manager Variables
public final static String TOKEN_MANAGER_ROOT = "/api";
public final static String TOKEN_MANAGER_TOKENS = "/token";
public final static String TOKEN_MANAGER_TOKEN_STATUS = "/token-status";
public final static String TOKEN_MANAGER_PROJECT = "/project";
public final static String TOKEN_MANAGER_PROJECT_STATUS = "/project-status";
public final static String TOKEN_MANAGER_SCRIPTS = "/script";
public final static String TOKEN_MANAGER_REFRESH_TOKEN = "/refreshToken";
public final static String AUTHENTICATION_SCRIPT_FILENAME_PREFIX = "authentication-script-";
public final static String AUTHENTICATION_SCRIPT_FILENAME_SUFFIX = ".r";
public final static String TOKEN_MANAGER_PARAMETER_BRIDGEHEAD = "bk";
public final static String TOKEN_MANAGER_PARAMETER_PROJECT_CODE = "project_id";
public final static String TOKEN_MANAGER_PARAMETER_EMAIL = "user_id";
public final static String TOKEN_MANAGER_PARAMETER_PROJECT_STATUS = "project_status";
public final static String TOKEN_MANAGER_PARAMETER_TOKEN_STATUS = "token_status";
public final static String TOKEN_MANAGER_PARAMETER_TOKEN_CREATED_AT = "token_created_at";


// Environment Variables
public final static String PM_ADMIN_GROUPS = "PM_ADMIN_GROUPS";
Expand Down Expand Up @@ -220,6 +239,11 @@ public class ProjectManagerConst {
public final static String FOCUS_FAILURE_STRATEGY_MAX_TRIES = "FOCUS_FAILURE_STRATEGY_MAX_TRIES";
public final static String FOCUS_URL = "FOCUS_URL";
public final static String FOCUS_API_KEY = "FOCUS_API_KEY";
public final static String TOKEN_MANAGER_URL = "TOKEN_MANAGER_URL";
public final static String ENABLE_EMAILS = "ENABLE_EMAILS";
public final static String MANAGE_TOKENS_CRON_EXPRESSION = "MANAGE_TOKENS_CRON_EXPRESSION";
public final static String CHECK_EXPIRED_ACTIVE_PROJECTS_CRON_EXPRESSION = "CHECK_EXPIRED_ACTIVE_PROJECTS_CRON_EXPRESSION";
public final static String EXPLORER_URL = "EXPLORER_URL";

// Spring Values (SV)
public final static String HEAD_SV = "${";
Expand Down Expand Up @@ -260,13 +284,22 @@ public class ProjectManagerConst {
public final static String EMAIL_TEMPLATES_DIRECTORY_SV = HEAD_SV + EMAIL_TEMPLATES_DIRECTORY + BOTTOM_SV;
public final static String EXPORT_TEMPLATES_SV = HEAD_SV + EXPORT_TEMPLATES + BOTTOM_SV;
public final static String DATASHIELD_TEMPLATES_SV = HEAD_SV + DATASHIELD_TEMPLATES + BOTTOM_SV;
public final static String TOKEN_MANAGER_URL_SV = HEAD_SV + TOKEN_MANAGER_URL + BOTTOM_SV;

public final static String FOCUS_PROJECT_MANAGER_ID_SV = HEAD_SV + FOCUS_PROJECT_MANAGER_ID + BOTTOM_SV;
public final static String FOCUS_TTL_SV = HEAD_SV + FOCUS_TTL + ":10s" + BOTTOM_SV;
public final static String FOCUS_FAILURE_STRATEGY_BACKOFF_IN_MILLISECONDS_SV =
HEAD_SV + FOCUS_FAILURE_STRATEGY_BACKOFF_IN_MILLISECONDS + ":1000" + BOTTOM_SV;
public final static String FOCUS_FAILURE_STRATEGY_MAX_TRIES_SV = HEAD_SV + FOCUS_FAILURE_STRATEGY_MAX_TRIES + ":5" + BOTTOM_SV;
public final static String FOCUS_URL_SV = HEAD_SV + FOCUS_URL + BOTTOM_SV;
public final static String FOCUS_API_KEY_SV = HEAD_SV + FOCUS_API_KEY + BOTTOM_SV;
public final static String ENABLE_EMAILS_SV = HEAD_SV + ENABLE_EMAILS + ":true" + BOTTOM_SV;
public final static String MANAGE_TOKENS_CRON_EXPRESSION_SV =
HEAD_SV + MANAGE_TOKENS_CRON_EXPRESSION + ":#{'0 0 * * * *'}" + BOTTOM_SV;
public final static String CHECK_EXPIRED_ACTIVE_PROJECTS_CRON_EXPRESSION_SV =
HEAD_SV + CHECK_EXPIRED_ACTIVE_PROJECTS_CRON_EXPRESSION + ":#{'0 0 1,13 * * *'}" + BOTTOM_SV;
public final static String EXPLORER_URL_SV = HEAD_SV + EXPLORER_URL + BOTTOM_SV;


// Others
public final static String TEST_EMAIL = "test@project-manager.com";
Expand Down
46 changes: 31 additions & 15 deletions src/main/java/de/samply/app/ProjectManagerController.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import de.samply.query.OutputFormat;
import de.samply.query.QueryFormat;
import de.samply.query.QueryService;
import de.samply.token.TokenManagerService;
import de.samply.token.DataShieldTokenManagerService;
import de.samply.user.UserService;
import de.samply.user.roles.OrganisationRole;
import de.samply.user.roles.ProjectRole;
Expand Down Expand Up @@ -62,7 +62,7 @@ public class ProjectManagerController {
private final QueryService queryService;
private final DocumentService documentService;
private final ExporterService exporterService;
private final TokenManagerService tokenManagerService;
private final DataShieldTokenManagerService dataShieldTokenManagerService;
private final ProjectService projectService;
private final ProjectBridgeheadService projectBridgeheadService;
private final NotificationService notificationService;
Expand All @@ -74,7 +74,7 @@ public ProjectManagerController(ProjectEventService projectEventService,
QueryService queryService,
DocumentService documentService,
ExporterService exporterService,
TokenManagerService tokenManagerService,
DataShieldTokenManagerService dataShieldTokenManagerService,
ProjectService projectService,
ProjectBridgeheadService projectBridgeheadService,
NotificationService notificationService,
Expand All @@ -85,7 +85,7 @@ public ProjectManagerController(ProjectEventService projectEventService,
this.queryService = queryService;
this.documentService = documentService;
this.exporterService = exporterService;
this.tokenManagerService = tokenManagerService;
this.dataShieldTokenManagerService = dataShieldTokenManagerService;
this.projectService = projectService;
this.projectBridgeheadService = projectBridgeheadService;
this.notificationService = notificationService;
Expand Down Expand Up @@ -167,9 +167,10 @@ public ResponseEntity<String> fetchProjectsBridgeheads(
}

@RoleConstraints(projectRoles = {ProjectRole.CREATOR, ProjectRole.PROJECT_MANAGER_ADMIN})
@StateConstraints(projectStates = {ProjectState.DEVELOP}, projectBridgeheadStates = {ProjectBridgeheadState.ACCEPTED})
@StateConstraints(projectStates = {ProjectState.DEVELOP})
@EmailSender(templateType = EmailTemplateType.INVITATION, recipients = {EmailRecipientType.EMAIL_ANNOTATION})
@EmailSender(templateType = EmailTemplateType.NEW_PROJECT, recipients = {EmailRecipientType.BRIDGEHEAD_ADMIN})
//TODO: Send email to PM-ADMIN, that there was a problem with the operation
@FrontendSiteModule(site = ProjectManagerConst.PROJECT_VIEW_SITE, module = ProjectManagerConst.USER_MODULE)
@FrontendAction(action = ProjectManagerConst.SET_DEVELOPER_USER_ACTION)
@PostMapping(value = ProjectManagerConst.SET_DEVELOPER_USER)
Expand All @@ -179,11 +180,11 @@ public ResponseEntity<String> setUserAsDeveloper(
@Email @RequestParam(name = ProjectManagerConst.EMAIL) String email
) {
return convertToResponseEntity(() ->
this.userService.setProjectBridgheadUserWithRole(email, projectCode, bridgehead, ProjectRole.DEVELOPER));
this.userService.setProjectBridgheadUserWithRoleAndGenerateTokensIfDataShield(email, projectCode, bridgehead, ProjectRole.DEVELOPER));
}

@RoleConstraints(organisationRoles = {OrganisationRole.PROJECT_MANAGER_ADMIN})
@StateConstraints(projectStates = {ProjectState.PILOT}, projectBridgeheadStates = {ProjectBridgeheadState.ACCEPTED})
@StateConstraints(projectStates = {ProjectState.PILOT})
@EmailSender(templateType = EmailTemplateType.INVITATION, recipients = {EmailRecipientType.EMAIL_ANNOTATION})
@EmailSender(templateType = EmailTemplateType.NEW_PROJECT, recipients = {EmailRecipientType.BRIDGEHEAD_ADMIN})
@FrontendSiteModule(site = ProjectManagerConst.PROJECT_VIEW_SITE, module = ProjectManagerConst.USER_MODULE)
Expand All @@ -195,7 +196,7 @@ public ResponseEntity<String> setUserAsPilot(
@Email @RequestParam(name = ProjectManagerConst.EMAIL) String email
) {
return convertToResponseEntity(() ->
this.userService.setProjectBridgheadUserWithRole(email, projectCode, bridgehead, ProjectRole.PILOT));
this.userService.setProjectBridgheadUserWithRoleAndGenerateTokensIfDataShield(email, projectCode, bridgehead, ProjectRole.PILOT));
}

@RoleConstraints(organisationRoles = {OrganisationRole.PROJECT_MANAGER_ADMIN})
Expand All @@ -211,7 +212,7 @@ public ResponseEntity<String> setUserAsFinal(
@Email @RequestParam(name = ProjectManagerConst.EMAIL) String email
) {
return convertToResponseEntity(() ->
this.userService.setProjectBridgheadUserWithRole(email, projectCode, bridgehead, ProjectRole.FINAL));
this.userService.setProjectBridgheadUserWithRoleAndGenerateTokensIfDataShield(email, projectCode, bridgehead, ProjectRole.FINAL));
}

@RoleConstraints(organisationRoles = {OrganisationRole.RESEARCHER})
Expand All @@ -224,7 +225,7 @@ public ResponseEntity<String> createProjectQuery(
@RequestParam(name = ProjectManagerConst.OUTPUT_FORMAT, required = false) OutputFormat outputFormat,
@RequestParam(name = ProjectManagerConst.TEMPLATE_ID, required = false) String templateId,
@RequestParam(name = ProjectManagerConst.HUMAN_READABLE, required = false) String humanReadable,
@RequestParam(name = ProjectManagerConst.EXPLORER_URL, required = false) String explorerUrl,
@RequestParam(name = ProjectManagerConst.REDIRECT_EXPLORER_URL, required = false) String explorerUrl,
@RequestParam(name = ProjectManagerConst.QUERY_CONTEXT, required = false) String queryContext
) {
return convertToResponseEntity(() ->
Expand All @@ -242,7 +243,7 @@ public ResponseEntity<String> createQueryAndDesignProject(
@RequestParam(name = ProjectManagerConst.OUTPUT_FORMAT, required = false) OutputFormat outputFormat,
@RequestParam(name = ProjectManagerConst.TEMPLATE_ID, required = false) String templateId,
@RequestParam(name = ProjectManagerConst.HUMAN_READABLE, required = false) String humanReadable,
@RequestParam(name = ProjectManagerConst.EXPLORER_URL, required = false) String explorerUrl,
@RequestParam(name = ProjectManagerConst.REDIRECT_EXPLORER_URL, required = false) String explorerUrl,
@RequestParam(name = ProjectManagerConst.PROJECT_TYPE, required = false) ProjectType projectType,
@RequestParam(name = ProjectManagerConst.QUERY_CONTEXT, required = false) String queryContext
) throws ProjectEventActionsException {
Expand All @@ -269,7 +270,7 @@ public ResponseEntity<String> editProject(
@RequestParam(name = ProjectManagerConst.OUTPUT_FORMAT, required = false) OutputFormat outputFormat,
@RequestParam(name = ProjectManagerConst.TEMPLATE_ID, required = false) String templateId,
@RequestParam(name = ProjectManagerConst.HUMAN_READABLE, required = false) String humanReadable,
@RequestParam(name = ProjectManagerConst.EXPLORER_URL, required = false) String explorerUrl,
@RequestParam(name = ProjectManagerConst.REDIRECT_EXPLORER_URL, required = false) String explorerUrl,
@RequestParam(name = ProjectManagerConst.PROJECT_TYPE, required = false) ProjectType projectType,
@RequestParam(name = ProjectManagerConst.QUERY_CONTEXT, required = false) String queryContext,
@ProjectCode @RequestParam(name = ProjectManagerConst.PROJECT_CODE) String projectCode
Expand Down Expand Up @@ -813,15 +814,30 @@ public ResponseEntity<String> saveAndExecuteQueryInBridgehead(
}

@RoleConstraints(projectRoles = {ProjectRole.DEVELOPER, ProjectRole.PILOT, ProjectRole.FINAL})
@StateConstraints(projectStates = {ProjectState.DEVELOP, ProjectState.PILOT, ProjectState.FINAL})
@StateConstraints(projectStates = {ProjectState.DEVELOP, ProjectState.PILOT, ProjectState.FINAL}, projectBridgeheadStates = {ProjectBridgeheadState.ACCEPTED})
@FrontendSiteModule(site = ProjectManagerConst.PROJECT_VIEW_SITE, module = ProjectManagerConst.TOKEN_MANAGER_MODULE)
@FrontendAction(action = ProjectManagerConst.FETCH_AUTHENTICATION_SCRIPT_ACTION)
@GetMapping(value = ProjectManagerConst.FETCH_AUTHENTICATION_SCRIPT)
public ResponseEntity<String> fetchTokenScript(
public ResponseEntity<Resource> fetchTokenScript(
@ProjectCode @RequestParam(name = ProjectManagerConst.PROJECT_CODE) String projectCode,
@Bridgehead @RequestParam(name = ProjectManagerConst.BRIDGEHEAD) String bridgehead
) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" +
ProjectManagerConst.AUTHENTICATION_SCRIPT_FILENAME_PREFIX + projectCode + ProjectManagerConst.AUTHENTICATION_SCRIPT_FILENAME_SUFFIX + "\"")
.body(this.dataShieldTokenManagerService.fetchAuthenticationScript(projectCode, bridgehead));
}

@RoleConstraints(projectRoles = {ProjectRole.DEVELOPER, ProjectRole.PILOT, ProjectRole.FINAL, ProjectRole.BRIDGEHEAD_ADMIN, ProjectRole.PROJECT_MANAGER_ADMIN})
@StateConstraints(projectStates = {ProjectState.DEVELOP, ProjectState.PILOT, ProjectState.FINAL})
@FrontendSiteModule(site = ProjectManagerConst.PROJECT_VIEW_SITE, module = ProjectManagerConst.TOKEN_MANAGER_MODULE)
@FrontendAction(action = ProjectManagerConst.FETCH_DATASHIELD_STATUS_ACTION)
@GetMapping(value = ProjectManagerConst.FETCH_DATASHIELD_STATUS)
public ResponseEntity<String> fetchOpalStatus(
@ProjectCode @RequestParam(name = ProjectManagerConst.PROJECT_CODE) String projectCode,
@Bridgehead @RequestParam(name = ProjectManagerConst.BRIDGEHEAD) String bridgehead
) {
return convertToResponseEntity(() -> this.tokenManagerService.fetchAuthenticationScript(projectCode, bridgehead));
return convertToResponseEntity(() -> this.dataShieldTokenManagerService.fetchProjectStatus(projectCode, bridgehead));
}

@FrontendSiteModule(site = ProjectManagerConst.PROJECT_VIEW_SITE, module = ProjectManagerConst.NOTIFICATIONS_MODULE)
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/de/samply/db/model/Notification.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class Notification {
@Column(name = "id", nullable = false)
private Long id;

@Column(name = "email", nullable = false)
@Column(name = "email")
private String email;

@Column(name = "timestamp", nullable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ public interface ProjectBridgeheadRepository extends JpaRepository<ProjectBridge
Set<ProjectBridgehead> findByProjectAndState(Project project, ProjectBridgeheadState state);

Page<ProjectBridgehead> findAll(Pageable pageable);

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
import de.samply.db.model.Project;
import de.samply.db.model.ProjectBridgehead;
import de.samply.db.model.ProjectBridgeheadUser;
import de.samply.project.ProjectType;
import de.samply.project.state.ProjectState;
import de.samply.user.roles.ProjectRole;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.Set;

@Repository
public interface ProjectBridgeheadUserRepository extends JpaRepository<ProjectBridgeheadUser, Long> {
Expand All @@ -20,9 +23,20 @@ public interface ProjectBridgeheadUserRepository extends JpaRepository<ProjectBr

Optional<ProjectBridgeheadUser> getFirstByEmailAndProjectBridgeheadOrderByModifiedAtDesc(String email, ProjectBridgehead projectBridgehead);

Optional<ProjectBridgeheadUser> getFirstByEmailAndProjectBridgehead_ProjectAndProjectBridgehead_BridgeheadOrderByModifiedAtDesc(String email, Project project, String bridgehead);

List<ProjectBridgeheadUser> getByProjectBridgehead(ProjectBridgehead projectBridgehead);

@Query("SELECT DISTINCT pbu.projectBridgehead.project FROM ProjectBridgeheadUser pbu WHERE pbu.email = :email")
List<Project> findProjectsByEmail(String email);

@Query("SELECT DISTINCT pbu FROM ProjectBridgeheadUser pbu WHERE pbu.projectBridgehead.project.type = :projectType AND pbu.projectBridgehead.project.state = :projectState AND pbu.projectRole = :projectRole")
List<ProjectBridgeheadUser> getByProjectTypeAndProjectStateAndProjectRole(ProjectType projectType, ProjectState projectState, ProjectRole projectRole);

@Query("SELECT DISTINCT pbu FROM ProjectBridgeheadUser pbu WHERE pbu.projectBridgehead.project.type = :projectType AND pbu.projectBridgehead.project.state = :projectState AND pbu.projectRole != :projectRole")
List<ProjectBridgeheadUser> getByProjectTypeAndProjectStateAndNotProjectRole(ProjectType projectType, ProjectState projectState, ProjectRole projectRole);

@Query("SELECT DISTINCT pbu FROM ProjectBridgeheadUser pbu WHERE pbu.projectBridgehead.project.type = :projectType AND pbu.projectBridgehead.project.state NOT IN :projectStates")
List<ProjectBridgeheadUser> getByProjectTypeAndNotProjectState(ProjectType projectType, Set<ProjectState> projectStates);

}
Loading
Loading