├── .dockerignore ├── .env.schema ├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── CONTRIBUTING.md ├── Dockerfile ├── EgoDatabaseDiagram.pdf ├── INSTALL.md ├── Jenkinsfile ├── LICENSE ├── NOTES.md ├── README.md ├── build ├── code_of_conduct.md ├── docker-compose-all.yml ├── docker-compose.yml ├── docs ├── Makefile ├── conf.py ├── ego-arch.png ├── index.rst ├── make.bat └── src │ ├── admins.rst │ ├── appdevelopers.rst │ ├── architecture.rst │ ├── contribution.rst │ ├── gettingstarted.rst │ ├── installation.rst │ ├── introduction.rst │ ├── jwt.png │ ├── technology.rst │ ├── terms.png │ └── tokens.rst ├── fly ├── icon-ego.png ├── makefile ├── mvnw ├── mvnw.cmd ├── ov-logo.png ├── pom.xml └── src ├── main ├── assembly │ └── bin.xml ├── bin │ ├── ego │ ├── wrapper-linux-x86-64 │ ├── wrapper-macosx-universal-64 │ └── wrapper.log ├── conf │ ├── logback.xml │ └── wrapper.conf ├── datasource │ └── test.mv.db ├── java │ ├── bio │ │ └── overture │ │ │ └── ego │ │ │ ├── AuthorizationServiceMain.java │ │ │ ├── config │ │ │ ├── AuthorizationServerConfig.java │ │ │ ├── DefaultProviderGuardListener.java │ │ │ ├── EncoderConfig.java │ │ │ ├── InitializationConfig.java │ │ │ ├── LoginNonceProperties.java │ │ │ ├── OAuth2AccessTokenResponseConverterWithDefaults.java │ │ │ ├── OAuth2ClientConfig.java │ │ │ ├── RequestLoggingFilterConfig.java │ │ │ ├── SecureServerConfig.java │ │ │ ├── ServerConfig.java │ │ │ ├── SessionConfig.java │ │ │ ├── SwaggerConfig.java │ │ │ ├── UserDefaultsConfig.java │ │ │ └── WebRequestConfig.java │ │ │ ├── controller │ │ │ ├── ApiKeyController.java │ │ │ ├── ApplicationController.java │ │ │ ├── AuthController.java │ │ │ ├── GroupController.java │ │ │ ├── PolicyController.java │ │ │ ├── TransactionController.java │ │ │ ├── UserController.java │ │ │ └── resolver │ │ │ │ ├── FilterResolver.java │ │ │ │ └── PageableResolver.java │ │ │ ├── event │ │ │ └── token │ │ │ │ ├── ApiKeyEventsPublisher.java │ │ │ │ ├── CleanupApiKeyListener.java │ │ │ │ ├── CleanupUserApiKeysEvent.java │ │ │ │ ├── InitApplicationListener.java │ │ │ │ ├── RevokeApiKeyListener.java │ │ │ │ └── RevokeApiKeysEvent.java │ │ │ ├── grpc │ │ │ ├── GrpcServer.java │ │ │ ├── ProtoUtils.java │ │ │ ├── interceptor │ │ │ │ ├── ApplicationAuthInterceptor.java │ │ │ │ ├── AuthInterceptor.java │ │ │ │ └── NoAuthInterceptor.java │ │ │ └── service │ │ │ │ └── UserServiceGrpcImpl.java │ │ │ ├── model │ │ │ ├── domain │ │ │ │ └── RefreshContext.java │ │ │ ├── dto │ │ │ │ ├── ApiKeyResponse.java │ │ │ │ ├── ApiKeyScopeResponse.java │ │ │ │ ├── CreateApplicationRequest.java │ │ │ │ ├── CreateTokenRequest.java │ │ │ │ ├── CreateUserRequest.java │ │ │ │ ├── GenericResponse.java │ │ │ │ ├── GroupRequest.java │ │ │ │ ├── LinkedinEmail.java │ │ │ │ ├── LinkedinEmailResponse.java │ │ │ │ ├── MaskDTO.java │ │ │ │ ├── OrcidEmail.java │ │ │ │ ├── OrcidEmailResponse.java │ │ │ │ ├── PageDTO.java │ │ │ │ ├── PermissionRequest.java │ │ │ │ ├── PolicyRequest.java │ │ │ │ ├── PolicyResponse.java │ │ │ │ ├── ResolvedPermissionResponse.java │ │ │ │ ├── Scope.java │ │ │ │ ├── TokenResponse.java │ │ │ │ ├── TransactionalDeleteRequest.java │ │ │ │ ├── TransactionalGroupPermissionRequest.java │ │ │ │ ├── UpdateApplicationRequest.java │ │ │ │ ├── UpdateUserRequest.java │ │ │ │ └── UserScopesResponse.java │ │ │ ├── entity │ │ │ │ ├── AbstractPermission.java │ │ │ │ ├── ApiKey.java │ │ │ │ ├── ApiKeyScope.java │ │ │ │ ├── Application.java │ │ │ │ ├── ApplicationPermission.java │ │ │ │ ├── DefaultProvider.java │ │ │ │ ├── Group.java │ │ │ │ ├── GroupPermission.java │ │ │ │ ├── Identifiable.java │ │ │ │ ├── InitTripWire.java │ │ │ │ ├── NameableEntity.java │ │ │ │ ├── Policy.java │ │ │ │ ├── PolicyOwner.java │ │ │ │ ├── RefreshToken.java │ │ │ │ ├── User.java │ │ │ │ └── UserPermission.java │ │ │ ├── enums │ │ │ │ ├── AccessLevel.java │ │ │ │ ├── ApplicationStatus.java │ │ │ │ ├── ApplicationType.java │ │ │ │ ├── Fields.java │ │ │ │ ├── JavaFields.java │ │ │ │ ├── LanguageType.java │ │ │ │ ├── LinkedinContactType.java │ │ │ │ ├── LombokFields.java │ │ │ │ ├── ProviderType.java │ │ │ │ ├── SqlFields.java │ │ │ │ ├── StatusType.java │ │ │ │ ├── Tables.java │ │ │ │ └── UserType.java │ │ │ ├── exceptions │ │ │ │ ├── ExceptionHandlers.java │ │ │ │ ├── ForbiddenException.java │ │ │ │ ├── InternalServerException.java │ │ │ │ ├── InvalidRequestException.java │ │ │ │ ├── InvalidScopeException.java │ │ │ │ ├── InvalidTokenException.java │ │ │ │ ├── MalformedRequestException.java │ │ │ │ ├── NoPrimaryEmailException.java │ │ │ │ ├── NotFoundException.java │ │ │ │ ├── OAuth2Exception.java │ │ │ │ ├── RequestValidationException.java │ │ │ │ ├── RequestViolation.java │ │ │ │ ├── SSOAuthenticationFailureHandler.java │ │ │ │ ├── UnauthorizedClientException.java │ │ │ │ ├── UnauthorizedException.java │ │ │ │ └── UniqueViolationException.java │ │ │ ├── join │ │ │ │ ├── GroupApplication.java │ │ │ │ ├── GroupApplicationId.java │ │ │ │ ├── UserApplication.java │ │ │ │ ├── UserApplicationId.java │ │ │ │ ├── UserGroup.java │ │ │ │ └── UserGroupId.java │ │ │ ├── params │ │ │ │ └── ScopeName.java │ │ │ └── search │ │ │ │ ├── Filters.java │ │ │ │ └── SearchFilter.java │ │ │ ├── provider │ │ │ └── google │ │ │ │ └── GoogleTokenService.java │ │ │ ├── repository │ │ │ ├── ApplicationPermissionRepository.java │ │ │ ├── ApplicationRepository.java │ │ │ ├── BaseRepository.java │ │ │ ├── DefaultProviderRepository.java │ │ │ ├── GroupPermissionRepository.java │ │ │ ├── GroupRepository.java │ │ │ ├── InitTripWireRepository.java │ │ │ ├── NameablePermissionRepository.java │ │ │ ├── NamedRepository.java │ │ │ ├── PermissionRepository.java │ │ │ ├── PolicyRepository.java │ │ │ ├── RefreshTokenRepository.java │ │ │ ├── TokenStoreRepository.java │ │ │ ├── UserPermissionRepository.java │ │ │ ├── UserRepository.java │ │ │ ├── join │ │ │ │ └── UserGroupRepository.java │ │ │ └── queryspecification │ │ │ │ ├── AbstractPermissionSpecification.java │ │ │ │ ├── ApplicationPermissionSpecification.java │ │ │ │ ├── ApplicationSpecification.java │ │ │ │ ├── GroupPermissionSpecification.java │ │ │ │ ├── GroupSpecification.java │ │ │ │ ├── PolicySpecification.java │ │ │ │ ├── SimpleCriteriaBuilder.java │ │ │ │ ├── SpecificationBase.java │ │ │ │ ├── TokenStoreSpecification.java │ │ │ │ ├── UserPermissionSpecification.java │ │ │ │ ├── UserSpecification.java │ │ │ │ └── builder │ │ │ │ ├── AbstractSpecificationBuilder.java │ │ │ │ ├── ApplicationSpecificationBuilder.java │ │ │ │ ├── GroupSpecificationBuilder.java │ │ │ │ ├── RefreshTokenSpecificationBuilder.java │ │ │ │ ├── TokenSpecificationBuilder.java │ │ │ │ └── UserSpecificationBuilder.java │ │ │ ├── security │ │ │ ├── AdminScoped.java │ │ │ ├── ApplicationScoped.java │ │ │ ├── AuthorizationManager.java │ │ │ ├── BasicAuthToken.java │ │ │ ├── CorsFilter.java │ │ │ ├── CustomOAuth2User.java │ │ │ ├── CustomOAuth2UserInfoService.java │ │ │ ├── CustomOidc2UserInfoService.java │ │ │ ├── DefaultAuthorizationManager.java │ │ │ ├── JWTAuthorizationFilter.java │ │ │ ├── OAuth2RequestResolver.java │ │ │ └── SecureAuthorizationManager.java │ │ │ ├── service │ │ │ ├── AbstractBaseService.java │ │ │ ├── AbstractNameablePermissionService.java │ │ │ ├── AbstractNamedService.java │ │ │ ├── AbstractPermissionService.java │ │ │ ├── ApiKeyStoreService.java │ │ │ ├── ApplicationPermissionService.java │ │ │ ├── ApplicationService.java │ │ │ ├── BaseService.java │ │ │ ├── DefaultProviderService.java │ │ │ ├── GithubService.java │ │ │ ├── GroupPermissionService.java │ │ │ ├── GroupService.java │ │ │ ├── InitializationService.java │ │ │ ├── LinkedinService.java │ │ │ ├── NamedService.java │ │ │ ├── OrcidService.java │ │ │ ├── PolicyService.java │ │ │ ├── RefreshContextService.java │ │ │ ├── TokenService.java │ │ │ ├── UserGroupService.java │ │ │ ├── UserPermissionService.java │ │ │ └── UserService.java │ │ │ ├── token │ │ │ ├── CustomTokenEnhancer.java │ │ │ ├── IDToken.java │ │ │ ├── TokenClaims.java │ │ │ ├── app │ │ │ │ ├── AppJWTAccessToken.java │ │ │ │ ├── AppTokenClaims.java │ │ │ │ └── AppTokenContext.java │ │ │ ├── signer │ │ │ │ ├── DefaultTokenSigner.java │ │ │ │ ├── JKSTokenSigner.java │ │ │ │ └── TokenSigner.java │ │ │ └── user │ │ │ │ ├── UserJWTAccessToken.java │ │ │ │ ├── UserTokenClaims.java │ │ │ │ └── UserTokenContext.java │ │ │ ├── utils │ │ │ ├── CollectionUtils.java │ │ │ ├── Collectors.java │ │ │ ├── Converters.java │ │ │ ├── Defaults.java │ │ │ ├── EntityServices.java │ │ │ ├── FieldUtils.java │ │ │ ├── HibernateSessions.java │ │ │ ├── Ids.java │ │ │ ├── IgnoreCaseSortDecorator.java │ │ │ ├── Joiners.java │ │ │ ├── PermissionRequestAnalyzer.java │ │ │ ├── PolicyPermissionUtils.java │ │ │ ├── QueryUtils.java │ │ │ ├── Redirects.java │ │ │ ├── Splitters.java │ │ │ ├── Streams.java │ │ │ ├── Strings.java │ │ │ ├── SwaggerConstants.java │ │ │ ├── Tokens.java │ │ │ └── TypeUtils.java │ │ │ └── view │ │ │ └── Views.java │ └── db │ │ └── migration │ │ ├── V1_1__complete_uuid_migration.java │ │ └── V1_3__string_to_date.java ├── lib │ ├── libwrapper-linux-x86-64.so │ ├── libwrapper-macosx-universal-64.jnilib │ └── wrapper.jar ├── proto │ └── Ego.proto └── resources │ ├── application.yml │ ├── bootstrap-iam.properties │ ├── bootstrap-token.properties │ ├── bootstrap.properties │ ├── dummy-data │ ├── 01-insert-dummy-users.sql │ ├── 02-insert-dummy-groups.sql │ ├── 03-insert-dummy-applications.sql │ ├── 04-insert-dummy-rel-user-group.sql │ ├── 05-insert-dummy-rel-user-application.sql │ ├── 06-insert-dummy-rel-group-application.sql │ └── reset-dummy-data.sh │ ├── ego-jwt.jks │ ├── flyway │ ├── conf │ │ └── flyway.conf │ └── sql │ │ ├── V1_10__remove_apps_from_apitokens.sql │ │ ├── V1_11__add_expiry_date_api_tokens.sql │ │ ├── V1_12__egoapplication_unique_constraints.sql │ │ ├── V1_13__fname_lname_not_null_constraints.sql │ │ ├── V1_14__indices.sql │ │ ├── V1_15_5__remove_duplicate_joins.sql │ │ ├── V1_15__add_refresh_token_table.sql │ │ ├── V1_16__add_primary_key_constraint_to_associations.sql │ │ ├── V1_17__add_application_permissions.sql │ │ ├── V1_18__ego_init.sql │ │ ├── V1_19__add_identity_provider_to_user.sql │ │ ├── V1_20__keycloak_provider_type.sql │ │ ├── V1_21__add_application_error_redirect.sql │ │ ├── V1_2__acl_expansion.sql │ │ ├── V1_4__score_integration.sql │ │ ├── V1_5__table_renaming.sql │ │ ├── V1_6__add_not_null_constraint.sql │ │ ├── V1_7__token_modification.sql │ │ ├── V1_8__application_types.sql │ │ ├── V1_9__new_enum_types.sql │ │ └── V1__initial_database.sql │ ├── logback.xml │ ├── schemas │ ├── 00-psql-drop-tables.sql │ └── 01-psql-schema.sql │ └── scripts │ ├── env_template.sh │ ├── jwt │ ├── export-pub-key.sh │ ├── gen-key-pair.sh │ └── gen-keystore.sh │ ├── run.sh │ ├── start-server-iam.sh │ ├── start-server-token.sh │ ├── start-server.sh │ ├── stop-server.sh │ └── vault │ ├── setup-local-vault.sh │ └── vault.conf └── test ├── java ├── bio │ └── overture │ │ └── ego │ │ ├── controller │ │ ├── AbstractControllerTest.java │ │ ├── AbstractListNameableOwnerPermissionsForPolicyControllerTest.java │ │ ├── AbstractListOwnerPermissionsForPolicyControllerTest.java │ │ ├── AbstractMockedTokenControllerTest.java │ │ ├── AbstractNameablePermissionControllerTest.java │ │ ├── AbstractNameableResolvablePermissionControllerTest.java │ │ ├── AbstractPermissionControllerTest.java │ │ ├── AbstractResolvablePermissionControllerTest.java │ │ ├── ApiKeyControllerTest.java │ │ ├── AppJWTTest.java │ │ ├── ApplicationControllerTest.java │ │ ├── ApplicationPermissionControllerTest.java │ │ ├── CreateUserControllerTest.java │ │ ├── GroupControllerTest.java │ │ ├── GroupPermissionControllerTest.java │ │ ├── ListApplicationPermissionsForPolicyControllerTest.java │ │ ├── ListGroupPermissionsForPolicyControllerTest.java │ │ ├── ListUserPermissionsForPolicyControllerTest.java │ │ ├── PolicyControllerTest.java │ │ ├── RefreshTokenTest.java │ │ ├── RevokeApiKeyControllerTest.java │ │ ├── TokensOnPermissionsChangeTest.java │ │ ├── TokensOnUserAndPolicyDeletes.java │ │ ├── TransactionControllerTest.java │ │ ├── UpdateTokenTest.java │ │ ├── UpdateUserControllerTest.java │ │ ├── UserControllerTest.java │ │ ├── UserJwtTest.java │ │ ├── UserPermissionControllerTest.java │ │ └── UserSelfAssignApiKeyTest.java │ │ ├── grpc │ │ ├── ProtoUtilsTest.java │ │ └── service │ │ │ ├── UserServiceGrpcAuthTest.java │ │ │ └── UserServiceGrpcTest.java │ │ ├── model │ │ ├── domain │ │ │ └── RefreshContextTest.java │ │ ├── entity │ │ │ └── ScopeTest.java │ │ ├── enums │ │ │ └── AccessLevelTest.java │ │ └── params │ │ │ └── ScopeNameTest.java │ │ ├── security │ │ ├── SecureAuthorizationManagerTest.java │ │ └── SecurityTest.java │ │ ├── service │ │ ├── DefaultProviderServiceTest.java │ │ ├── FirstUserAsAdminTest.java │ │ ├── RefreshContextServiceTest.java │ │ ├── UserServiceTest.java │ │ └── initialization │ │ │ ├── InitializationEventTest.java │ │ │ └── InitializationServiceTest.java │ │ ├── test │ │ └── FlywayInit.java │ │ ├── token │ │ ├── JwtTest.java │ │ ├── LastloginTest.java │ │ └── ListApiKeyTest.java │ │ └── utils │ │ ├── EntityGenerator.java │ │ ├── EntityTools.java │ │ ├── RedirectsTest.java │ │ ├── SSOAuthenticationFailureHandlerTest.java │ │ ├── TestData.java │ │ ├── WithMockCustomApplication.java │ │ ├── WithMockCustomApplicationSecurityContextFactory.java │ │ ├── WithMockCustomUser.java │ │ ├── WithMockCustomUserSecurityContextFactory.java │ │ └── web │ │ ├── AbstractWebResource.java │ │ ├── BasicWebResource.java │ │ ├── CleanResponse.java │ │ ├── QueryParam.java │ │ ├── ResponseOption.java │ │ ├── StringResponseOption.java │ │ └── StringWebResource.java └── selenium │ ├── AbstractSeleniumTest.java │ ├── LoadAdminUITest.java │ ├── driver │ ├── BrowserStackDriverProxy.java │ └── WebDriverFactory.java │ └── rule │ ├── AssumingSeleniumEnvironment.java │ └── SeleniumEnvironmentChecker.java └── resources └── conf └── bs.conf.json /.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | .git 3 | target -------------------------------------------------------------------------------- /.env.schema: -------------------------------------------------------------------------------- 1 | EGO_ACTIVE_PROFILES= 2 | EGO_SERVER_PORT= 3 | EGO_DB_HOST= 4 | EGO_DB_PORT= 5 | EGO_DB= 6 | EGO_DB_USER= 7 | EGO_DB_PASS= 8 | EGO_SERVER_GOOGLE_CLIENT_IDS= 9 | EGO_SERVER_FACEBOOK_APP_ID= 10 | EGO_SERVER_FACEBOOK_SECRET= 11 | 12 | # required for docker-compose config. This is the port that the api will be available on. 13 | API_HOST_PORT= 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | env.sh 4 | 5 | ### Java Wrapper Logs ### 6 | *wrapper*.log 7 | *.log 8 | 9 | ### STS ### 10 | .apt_generated 11 | .classpath 12 | .factorypath 13 | .project 14 | .settings 15 | .springBeans 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | 23 | ### NetBeans ### 24 | nbproject/private/ 25 | build/ 26 | nbbuild/ 27 | dist/ 28 | nbdist/ 29 | .nb-gradle/ 30 | 31 | ### VSCode ### 32 | .vscode 33 | .env 34 | 35 | ### Docs ### 36 | _build/ 37 | _source/ 38 | _templates/ 39 | .DS_Store 40 | 41 | classes/ 42 | 43 | local.log 44 | *.local.yaml 45 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM adoptopenjdk/openjdk11:jdk-11.0.6_10-slim as builder 2 | WORKDIR /usr/src/app 3 | ADD . . 4 | RUN ./mvnw package -Dmaven.test.skip=true 5 | 6 | ##################################################### 7 | 8 | FROM adoptopenjdk/openjdk11:jre-11.0.6_10 9 | COPY --from=builder /usr/src/app/target/ego-*-exec.jar /usr/bin/ego.jar 10 | ENV EGO_USER ego 11 | ENV EGO_USER_ID 9999 12 | ENV EGO_GROUP_ID 9999 13 | ENV EGO_DIR /target 14 | RUN addgroup --system --gid $EGO_GROUP_ID $EGO_USER \ 15 | && adduser --system --uid $EGO_USER_ID --ingroup $EGO_USER $EGO_USER \ 16 | && mkdir -p $EGO_DIR \ 17 | && chown -R $EGO_USER $EGO_DIR 18 | USER $EGO_USER_ID 19 | CMD ["java", "-jar", "/usr/bin/ego.jar"] 20 | EXPOSE 8081/tcp 21 | -------------------------------------------------------------------------------- /EgoDatabaseDiagram.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/EgoDatabaseDiagram.pdf -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | @Library(value='jenkins-pipeline-library@master', changelog=false) _ 2 | pipelineOVERTUREEgo() -------------------------------------------------------------------------------- /build: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ./fly migrate 3 | mvn clean package 4 | -------------------------------------------------------------------------------- /docker-compose-all.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | ego-ui: 4 | image: overture/ego-ui:edge 5 | expose: 6 | - "8080" 7 | ports: 8 | - "8080:8080" 9 | environment: 10 | REACT_APP_API: http://localhost:8081 11 | REACT_APP_EGO_CLIENT_ID: ego-ui 12 | api: 13 | # change the image tag to the target image as needed 14 | image: overture/ego:latest 15 | environment: 16 | SERVER_PORT: 8081 17 | SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/ego?stringtype=unspecified 18 | SPRING_DATASOURCE_USERNAME: postgres 19 | SPRING_DATASOURCE_PASSWORD: password 20 | SPRING_FLYWAY_ENABLED: "true" 21 | SPRING_FLYWAY_LOCATIONS: "classpath:flyway/sql,classpath:db/migration" 22 | SPRING_PROFILES_ACTIVE: auth 23 | 24 | # example on how to configure ego google oauth2 login 25 | spring.security.oauth2.client.registration.google.clientId : ".." 26 | spring.security.oauth2.client.registration.google.clientSecret: ".." 27 | # this should be registered as the authorized redirect URI in google cloud console 28 | spring.security.oauth2.client.registration.google.redirectUri : "http://localhost:8081/oauth/code/google" 29 | 30 | default.user.firstUserAsAdmin: "true" 31 | logging.level.root: INFO 32 | expose: 33 | - "8081" 34 | ports: 35 | - "8081:8081" 36 | depends_on: 37 | - postgres 38 | postgres: 39 | image: postgres:12.6 40 | environment: 41 | - POSTGRES_DB=ego 42 | - POSTGRES_PASSWORD=password 43 | expose: 44 | - "5432" 45 | ports: 46 | - "5432:5432" 47 | volumes: 48 | - "ego_data:/var/lib/postgresql/data" 49 | volumes: 50 | ego_data: -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | keycloak: 4 | image: quay.io/keycloak/keycloak:16.1.0 5 | ports: 6 | - 8083:8080 7 | environment: 8 | KEYCLOAK_USER: admin 9 | KEYCLOAK_PASSWORD: admin 10 | DB_VENDOR: POSTGRES 11 | DB_ADDR: postgres 12 | DB_DATABASE: ego 13 | DB_USER: postgres 14 | DB_SCHEMA: public 15 | DB_PASSWORD: password 16 | ego-ui: 17 | image: overture/ego-ui:edge 18 | ports: 19 | - "8080:8080" 20 | environment: 21 | REACT_APP_API: http://localhost:8081 22 | REACT_APP_EGO_CLIENT_ID: ego-ui 23 | REACT_APP_KEYCLOAK_ENABLED: "true" 24 | postgres: 25 | image: postgres:12.6 26 | restart: always 27 | environment: 28 | - POSTGRES_DB=ego 29 | - POSTGRES_PASSWORD=password 30 | expose: 31 | - "5432" 32 | ports: 33 | - "5432:5432" 34 | volumes: 35 | - "psql_data:/var/lib/postgresql/data" 36 | volumes: 37 | psql_data: 38 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = Ego 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/ego-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/docs/ego-arch.png -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. Ego documentation master file, created by 2 | sphinx-quickstart on Fri Mar 16 14:17:55 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | ============ 7 | Ego Documentation 8 | ============ 9 | 10 | .. toctree:: 11 | :maxdepth: 4 12 | :caption: First Steps 13 | 14 | src/introduction.rst 15 | src/gettingstarted.rst 16 | 17 | .. toctree:: 18 | :maxdepth: 4 19 | :caption: User Documentation 20 | 21 | src/admins.rst 22 | src/appdevelopers.rst 23 | src/tokens.rst 24 | 25 | .. toctree:: 26 | :maxdepth: 4 27 | :caption: Developer Documentation 28 | 29 | src/installation.rst 30 | src/architecture.rst 31 | src/technology.rst 32 | src/contribution.rst 33 | 34 | 35 | Contribute 36 | ------------ 37 | If you'd like to contribute to this project, it's hosted on github. 38 | 39 | See https://github.com/overture-stack/ego 40 | 41 | Indices and tables 42 | ================== 43 | 44 | * :ref:`genindex` 45 | * :ref:`search` 46 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=Ego 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 20 | echo.installed, then set the SPHINXBUILD environment variable to point 21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 22 | echo.may add the Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /docs/src/admins.rst: -------------------------------------------------------------------------------- 1 | ======================= 2 | Ego for Administrators 3 | ======================= 4 | 5 | Tutorial 6 | ====================== 7 | 8 | To administer Ego, the admin must: 9 | 10 | **1. Install Ego.** 11 | 12 | View the installation instructions. 13 | 14 | **2. Insert a new user with the admin’s Oauth Id into the “egousers” table, with role ADMIN.** 15 | 16 | **3. A developer creates a new Ego-aware application** 17 | 18 | a. Admin creates a new application in Ego with the client_id and password. 19 | b. Admin creates new policies with new policy names 20 | c. Admin assigns permissions to users/groups to permit/deny them access to the new application and policies 21 | 22 | **4. Admin creates or deletes groups, assigns user/group permissions, revoke tokens, etc. as necessary.** 23 | 24 | For example, an administrator might want to: 25 | 26 | - Create a new group called **“QA”**, whose members are all the people in the “QA department” 27 | - Create a group called “Access Denied” with access level “DENY” set for every policy in Ego 28 | - Grant another user administrative rights (role ADMIN) 29 | - Add a former employee to the group “AccessDenied”, and revoke all of their active tokens. 30 | - In general, manage permissions and access controls within Ego. 31 | 32 | Using the Admin Portal 33 | ====================== 34 | 35 | Ego provides an intuitive GUI for painless user management. 36 | -------------------------------------------------------------------------------- /docs/src/appdevelopers.rst: -------------------------------------------------------------------------------- 1 | ================================ 2 | Ego for Application Developers 3 | ================================ 4 | 5 | To create an Ego-aware application, a developer must: 6 | 7 | 1. Pick a unique policy name for each type of authorization that the application requires. 8 | 9 | 2. Write the application. Ensure that the application does it’s authorization by performing a call to Ego’s “check_token” REST endpoint, and only grants access to the service for the user id returned by “check_token” if the permissions returned by “check_token” include the required permission. 10 | 11 | 3. Configure the program with a meaningful client_id and a secret password. 12 | 13 | 4. Give the client_id, password, and policy names to an Ego administrator, and ask them to configure Ego for you. 14 | -------------------------------------------------------------------------------- /docs/src/architecture.rst: -------------------------------------------------------------------------------- 1 | Architecture 2 | ============================ 3 | -------------------------------------------------------------------------------- /docs/src/contribution.rst: -------------------------------------------------------------------------------- 1 | Contributing to the Ego Project 2 | ============================ 3 | -------------------------------------------------------------------------------- /docs/src/installation.rst: -------------------------------------------------------------------------------- 1 | .. _installation: 2 | 3 | Installation 4 | ============================ 5 | 6 | Step 1 - Setup Database 7 | ----------------------- 8 | 9 | 1. Install Postgres 10 | 2. Create a Database: ego with user postgres and empty password 11 | 3. Execute SQL Script to setup tables. 12 | 13 | Database Migrations with Flyway 14 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 15 | 16 | Database migrations and versioning is managed by `flyway `_. 17 | 18 | Step 2 - Run 19 | ------------ 20 | 21 | EGO currently supports three Profiles: 22 | 23 | - default: Use this to run the most simple setup. This lets you test various API endpoints without a valid JWT in authorization header. 24 | - auth: Run this to include validations for JWT. 25 | - secure: Run this profile to enable https 26 | 27 | Run using Maven. Maven can be used to prepare a runnable jar file, as well as the uber-jar for deployment: 28 | 29 | .. code-block:: bash 30 | 31 | $ mvn clean package ; ./fly migrate 32 | 33 | 34 | To run from command line with maven: 35 | 36 | .. code-block:: bash 37 | 38 | $ mvn spring-boot:run 39 | -------------------------------------------------------------------------------- /docs/src/jwt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/docs/src/jwt.png -------------------------------------------------------------------------------- /docs/src/terms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/docs/src/terms.png -------------------------------------------------------------------------------- /fly: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CMD=${1:-info} 3 | CONFIG_FILE=${2:-`pwd`/src/main/resources/flyway/conf/flyway.conf} 4 | 5 | # To debug, use this line instead... 6 | # mvn flyway:${CMD} -X -Dflyway.configFile=$CONFIG_FILE 7 | 8 | mvn "flyway:$CMD" -Dflyway.configFiles=${CONFIG_FILE} 9 | -------------------------------------------------------------------------------- /icon-ego.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/icon-ego.png -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | start: 2 | docker-compose -f docker-compose-all.yml up -d 3 | sleep 10; 4 | make init-db 5 | 6 | up: 7 | docker-compose -f docker-compose-all.yml up -d 8 | 9 | down: 10 | docker-compose -f docker-compose-all.yml down 11 | 12 | nuke: 13 | docker-compose -f docker-compose-all.yml down --volumes 14 | 15 | # needed to insert the ego ui client in ego db 16 | init-db: 17 | docker exec ego-postgres-1 psql -h localhost -p 5432 -U postgres -d ego --command "INSERT INTO EGOAPPLICATION (name, clientId, clientSecret, redirectUri, description, status, errorredirecturi) VALUES ('ego ui', 'ego-ui', 'secret', 'http://localhost:8080/', '...', 'APPROVED', 'http://localhost:8080/error') on conflict do nothing" -------------------------------------------------------------------------------- /ov-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/ov-logo.png -------------------------------------------------------------------------------- /src/main/bin/wrapper-linux-x86-64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/src/main/bin/wrapper-linux-x86-64 -------------------------------------------------------------------------------- /src/main/bin/wrapper-macosx-universal-64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/src/main/bin/wrapper-macosx-universal-64 -------------------------------------------------------------------------------- /src/main/datasource/test.mv.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/src/main/datasource/test.mv.db -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/AuthorizationServiceMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego; 18 | 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | 22 | @SpringBootApplication 23 | public class AuthorizationServiceMain { 24 | 25 | public static void main(String[] args) { 26 | SpringApplication.run(AuthorizationServiceMain.class, args); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/config/EncoderConfig.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | import org.springframework.security.crypto.password.PasswordEncoder; 7 | 8 | @Configuration 9 | public class EncoderConfig { 10 | 11 | @Bean 12 | public PasswordEncoder passwordEncoder() { 13 | return new BCryptPasswordEncoder(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/config/InitializationConfig.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.config; 2 | 3 | import bio.overture.ego.model.enums.ApplicationType; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import javax.validation.constraints.NotBlank; 7 | import javax.validation.constraints.NotNull; 8 | import javax.validation.constraints.Size; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Builder; 11 | import lombok.Getter; 12 | import lombok.NoArgsConstructor; 13 | import lombok.Setter; 14 | import org.springframework.boot.context.properties.ConfigurationProperties; 15 | import org.springframework.stereotype.Component; 16 | 17 | @Setter 18 | @Getter 19 | @Component 20 | @ConfigurationProperties("initialization") 21 | public class InitializationConfig { 22 | 23 | private boolean enabled; 24 | private final List applications = new ArrayList<>(); 25 | 26 | @Getter 27 | @Setter 28 | @Builder 29 | @NoArgsConstructor 30 | @AllArgsConstructor 31 | public static class InitialApplication { 32 | @NotBlank private String name; 33 | @NotNull private ApplicationType type; 34 | 35 | @NotBlank 36 | @Size(min = 3) 37 | private String clientId; 38 | 39 | @NotBlank 40 | @Size(min = 15) 41 | private String clientSecret; 42 | 43 | private String redirectUri; 44 | private String description; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/config/LoginNonceProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.config; 19 | 20 | import lombok.Data; 21 | import org.springframework.boot.context.properties.ConfigurationProperties; 22 | import org.springframework.context.annotation.Configuration; 23 | 24 | @Data 25 | @Configuration 26 | @ConfigurationProperties(prefix = "login.nonce") 27 | public class LoginNonceProperties { 28 | 29 | private String name; 30 | private String sameSite; 31 | private boolean secure; 32 | private int maxAge; 33 | private String domainPattern; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/config/OAuth2ClientConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.config; 19 | 20 | import bio.overture.ego.security.CorsFilter; 21 | import bio.overture.ego.security.OAuth2RequestResolver; 22 | import org.springframework.context.annotation.Bean; 23 | import org.springframework.context.annotation.Configuration; 24 | import org.springframework.context.annotation.Primary; 25 | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; 26 | import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; 27 | 28 | @Configuration 29 | public class OAuth2ClientConfig { 30 | @Bean 31 | public OAuth2AuthorizationRequestResolver oAuth2AuthorizationRequestResolver( 32 | ClientRegistrationRepository clientRegistrationRepository) { 33 | return new OAuth2RequestResolver(clientRegistrationRepository, "/oauth/login/"); 34 | } 35 | 36 | @Bean 37 | @Primary 38 | public CorsFilter corsFilter() { 39 | return new CorsFilter(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/config/RequestLoggingFilterConfig.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.filter.CommonsRequestLoggingFilter; 6 | 7 | @Configuration 8 | public class RequestLoggingFilterConfig { 9 | 10 | @Bean 11 | public CommonsRequestLoggingFilter logFilter() { 12 | CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); 13 | filter.setIncludeQueryString(true); 14 | filter.setIncludePayload(true); 15 | filter.setMaxPayloadLength(10000); 16 | filter.setIncludeHeaders(false); 17 | filter.setIncludeClientInfo(true); 18 | return filter; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/config/UserDefaultsConfig.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.config; 2 | 3 | import static bio.overture.ego.model.enums.StatusType.PENDING; 4 | import static bio.overture.ego.model.enums.StatusType.resolveStatusType; 5 | import static bio.overture.ego.model.enums.UserType.USER; 6 | import static bio.overture.ego.model.enums.UserType.resolveUserType; 7 | import static org.springframework.util.StringUtils.isEmpty; 8 | 9 | import bio.overture.ego.model.enums.StatusType; 10 | import bio.overture.ego.model.enums.UserType; 11 | import lombok.Getter; 12 | import org.springframework.beans.factory.annotation.Value; 13 | import org.springframework.context.annotation.Configuration; 14 | 15 | @Configuration 16 | public class UserDefaultsConfig { 17 | 18 | @Getter private final UserType defaultUserType; 19 | 20 | @Getter private final StatusType defaultUserStatus; 21 | 22 | @Getter private final boolean firstUserAsAdmin; 23 | 24 | public UserDefaultsConfig( 25 | @Value("${default.user.type}") String userType, 26 | @Value("${default.user.status}") String userStatus, 27 | @Value("${default.user.firstUserAsAdmin:false}") boolean firstUserAsAdmin) { 28 | this.defaultUserType = isEmpty(userType) ? USER : resolveUserType(userType); 29 | this.defaultUserStatus = isEmpty(userStatus) ? PENDING : resolveStatusType(userStatus); 30 | this.firstUserAsAdmin = firstUserAsAdmin; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/config/WebRequestConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.config; 18 | 19 | import bio.overture.ego.controller.resolver.FilterResolver; 20 | import bio.overture.ego.controller.resolver.PageableResolver; 21 | import bio.overture.ego.model.enums.Fields; 22 | import bio.overture.ego.utils.FieldUtils; 23 | import java.util.List; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.context.annotation.Configuration; 26 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 27 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 28 | 29 | @Configuration 30 | public class WebRequestConfig extends WebMvcConfigurerAdapter { 31 | 32 | @Bean 33 | public List fieldValues() { 34 | return FieldUtils.getStaticFieldValueList(Fields.class); 35 | } 36 | 37 | @Override 38 | public void addArgumentResolvers(List argumentResolvers) { 39 | argumentResolvers.add(new PageableResolver()); 40 | argumentResolvers.add(new FilterResolver(fieldValues())); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/event/token/ApiKeyEventsPublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.event.token; 19 | 20 | import bio.overture.ego.model.entity.ApiKey; 21 | import bio.overture.ego.model.entity.User; 22 | import java.util.Set; 23 | import lombok.NonNull; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.context.ApplicationEventPublisher; 26 | import org.springframework.stereotype.Component; 27 | 28 | @Component 29 | public class ApiKeyEventsPublisher { 30 | 31 | private ApplicationEventPublisher applicationEventPublisher; 32 | 33 | @Autowired 34 | public ApiKeyEventsPublisher(ApplicationEventPublisher applicationEventPublisher) { 35 | this.applicationEventPublisher = applicationEventPublisher; 36 | } 37 | 38 | public void requestApiKeyCleanupByUsers(@NonNull final Set users) { 39 | applicationEventPublisher.publishEvent(new CleanupUserApiKeysEvent(this, users)); 40 | } 41 | 42 | public void requestApiKeyCleanup(@NonNull final Set apiKeys) { 43 | applicationEventPublisher.publishEvent(new RevokeApiKeysEvent(this, apiKeys)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/event/token/CleanupUserApiKeysEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.event.token; 19 | 20 | import bio.overture.ego.model.entity.User; 21 | import java.util.Set; 22 | import lombok.Getter; 23 | import lombok.NonNull; 24 | import org.springframework.context.ApplicationEvent; 25 | 26 | public class CleanupUserApiKeysEvent extends ApplicationEvent { 27 | 28 | @Getter private Set users; 29 | 30 | public CleanupUserApiKeysEvent(@NonNull Object source, Set users) { 31 | super(source); 32 | this.users = users; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/event/token/InitApplicationListener.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.event.token; 2 | 3 | import bio.overture.ego.service.InitializationService; 4 | import lombok.NonNull; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 8 | import org.springframework.boot.context.event.ApplicationPreparedEvent; 9 | import org.springframework.context.ApplicationListener; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * After the application is ready to serve requests, attempt to initialize the application. If there 14 | * is an error during the initialization, the app will shutdown. 15 | */ 16 | @Slf4j 17 | @Component 18 | @ConditionalOnProperty( 19 | value = "initialization.enabled", 20 | havingValue = "true", 21 | matchIfMissing = false) 22 | public class InitApplicationListener implements ApplicationListener { 23 | 24 | private final InitializationService initializationService; 25 | 26 | @Autowired 27 | public InitApplicationListener(@NonNull InitializationService initializationService) { 28 | this.initializationService = initializationService; 29 | } 30 | 31 | @Override 32 | public void onApplicationEvent(ApplicationPreparedEvent applicationPreparedEvent) { 33 | initializationService.initialize(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/event/token/RevokeApiKeyListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.event.token; 19 | 20 | import bio.overture.ego.model.entity.ApiKey; 21 | import bio.overture.ego.service.TokenService; 22 | import lombok.NonNull; 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.context.ApplicationListener; 25 | import org.springframework.stereotype.Component; 26 | 27 | @Component 28 | public class RevokeApiKeyListener implements ApplicationListener { 29 | 30 | /** Dependencies */ 31 | private final TokenService tokenService; 32 | 33 | @Autowired 34 | public RevokeApiKeyListener(@NonNull TokenService tokenService) { 35 | this.tokenService = tokenService; 36 | } 37 | 38 | @Override 39 | public void onApplicationEvent(@NonNull RevokeApiKeysEvent event) { 40 | event.getApiKeys().stream().map(ApiKey::getName).forEach(tokenService::revoke); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/event/token/RevokeApiKeysEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.event.token; 19 | 20 | import bio.overture.ego.model.entity.ApiKey; 21 | import java.util.Set; 22 | import lombok.Getter; 23 | import lombok.NonNull; 24 | import org.springframework.context.ApplicationEvent; 25 | 26 | public class RevokeApiKeysEvent extends ApplicationEvent { 27 | 28 | @Getter private Set apiKeys; 29 | 30 | public RevokeApiKeysEvent(@NonNull Object source, @NonNull Set apiKeys) { 31 | super(source); 32 | this.apiKeys = apiKeys; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/grpc/interceptor/AuthInterceptor.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.grpc.interceptor; 2 | 3 | import io.grpc.ServerInterceptor; 4 | 5 | public interface AuthInterceptor extends ServerInterceptor {} 6 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/grpc/interceptor/NoAuthInterceptor.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.grpc.interceptor; 2 | 3 | import io.grpc.Metadata; 4 | import io.grpc.ServerCall; 5 | import io.grpc.ServerCallHandler; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** Noop Interceptor */ 10 | @Slf4j 11 | @Component 12 | public class NoAuthInterceptor implements AuthInterceptor { 13 | 14 | @Override 15 | public ServerCall.Listener interceptCall( 16 | ServerCall call, Metadata headers, ServerCallHandler next) { 17 | log.info("No Auth Interceptor..."); 18 | return next.startCall(call, headers); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/domain/RefreshContext.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.domain; 2 | 3 | import static bio.overture.ego.model.enums.StatusType.APPROVED; 4 | 5 | import bio.overture.ego.model.entity.RefreshToken; 6 | import bio.overture.ego.model.entity.User; 7 | import bio.overture.ego.model.exceptions.ForbiddenException; 8 | import bio.overture.ego.model.exceptions.UnauthorizedException; 9 | import io.jsonwebtoken.Claims; 10 | import java.util.UUID; 11 | import lombok.*; 12 | 13 | @Data 14 | @Builder 15 | @AllArgsConstructor 16 | public class RefreshContext { 17 | 18 | @NonNull private RefreshToken refreshToken; 19 | @NonNull private User user; 20 | @NonNull private Claims tokenClaims; 21 | 22 | public boolean hasApprovedUser() { 23 | return user.getStatus() == APPROVED; 24 | } 25 | 26 | private boolean userMatches() { 27 | return user.getId().equals(UUID.fromString(tokenClaims.getSubject())); 28 | } 29 | 30 | private boolean jtiMatches() { 31 | return refreshToken.getJti().equals(UUID.fromString(tokenClaims.getId())); 32 | } 33 | 34 | private boolean isExpired() { 35 | return refreshToken.getSecondsUntilExpiry() <= 0; 36 | } 37 | 38 | public boolean validate() { 39 | if (!hasApprovedUser()) { 40 | throw new ForbiddenException("User does not have approved status, rejecting."); 41 | } 42 | if (this.isExpired()) { 43 | throw new UnauthorizedException( 44 | String.format("RefreshToken %s is expired", refreshToken.getId())); 45 | } 46 | if (this.userMatches() & this.jtiMatches()) { 47 | return true; 48 | } else { 49 | throw new ForbiddenException( 50 | String.format("Invalid token claims for refreshId %s.", refreshToken.getId())); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/ApiKeyResponse.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.view.Views; 4 | import com.fasterxml.jackson.annotation.JsonView; 5 | import java.util.Date; 6 | import java.util.Set; 7 | import lombok.*; 8 | 9 | @Data 10 | @Builder 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @JsonView(Views.REST.class) 14 | public class ApiKeyResponse { 15 | 16 | @NonNull private String name; 17 | @NonNull private Set scope; 18 | @NonNull private Date expiryDate; 19 | @NonNull private Date issueDate; 20 | @NonNull private Boolean isRevoked; 21 | private String description; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/ApiKeyScopeResponse.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.view.Views; 4 | import com.fasterxml.jackson.annotation.JsonView; 5 | import java.util.Set; 6 | import java.util.UUID; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Getter; 9 | 10 | @AllArgsConstructor 11 | @Getter 12 | @JsonView(Views.REST.class) 13 | public class ApiKeyScopeResponse { 14 | private UUID user_id; 15 | private Long exp; 16 | private Set scope; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/CreateApplicationRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.dto; 18 | 19 | import bio.overture.ego.model.enums.ApplicationType; 20 | import bio.overture.ego.model.enums.StatusType; 21 | import javax.validation.constraints.NotNull; 22 | import lombok.AllArgsConstructor; 23 | import lombok.Builder; 24 | import lombok.Data; 25 | import lombok.NoArgsConstructor; 26 | 27 | @Data 28 | @Builder 29 | @NoArgsConstructor 30 | @AllArgsConstructor 31 | public class CreateApplicationRequest { 32 | 33 | @NotNull private String name; 34 | 35 | @NotNull private ApplicationType type; 36 | 37 | @NotNull private String clientId; 38 | 39 | @NotNull private String clientSecret; 40 | 41 | private String redirectUri; 42 | 43 | private String description; 44 | 45 | @NotNull private StatusType status; 46 | 47 | private String errorRedirectUri; 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/CreateTokenRequest.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import java.util.Date; 4 | import javax.validation.constraints.NotNull; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import lombok.NonNull; 10 | 11 | @Data 12 | @Builder 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class CreateTokenRequest { 16 | 17 | @NotNull private String token; 18 | 19 | @NonNull private Date issueDate; 20 | 21 | @NotNull private boolean isRevoked; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/CreateUserRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.dto; 18 | 19 | import bio.overture.ego.model.enums.LanguageType; 20 | import bio.overture.ego.model.enums.ProviderType; 21 | import bio.overture.ego.model.enums.StatusType; 22 | import bio.overture.ego.model.enums.UserType; 23 | import javax.validation.constraints.NotNull; 24 | import lombok.AllArgsConstructor; 25 | import lombok.Builder; 26 | import lombok.Data; 27 | import lombok.NoArgsConstructor; 28 | 29 | @Data 30 | @Builder 31 | @AllArgsConstructor 32 | @NoArgsConstructor 33 | public class CreateUserRequest { 34 | 35 | private String email; 36 | 37 | @NotNull private UserType type; 38 | 39 | @NotNull private StatusType status; 40 | 41 | @NotNull private String firstName; 42 | 43 | @NotNull private String lastName; 44 | 45 | private LanguageType preferredLanguage; 46 | 47 | @NotNull ProviderType providerType; 48 | 49 | @NotNull String providerSubjectId; 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/GenericResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.model.dto; 19 | 20 | import static java.lang.String.format; 21 | 22 | import bio.overture.ego.view.Views; 23 | import com.fasterxml.jackson.annotation.JsonView; 24 | import lombok.AllArgsConstructor; 25 | import lombok.Getter; 26 | import lombok.NonNull; 27 | 28 | @AllArgsConstructor 29 | @Getter 30 | @JsonView(Views.REST.class) 31 | public class GenericResponse { 32 | private String message; 33 | 34 | public static GenericResponse createGenericResponse( 35 | @NonNull String formattedString, Object... args) { 36 | return new GenericResponse(format(formattedString, args)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/GroupRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.dto; 18 | 19 | import bio.overture.ego.model.enums.StatusType; 20 | import javax.validation.constraints.NotNull; 21 | import lombok.AllArgsConstructor; 22 | import lombok.Builder; 23 | import lombok.Data; 24 | import lombok.NoArgsConstructor; 25 | 26 | @Data 27 | @Builder 28 | @AllArgsConstructor 29 | @NoArgsConstructor 30 | public class GroupRequest { 31 | 32 | @NotNull private String name; 33 | 34 | private String description; 35 | 36 | @NotNull private StatusType status; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/LinkedinEmail.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.model.enums.LinkedinContactType; 4 | import bio.overture.ego.view.Views; 5 | import com.fasterxml.jackson.annotation.JsonInclude; 6 | import com.fasterxml.jackson.annotation.JsonProperty; 7 | import com.fasterxml.jackson.annotation.JsonView; 8 | import java.util.LinkedHashMap; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Builder; 11 | import lombok.Data; 12 | import lombok.NoArgsConstructor; 13 | 14 | @Data 15 | @JsonInclude 16 | @JsonView(Views.REST.class) 17 | @Builder 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | public class LinkedinEmail { 21 | 22 | @Builder.Default 23 | @JsonProperty("handle~") 24 | private LinkedHashMap handle = new LinkedHashMap<>(); 25 | 26 | private boolean primary; 27 | private LinkedinContactType type; 28 | 29 | public String getEmail() { 30 | return this.handle.get("emailAddress"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/LinkedinEmailResponse.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.view.Views; 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.fasterxml.jackson.annotation.JsonView; 6 | import java.util.List; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Builder; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | @Data 13 | @JsonInclude 14 | @JsonView(Views.REST.class) 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class LinkedinEmailResponse { 19 | 20 | private List elements; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/MaskDTO.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.model.enums.AccessLevel; 4 | import javax.validation.constraints.NotNull; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import lombok.NonNull; 10 | 11 | @Data 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class MaskDTO { 16 | 17 | @NotNull @NonNull private AccessLevel mask; 18 | 19 | public static MaskDTO createMaskDTO(AccessLevel mask) { 20 | return new MaskDTO(mask); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/OrcidEmail.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.view.Views; 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.fasterxml.jackson.annotation.JsonView; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | @Data 12 | @JsonInclude 13 | @JsonView(Views.REST.class) 14 | @Builder 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class OrcidEmail { 18 | 19 | private String email; 20 | 21 | private boolean primary; 22 | 23 | private boolean verified; 24 | 25 | private String visibility; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/OrcidEmailResponse.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.view.Views; 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.fasterxml.jackson.annotation.JsonView; 6 | import java.util.List; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Builder; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | @Data 13 | @JsonInclude 14 | @JsonView(Views.REST.class) 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class OrcidEmailResponse { 19 | 20 | private List email; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/PageDTO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.dto; 18 | 19 | import bio.overture.ego.view.Views; 20 | import com.fasterxml.jackson.annotation.JsonView; 21 | import java.util.List; 22 | import lombok.Getter; 23 | import lombok.NonNull; 24 | import org.springframework.data.domain.Page; 25 | 26 | @Getter 27 | @JsonView(Views.REST.class) 28 | public class PageDTO { 29 | 30 | private final int limit; 31 | private final int offset; 32 | private final long count; 33 | private final List resultSet; 34 | 35 | public PageDTO(@NonNull final Page page) { 36 | this.limit = page.getSize(); 37 | this.offset = page.getNumber(); 38 | this.count = page.getTotalElements(); 39 | this.resultSet = page.getContent(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/PermissionRequest.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.model.enums.AccessLevel; 4 | import java.util.UUID; 5 | import javax.validation.constraints.NotNull; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | import lombok.NonNull; 11 | 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class PermissionRequest { 17 | 18 | @NotNull @NonNull private UUID policyId; 19 | 20 | @NotNull @NonNull private AccessLevel mask; 21 | 22 | @Override 23 | public String toString() { 24 | return policyId + "." + mask; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/PolicyRequest.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import javax.validation.constraints.NotNull; 4 | import javax.validation.constraints.Pattern; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | @Data 11 | @Builder 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class PolicyRequest { 15 | 16 | @NotNull 17 | @Pattern(regexp = "^[A-Za-z0-9_-]+$") 18 | private String name; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/PolicyResponse.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.model.enums.AccessLevel; 4 | import bio.overture.ego.view.Views; 5 | import com.fasterxml.jackson.annotation.JsonInclude; 6 | import com.fasterxml.jackson.annotation.JsonView; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Builder; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | @Data 13 | @JsonInclude 14 | @JsonView(Views.REST.class) 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class PolicyResponse { 19 | 20 | private String id; 21 | private String name; 22 | private AccessLevel mask; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/ResolvedPermissionResponse.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.model.entity.*; 4 | import bio.overture.ego.model.enums.AccessLevel; 5 | import java.util.UUID; 6 | import lombok.*; 7 | 8 | @Value 9 | @Builder 10 | public class ResolvedPermissionResponse { 11 | @NonNull private final Policy policy; 12 | @NonNull private final AccessLevel accessLevel; 13 | @NonNull private final String ownerType; 14 | @NonNull private final Identifiable owner; 15 | @NonNull private final UUID id; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/TokenResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.model.dto; 19 | 20 | import bio.overture.ego.view.Views; 21 | import com.fasterxml.jackson.annotation.JsonView; 22 | import java.util.Set; 23 | import lombok.Builder; 24 | import lombok.NonNull; 25 | import lombok.Value; 26 | 27 | @Deprecated 28 | @Value 29 | @Builder 30 | @JsonView(Views.REST.class) 31 | public class TokenResponse { 32 | @NonNull private final String accessToken; 33 | @NonNull private final Set scope; 34 | @NonNull private final Long exp; 35 | private String description; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/TransactionalDeleteRequest.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import java.util.List; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @Builder 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | /** * A request to delete all of the given groups and policies in a single transaction. */ 14 | public class TransactionalDeleteRequest { 15 | List groupNames; 16 | List policyNames; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/TransactionalGroupPermissionRequest.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.model.enums.AccessLevel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @Builder 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | /** 14 | * * A request create the group, policy and/or permission necessary to ensure that the specified 15 | * group exists, and has a group permission consisting of the specified policy at the specified 16 | * accessLevel. 17 | */ 18 | public class TransactionalGroupPermissionRequest { 19 | private String groupName; 20 | private String policyName; 21 | private AccessLevel mask; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/UpdateApplicationRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.dto; 18 | 19 | import bio.overture.ego.model.enums.ApplicationType; 20 | import bio.overture.ego.model.enums.StatusType; 21 | import lombok.AllArgsConstructor; 22 | import lombok.Builder; 23 | import lombok.Data; 24 | import lombok.NoArgsConstructor; 25 | 26 | @Data 27 | @Builder 28 | @NoArgsConstructor 29 | @AllArgsConstructor 30 | public class UpdateApplicationRequest { 31 | 32 | private String name; 33 | private String clientId; 34 | private ApplicationType type; 35 | private String clientSecret; 36 | private String redirectUri; 37 | private String description; 38 | private StatusType status; 39 | private String errorRedirectUri; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/UpdateUserRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.dto; 18 | 19 | import bio.overture.ego.model.enums.LanguageType; 20 | import bio.overture.ego.model.enums.StatusType; 21 | import bio.overture.ego.model.enums.UserType; 22 | import lombok.*; 23 | 24 | @Data 25 | @Builder 26 | @AllArgsConstructor 27 | @NoArgsConstructor 28 | public class UpdateUserRequest { 29 | 30 | private UserType type; 31 | private StatusType status; 32 | private LanguageType preferredLanguage; 33 | private String firstName; 34 | private String lastName; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/dto/UserScopesResponse.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.dto; 2 | 3 | import bio.overture.ego.view.Views; 4 | import com.fasterxml.jackson.annotation.JsonView; 5 | import java.util.Set; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Getter; 8 | 9 | @AllArgsConstructor 10 | @Getter 11 | @JsonView(Views.REST.class) 12 | public class UserScopesResponse { 13 | 14 | private Set scopes; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/entity/ApplicationPermission.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.entity; 2 | 3 | import bio.overture.ego.model.enums.JavaFields; 4 | import bio.overture.ego.model.enums.SqlFields; 5 | import bio.overture.ego.model.enums.Tables; 6 | import bio.overture.ego.view.Views; 7 | import com.fasterxml.jackson.annotation.JsonView; 8 | import javax.persistence.*; 9 | import lombok.*; 10 | import lombok.experimental.FieldNameConstants; 11 | 12 | @Entity 13 | @Table(name = Tables.APPLICATION_PERMISSION) 14 | @Data 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @JsonView(Views.REST.class) 19 | @ToString(callSuper = true) 20 | @FieldNameConstants 21 | @EqualsAndHashCode( 22 | callSuper = true, 23 | of = {"id"}) 24 | @NamedEntityGraph( 25 | name = "application-permission-entity-with-relationships", 26 | attributeNodes = { 27 | @NamedAttributeNode(value = JavaFields.POLICY), 28 | @NamedAttributeNode(value = JavaFields.OWNER) 29 | }) 30 | public class ApplicationPermission extends AbstractPermission { 31 | 32 | @ManyToOne(fetch = FetchType.LAZY) 33 | @JoinColumn(name = SqlFields.APPID_JOIN, nullable = false) 34 | private Application owner; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/entity/DefaultProvider.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.entity; 2 | 3 | import static bio.overture.ego.model.enums.AccessLevel.EGO_ENUM; 4 | 5 | import bio.overture.ego.model.enums.ProviderType; 6 | import bio.overture.ego.model.enums.SqlFields; 7 | import bio.overture.ego.model.enums.Tables; 8 | import javax.persistence.*; 9 | import lombok.*; 10 | import org.hibernate.annotations.Type; 11 | 12 | @Entity 13 | @Table(name = Tables.DEFAULTPROVIDERTRIPWIRE) 14 | @Data 15 | @EqualsAndHashCode(of = "id") 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class DefaultProvider implements Identifiable { 19 | 20 | @Id 21 | @Column(name = SqlFields.ID, nullable = false) 22 | @Type(type = EGO_ENUM) 23 | @Enumerated(EnumType.STRING) 24 | private ProviderType id; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/entity/GroupPermission.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.entity; 2 | 3 | import bio.overture.ego.model.enums.JavaFields; 4 | import bio.overture.ego.model.enums.SqlFields; 5 | import bio.overture.ego.model.enums.Tables; 6 | import bio.overture.ego.view.Views; 7 | import com.fasterxml.jackson.annotation.JsonInclude; 8 | import com.fasterxml.jackson.annotation.JsonView; 9 | import javax.persistence.Entity; 10 | import javax.persistence.FetchType; 11 | import javax.persistence.JoinColumn; 12 | import javax.persistence.ManyToOne; 13 | import javax.persistence.NamedAttributeNode; 14 | import javax.persistence.NamedEntityGraph; 15 | import javax.persistence.Table; 16 | import lombok.AllArgsConstructor; 17 | import lombok.Data; 18 | import lombok.EqualsAndHashCode; 19 | import lombok.NoArgsConstructor; 20 | import lombok.ToString; 21 | 22 | @Entity 23 | @Table(name = Tables.GROUP_PERMISSION) 24 | @Data 25 | @JsonInclude() 26 | @AllArgsConstructor 27 | @NoArgsConstructor 28 | @JsonView(Views.REST.class) 29 | @ToString( 30 | callSuper = true, 31 | exclude = {"owner"}) 32 | @EqualsAndHashCode( 33 | callSuper = true, 34 | of = {"id"}) 35 | @NamedEntityGraph( 36 | name = "group-permission-entity-with-relationships", 37 | attributeNodes = { 38 | @NamedAttributeNode(value = JavaFields.POLICY), 39 | @NamedAttributeNode(value = JavaFields.OWNER) 40 | }) 41 | public class GroupPermission extends AbstractPermission { 42 | 43 | // Owning side 44 | @ManyToOne(fetch = FetchType.LAZY) 45 | @JoinColumn(name = SqlFields.GROUPID_JOIN, nullable = false) 46 | private Group owner; 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/entity/Identifiable.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.entity; 2 | 3 | public interface Identifiable { 4 | 5 | ID getId(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/entity/InitTripWire.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.entity; 2 | 3 | import bio.overture.ego.model.enums.SqlFields; 4 | import bio.overture.ego.model.enums.Tables; 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.Id; 8 | import javax.persistence.Table; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Builder; 11 | import lombok.Data; 12 | import lombok.NoArgsConstructor; 13 | 14 | @Data 15 | @Entity 16 | @Builder 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @Table(name = Tables.INITTRIPWIRE) 20 | public class InitTripWire { 21 | 22 | @Id 23 | @Column(name = SqlFields.INITIALIZED) 24 | // 0 for false, >0 for true 25 | private int initialized; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/entity/NameableEntity.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.entity; 2 | 3 | public interface NameableEntity extends Identifiable { 4 | 5 | String getName(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/entity/PolicyOwner.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.entity; 2 | 3 | public interface PolicyOwner {} 4 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/entity/RefreshToken.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.entity; 2 | 3 | import bio.overture.ego.model.enums.SqlFields; 4 | import bio.overture.ego.model.enums.Tables; 5 | import com.fasterxml.jackson.annotation.JsonIgnore; 6 | import java.util.*; 7 | import javax.persistence.*; 8 | import javax.validation.constraints.NotNull; 9 | import lombok.*; 10 | import lombok.experimental.FieldNameConstants; 11 | import org.hibernate.annotations.GenericGenerator; 12 | 13 | @Entity 14 | @Table(name = Tables.REFRESHTOKEN) 15 | @Data 16 | @Builder 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @FieldNameConstants 20 | @ToString(exclude = {"user"}) 21 | public class RefreshToken implements Identifiable { 22 | 23 | @Id 24 | @Column(name = SqlFields.ID, nullable = false, updatable = false) 25 | @GenericGenerator(name = "refresh_uuid", strategy = "org.hibernate.id.UUIDGenerator") 26 | @GeneratedValue(generator = "refresh_uuid") 27 | private UUID id; 28 | 29 | @JsonIgnore 30 | @OneToOne(fetch = FetchType.LAZY) 31 | @JoinColumn(name = SqlFields.USERID_JOIN, referencedColumnName = SqlFields.ID, nullable = false) 32 | private User user; 33 | 34 | @NotNull 35 | @Column(name = SqlFields.JTI, updatable = false, nullable = false) 36 | private UUID jti; 37 | 38 | @NotNull 39 | @Column(name = SqlFields.ISSUEDATE) 40 | @Temporal(value = TemporalType.TIMESTAMP) 41 | private Date issueDate; 42 | 43 | @NotNull 44 | @Column(name = SqlFields.EXPIRYDATE) 45 | @Temporal(value = TemporalType.TIMESTAMP) 46 | private Date expiryDate; 47 | 48 | public Long getSecondsUntilExpiry() { 49 | val seconds = expiryDate.getTime() / 1000L - Calendar.getInstance().getTime().getTime() / 1000L; 50 | return seconds > 0 ? seconds : 0; 51 | } 52 | 53 | public void associateWithUser(@NonNull User user) { 54 | this.setUser(user); 55 | user.setRefreshToken(this); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/entity/UserPermission.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.entity; 2 | 3 | import bio.overture.ego.model.enums.JavaFields; 4 | import bio.overture.ego.model.enums.SqlFields; 5 | import bio.overture.ego.model.enums.Tables; 6 | import bio.overture.ego.view.Views; 7 | import com.fasterxml.jackson.annotation.JsonView; 8 | import javax.persistence.Entity; 9 | import javax.persistence.FetchType; 10 | import javax.persistence.JoinColumn; 11 | import javax.persistence.ManyToOne; 12 | import javax.persistence.NamedAttributeNode; 13 | import javax.persistence.NamedEntityGraph; 14 | import javax.persistence.Table; 15 | import lombok.AllArgsConstructor; 16 | import lombok.Builder; 17 | import lombok.Data; 18 | import lombok.EqualsAndHashCode; 19 | import lombok.NoArgsConstructor; 20 | import lombok.ToString; 21 | import lombok.experimental.FieldNameConstants; 22 | 23 | @Entity 24 | @Table(name = Tables.USER_PERMISSION) 25 | @Data 26 | @Builder 27 | @NoArgsConstructor 28 | @AllArgsConstructor 29 | @JsonView(Views.REST.class) 30 | @ToString(callSuper = true) 31 | @FieldNameConstants 32 | @EqualsAndHashCode( 33 | callSuper = true, 34 | of = {"id"}) 35 | @NamedEntityGraph( 36 | name = "user-permission-entity-with-relationships", 37 | attributeNodes = { 38 | @NamedAttributeNode(value = JavaFields.POLICY), 39 | @NamedAttributeNode(value = JavaFields.OWNER) 40 | }) 41 | public class UserPermission extends AbstractPermission { 42 | 43 | @ManyToOne(fetch = FetchType.LAZY) 44 | @JoinColumn(name = SqlFields.USERID_JOIN, nullable = false) 45 | private User owner; 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/enums/ApplicationStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.enums; 18 | 19 | import lombok.NonNull; 20 | import lombok.RequiredArgsConstructor; 21 | 22 | @RequiredArgsConstructor 23 | public enum ApplicationStatus { 24 | APPROVED("Approved"), 25 | DISABLED("Disabled"), 26 | PENDING("Pending"), 27 | REJECTED("Rejected"), 28 | ; 29 | 30 | @NonNull private final String value; 31 | 32 | @Override 33 | public String toString() { 34 | return value; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/enums/ApplicationType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.enums; 18 | 19 | public enum ApplicationType { 20 | CLIENT, 21 | ADMIN; 22 | 23 | @Override 24 | public String toString() { 25 | return this.name(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/enums/Fields.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License; Version 2.0 (the "License" ; 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing; software 11 | * distributed under the License is distributed on an "AS IS" BASIS; 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND; either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.enums; 18 | 19 | import static lombok.AccessLevel.PRIVATE; 20 | 21 | import lombok.NoArgsConstructor; 22 | 23 | @NoArgsConstructor(access = PRIVATE) 24 | public class Fields { 25 | 26 | public static final String ID = "id"; 27 | public static final String NAME = "name"; 28 | public static final String EMAIL = "email"; 29 | public static final String PROVIDERTYPE = "providerType"; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/enums/LanguageType.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.enums; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | 5 | @RequiredArgsConstructor 6 | public enum LanguageType { 7 | ENGLISH, 8 | FRENCH, 9 | SPANISH; 10 | 11 | @Override 12 | public String toString() { 13 | return this.name(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/enums/LinkedinContactType.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.enums; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | 5 | @RequiredArgsConstructor 6 | public enum LinkedinContactType { 7 | EMAIL, 8 | PHONE; 9 | 10 | @Override 11 | public String toString() { 12 | return this.name(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/enums/LombokFields.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.enums; 2 | 3 | import static lombok.AccessLevel.PRIVATE; 4 | 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * Note: When using a Lombok annotation with field names (for example @EqualsAndHashCode(ids = 9 | * {LombokFields.id}) lombok does not look at the variable's value, but instead takes the variables 10 | * name as the value. https://github.com/rzwitserloot/lombok/issues/1094 11 | */ 12 | @NoArgsConstructor(access = PRIVATE) 13 | public class LombokFields { 14 | 15 | public static final String id = "doesn't matter, lombok doesnt use this string"; 16 | public static final String groups = "doesn't matter, lombok doesnt use this string"; 17 | public static final String userApplications = "doesn't matter, lombok doesnt use this string"; 18 | public static final String policy = "doesn't matter, lombok doesnt use this string"; 19 | public static final String userPermissions = "doesn't matter, lombok doesnt use this string"; 20 | public static final String owner = "doesn't matter, lombok doesnt use this string"; 21 | public static final String scopes = "doesn't matter, lombok doesnt use this string"; 22 | public static final String users = "doesn't matter, lombok doesnt use this string"; 23 | public static final String permissions = "doesn't matter, lombok doesnt use this string"; 24 | public static final String tokens = "doesn't matter, lombok doesnt use this string"; 25 | public static final String userGroups = "doesn't matter, lombok doesnt use this string"; 26 | public static final String groupApplications = "doesn't matter, lombok doesnt use this string"; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/enums/ProviderType.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.enums; 2 | 3 | import static bio.overture.ego.utils.Joiners.COMMA; 4 | import static bio.overture.ego.utils.Streams.stream; 5 | import static java.lang.String.format; 6 | 7 | import bio.overture.ego.model.exceptions.ForbiddenException; 8 | import lombok.NonNull; 9 | import lombok.RequiredArgsConstructor; 10 | 11 | @RequiredArgsConstructor 12 | public enum ProviderType { 13 | GOOGLE, 14 | FACEBOOK, 15 | LINKEDIN, 16 | GITHUB, 17 | ORCID, 18 | KEYCLOAK; 19 | 20 | // TODO: verify these are the correct accessor keys for each provider 21 | public static String getIdAccessor(ProviderType provider) { 22 | if (provider.equals(GOOGLE) || provider.equals(ORCID) || provider.equals(KEYCLOAK)) { 23 | return "sub"; 24 | } 25 | 26 | if (provider.equals(FACEBOOK)) { 27 | return "user_id"; 28 | } 29 | 30 | // from LinkedIn: "Each member id is unique to the context of your application only. Sharing a 31 | // person ID across applications will not work and result in a 404 error." 32 | // https://docs.microsoft.com/en-us/linkedin/shared/integrations/people/profile-api#person-id 33 | if (provider.equals(LINKEDIN) || provider.equals(GITHUB)) { 34 | return "id"; 35 | } 36 | 37 | throw new ForbiddenException(format("Provider '%s' is not a valid providerType", provider)); 38 | } 39 | 40 | public static ProviderType resolveProviderType(@NonNull String providerType) { 41 | return stream(values()) 42 | .filter(x -> x.toString().equalsIgnoreCase(providerType)) 43 | .findFirst() 44 | .orElseThrow( 45 | () -> 46 | new IllegalArgumentException( 47 | format( 48 | "The provider type '%s' cannot be resolved. Must be one of: [%s]", 49 | providerType, COMMA.join(values())))); 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return this.name(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/enums/StatusType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.enums; 18 | 19 | import static bio.overture.ego.utils.Joiners.COMMA; 20 | import static bio.overture.ego.utils.Streams.stream; 21 | import static java.lang.String.format; 22 | 23 | import lombok.NonNull; 24 | import lombok.RequiredArgsConstructor; 25 | 26 | @RequiredArgsConstructor 27 | public enum StatusType { 28 | APPROVED, 29 | DISABLED, 30 | PENDING, 31 | REJECTED; 32 | 33 | public static StatusType resolveStatusType(@NonNull String statusType) { 34 | return stream(values()) 35 | .filter(x -> x.toString().equals(statusType)) 36 | .findFirst() 37 | .orElseThrow( 38 | () -> 39 | new IllegalArgumentException( 40 | format( 41 | "The status type '%s' cannot be resolved. Must be one of: [%s]", 42 | statusType, COMMA.join(values())))); 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return this.name(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/enums/Tables.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.enums; 2 | 3 | import static lombok.AccessLevel.PRIVATE; 4 | 5 | import lombok.NoArgsConstructor; 6 | 7 | @NoArgsConstructor(access = PRIVATE) 8 | public class Tables { 9 | 10 | public static final String APPLICATION = "egoapplication"; 11 | public static final String GROUP = "egogroup"; 12 | public static final String TOKEN = "token"; 13 | public static final String GROUP_APPLICATION = "groupapplication"; 14 | public static final String USER_GROUP = "usergroup"; 15 | public static final String EGOUSER = "egouser"; 16 | public static final String USER_APPLICATION = "userapplication"; 17 | public static final String USER_PERMISSION = "userpermission"; 18 | public static final String GROUP_PERMISSION = "grouppermission"; 19 | public static final String POLICY = "policy"; 20 | public static final String TOKENSCOPE = "tokenscope"; 21 | public static final String REFRESHTOKEN = "refreshtoken"; 22 | public static final String APPLICATION_PERMISSION = "applicationpermission"; 23 | public static final String DEFAULTPROVIDERTRIPWIRE = "defaultprovidertripwire"; 24 | public static final String INITTRIPWIRE = "inittripwire"; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/enums/UserType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.enums; 18 | 19 | import static bio.overture.ego.utils.Joiners.COMMA; 20 | import static bio.overture.ego.utils.Streams.stream; 21 | import static java.lang.String.format; 22 | 23 | import lombok.NonNull; 24 | import lombok.RequiredArgsConstructor; 25 | 26 | @RequiredArgsConstructor 27 | public enum UserType { 28 | USER, 29 | ADMIN; 30 | 31 | public static UserType resolveUserType(@NonNull String userType) { 32 | return stream(values()) 33 | .filter(x -> x.toString().equals(userType)) 34 | .findFirst() 35 | .orElseThrow( 36 | () -> 37 | new IllegalArgumentException( 38 | format( 39 | "The user type '%s' cannot be resolved. Must be one of: [%s]", 40 | userType, COMMA.join(values())))); 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return this.name(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/ForbiddenException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.model.exceptions; 19 | 20 | import static org.springframework.http.HttpStatus.FORBIDDEN; 21 | 22 | import lombok.NonNull; 23 | import org.springframework.web.bind.annotation.ResponseStatus; 24 | 25 | @ResponseStatus(FORBIDDEN) 26 | public class ForbiddenException extends RuntimeException { 27 | 28 | public ForbiddenException(@NonNull String message) { 29 | super(message); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/InvalidRequestException.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.exceptions; 2 | 3 | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; 4 | 5 | public class InvalidRequestException extends OAuth2Exception { 6 | public InvalidRequestException(String message) { 7 | super(OAuth2ErrorCodes.INVALID_REQUEST, message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/InvalidScopeException.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.exceptions; 2 | 3 | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; 4 | 5 | public class InvalidScopeException extends OAuth2Exception { 6 | public InvalidScopeException(String message) { 7 | super(OAuth2ErrorCodes.INVALID_SCOPE, message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/InvalidTokenException.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.exceptions; 2 | 3 | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; 4 | 5 | public class InvalidTokenException extends OAuth2Exception { 6 | public InvalidTokenException(String message) { 7 | super(OAuth2ErrorCodes.INVALID_TOKEN, message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/NoPrimaryEmailException.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.exceptions; 2 | 3 | import static org.springframework.http.HttpStatus.FORBIDDEN; 4 | 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | 8 | @Slf4j 9 | @ResponseStatus(FORBIDDEN) 10 | public class NoPrimaryEmailException extends InvalidTokenException { 11 | 12 | public NoPrimaryEmailException(String msg) { 13 | super(msg); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/OAuth2Exception.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.exceptions; 2 | 3 | public class OAuth2Exception extends RuntimeException { 4 | protected String code; 5 | 6 | public OAuth2Exception(String code, String message) { 7 | super(message); 8 | this.code = code; 9 | } 10 | 11 | public String getCode() { 12 | return code; 13 | } 14 | 15 | @Override 16 | public String getMessage() { 17 | return super.getMessage(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/RequestValidationException.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.exceptions; 2 | 3 | import static bio.overture.ego.utils.Collectors.toImmutableSet; 4 | import static bio.overture.ego.utils.Joiners.PRETTY_COMMA; 5 | import static java.lang.String.format; 6 | import static org.springframework.http.HttpStatus.BAD_REQUEST; 7 | 8 | import javax.validation.Validation; 9 | import javax.validation.Validator; 10 | import lombok.NonNull; 11 | import lombok.val; 12 | import org.springframework.web.bind.annotation.ResponseStatus; 13 | 14 | @ResponseStatus(BAD_REQUEST) 15 | public class RequestValidationException extends RuntimeException { 16 | 17 | /** 18 | * Validator is thread-safe so can be a constant 19 | * https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#_validating_constraints 20 | */ 21 | private static final Validator VALIDATOR = 22 | Validation.buildDefaultValidatorFactory().getValidator(); 23 | 24 | public RequestValidationException(String message) { 25 | super(message); 26 | } 27 | 28 | public static void checkRequestValid(@NonNull T objectToValidate) { 29 | val errors = VALIDATOR.validate(objectToValidate); 30 | if (!errors.isEmpty()) { 31 | val requestViolations = 32 | errors.stream().map(RequestViolation::createRequestViolation).collect(toImmutableSet()); 33 | val formattedMessage = 34 | "The object of type '%s' with value '%s' has the following constraint violations: [%s]"; 35 | throw new RequestValidationException( 36 | format( 37 | formattedMessage, 38 | objectToValidate.getClass().getSimpleName(), 39 | objectToValidate, 40 | PRETTY_COMMA.join(requestViolations))); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/RequestViolation.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.exceptions; 2 | 3 | import javax.validation.ConstraintViolation; 4 | import lombok.Builder; 5 | import lombok.NonNull; 6 | import lombok.Value; 7 | 8 | @Value 9 | @Builder 10 | public class RequestViolation { 11 | @NonNull private final String fieldName; 12 | private final Object fieldValue; 13 | @NonNull private final String error; 14 | 15 | public static RequestViolation createRequestViolation(ConstraintViolation v) { 16 | return RequestViolation.builder() 17 | .error(v.getMessage()) 18 | .fieldName(v.getPropertyPath().toString()) 19 | .fieldValue(v.getInvalidValue()) 20 | .build(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/UnauthorizedClientException.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.exceptions; 2 | 3 | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; 4 | 5 | public class UnauthorizedClientException extends OAuth2Exception { 6 | public UnauthorizedClientException(String message) { 7 | super(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT, message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/UnauthorizedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.model.exceptions; 19 | 20 | import static org.springframework.http.HttpStatus.UNAUTHORIZED; 21 | 22 | import lombok.NonNull; 23 | import org.springframework.web.bind.annotation.ResponseStatus; 24 | 25 | @ResponseStatus(UNAUTHORIZED) 26 | public class UnauthorizedException extends RuntimeException { 27 | 28 | public UnauthorizedException(@NonNull String message) { 29 | super(message); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/exceptions/UniqueViolationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the terms of the GNU Public License v3.0. 5 | * You should have received a copy of the GNU General Public License along with 6 | * this program. If not, see . 7 | * 8 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 9 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 10 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 11 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 12 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 13 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 14 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 15 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 16 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 17 | */ 18 | package bio.overture.ego.model.exceptions; 19 | 20 | import static java.lang.String.format; 21 | import static org.springframework.http.HttpStatus.CONFLICT; 22 | 23 | import lombok.NonNull; 24 | import org.springframework.web.bind.annotation.ResponseStatus; 25 | 26 | @ResponseStatus(CONFLICT) 27 | public class UniqueViolationException extends RuntimeException { 28 | public UniqueViolationException(@NonNull String message) { 29 | super(message); 30 | } 31 | 32 | public static void checkUnique( 33 | boolean expression, @NonNull String formattedMessage, @NonNull Object... args) { 34 | if (!expression) { 35 | throw new UniqueViolationException(format(formattedMessage, args)); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/join/GroupApplication.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.join; 2 | 3 | import bio.overture.ego.model.entity.Application; 4 | import bio.overture.ego.model.entity.Group; 5 | import bio.overture.ego.model.entity.Identifiable; 6 | import bio.overture.ego.model.enums.JavaFields; 7 | import bio.overture.ego.model.enums.SqlFields; 8 | import bio.overture.ego.model.enums.Tables; 9 | import javax.persistence.CascadeType; 10 | import javax.persistence.EmbeddedId; 11 | import javax.persistence.Entity; 12 | import javax.persistence.FetchType; 13 | import javax.persistence.JoinColumn; 14 | import javax.persistence.ManyToOne; 15 | import javax.persistence.MapsId; 16 | import javax.persistence.Table; 17 | import lombok.AllArgsConstructor; 18 | import lombok.Builder; 19 | import lombok.Data; 20 | import lombok.EqualsAndHashCode; 21 | import lombok.NoArgsConstructor; 22 | import lombok.ToString; 23 | 24 | @Data 25 | @Entity 26 | @Table(name = Tables.GROUP_APPLICATION) 27 | @Builder 28 | @EqualsAndHashCode(of = "id") 29 | @NoArgsConstructor 30 | @AllArgsConstructor 31 | @ToString(exclude = {"group", "application"}) 32 | public class GroupApplication implements Identifiable { 33 | 34 | @EmbeddedId private GroupApplicationId id; 35 | 36 | @MapsId(value = JavaFields.GROUP_ID) 37 | @JoinColumn(name = SqlFields.GROUPID_JOIN, nullable = false, updatable = false) 38 | @ManyToOne( 39 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 40 | fetch = FetchType.LAZY) 41 | private Group group; 42 | 43 | @MapsId(value = JavaFields.APPLICATION_ID) 44 | @JoinColumn(name = SqlFields.APPID_JOIN, nullable = false, updatable = false) 45 | @ManyToOne( 46 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 47 | fetch = FetchType.LAZY) 48 | private Application application; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/join/GroupApplicationId.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.join; 2 | 3 | import bio.overture.ego.model.enums.SqlFields; 4 | import java.io.Serializable; 5 | import java.util.UUID; 6 | import javax.persistence.Column; 7 | import javax.persistence.Embeddable; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Builder; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | 13 | @Data 14 | @Builder 15 | @Embeddable 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class GroupApplicationId implements Serializable { 19 | 20 | @Column(name = SqlFields.GROUPID_JOIN) 21 | private UUID groupId; 22 | 23 | @Column(name = SqlFields.APPID_JOIN) 24 | private UUID applicationId; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/join/UserApplication.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.join; 2 | 3 | import bio.overture.ego.model.entity.Application; 4 | import bio.overture.ego.model.entity.Identifiable; 5 | import bio.overture.ego.model.entity.User; 6 | import bio.overture.ego.model.enums.JavaFields; 7 | import bio.overture.ego.model.enums.SqlFields; 8 | import bio.overture.ego.model.enums.Tables; 9 | import javax.persistence.CascadeType; 10 | import javax.persistence.EmbeddedId; 11 | import javax.persistence.Entity; 12 | import javax.persistence.FetchType; 13 | import javax.persistence.JoinColumn; 14 | import javax.persistence.ManyToOne; 15 | import javax.persistence.MapsId; 16 | import javax.persistence.Table; 17 | import lombok.AllArgsConstructor; 18 | import lombok.Builder; 19 | import lombok.Data; 20 | import lombok.EqualsAndHashCode; 21 | import lombok.NoArgsConstructor; 22 | import lombok.ToString; 23 | 24 | @Data 25 | @Entity 26 | @Table(name = Tables.USER_APPLICATION) 27 | @Builder 28 | @EqualsAndHashCode(of = "id") 29 | @NoArgsConstructor 30 | @AllArgsConstructor 31 | @ToString(exclude = {"user", "application"}) 32 | public class UserApplication implements Identifiable { 33 | 34 | @EmbeddedId private UserApplicationId id; 35 | 36 | @MapsId(value = JavaFields.USER_ID) 37 | @JoinColumn(name = SqlFields.USERID_JOIN, nullable = false, updatable = false) 38 | @ManyToOne( 39 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 40 | fetch = FetchType.LAZY) 41 | private User user; 42 | 43 | @MapsId(value = JavaFields.APPLICATION_ID) 44 | @JoinColumn(name = SqlFields.APPID_JOIN, nullable = false, updatable = false) 45 | @ManyToOne( 46 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 47 | fetch = FetchType.LAZY) 48 | private Application application; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/join/UserApplicationId.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.join; 2 | 3 | import bio.overture.ego.model.enums.SqlFields; 4 | import java.io.Serializable; 5 | import java.util.UUID; 6 | import javax.persistence.Column; 7 | import javax.persistence.Embeddable; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Builder; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | 13 | @Data 14 | @Builder 15 | @Embeddable 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class UserApplicationId implements Serializable { 19 | 20 | @Column(name = SqlFields.USERID_JOIN) 21 | private UUID userId; 22 | 23 | @Column(name = SqlFields.APPID_JOIN) 24 | private UUID applicationId; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/join/UserGroup.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.join; 2 | 3 | import bio.overture.ego.model.entity.Group; 4 | import bio.overture.ego.model.entity.Identifiable; 5 | import bio.overture.ego.model.entity.User; 6 | import bio.overture.ego.model.enums.JavaFields; 7 | import bio.overture.ego.model.enums.SqlFields; 8 | import bio.overture.ego.model.enums.Tables; 9 | import javax.persistence.CascadeType; 10 | import javax.persistence.EmbeddedId; 11 | import javax.persistence.Entity; 12 | import javax.persistence.FetchType; 13 | import javax.persistence.JoinColumn; 14 | import javax.persistence.ManyToOne; 15 | import javax.persistence.MapsId; 16 | import javax.persistence.Table; 17 | import lombok.AllArgsConstructor; 18 | import lombok.Builder; 19 | import lombok.Data; 20 | import lombok.EqualsAndHashCode; 21 | import lombok.NoArgsConstructor; 22 | import lombok.ToString; 23 | 24 | @Data 25 | @Entity 26 | @Table(name = Tables.USER_GROUP) 27 | @Builder 28 | @EqualsAndHashCode(of = "id") 29 | @NoArgsConstructor 30 | @AllArgsConstructor 31 | @ToString(exclude = {"user", "group"}) 32 | public class UserGroup implements Identifiable { 33 | 34 | @EmbeddedId private UserGroupId id; 35 | 36 | @MapsId(value = JavaFields.USER_ID) 37 | @JoinColumn(name = SqlFields.USERID_JOIN, nullable = false, updatable = false) 38 | @ManyToOne( 39 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 40 | fetch = FetchType.LAZY) 41 | private User user; 42 | 43 | @MapsId(value = JavaFields.GROUP_ID) 44 | @JoinColumn(name = SqlFields.GROUPID_JOIN, nullable = false, updatable = false) 45 | @ManyToOne( 46 | cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 47 | fetch = FetchType.LAZY) 48 | private Group group; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/join/UserGroupId.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.join; 2 | 3 | import bio.overture.ego.model.enums.SqlFields; 4 | import java.io.Serializable; 5 | import java.util.UUID; 6 | import javax.persistence.Column; 7 | import javax.persistence.Embeddable; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Builder; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | 13 | @Data 14 | @Builder 15 | @Embeddable 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class UserGroupId implements Serializable { 19 | 20 | @Column(name = SqlFields.USERID_JOIN) 21 | private UUID userId; 22 | 23 | @Column(name = SqlFields.GROUPID_JOIN) 24 | private UUID groupId; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/params/ScopeName.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.params; 2 | 3 | import static java.lang.String.format; 4 | 5 | import bio.overture.ego.model.enums.AccessLevel; 6 | import bio.overture.ego.model.exceptions.InvalidScopeException; 7 | import lombok.Data; 8 | 9 | @Data 10 | public class ScopeName { 11 | private String scopeName; 12 | 13 | public ScopeName(String name) { 14 | if (!name.contains(".")) { 15 | throw new InvalidScopeException( 16 | format("Bad scope name '%s'. Must be of the form \".\"", name)); 17 | } 18 | scopeName = name; 19 | } 20 | 21 | public AccessLevel getAccessLevel() { 22 | return AccessLevel.fromValue(scopeName.substring(scopeName.lastIndexOf(".") + 1)); 23 | } 24 | 25 | public String getName() { 26 | return scopeName.substring(0, scopeName.lastIndexOf(".")); 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return scopeName; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/search/Filters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.search; 18 | 19 | import java.lang.annotation.*; 20 | 21 | @Target(ElementType.PARAMETER) 22 | @Retention(RetentionPolicy.RUNTIME) 23 | @Documented 24 | public @interface Filters {} 25 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/model/search/SearchFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.model.search; 18 | 19 | import lombok.Data; 20 | import lombok.NonNull; 21 | import lombok.RequiredArgsConstructor; 22 | 23 | @Data 24 | @RequiredArgsConstructor 25 | public class SearchFilter { 26 | 27 | @NonNull private String filterField; 28 | @NonNull private String filterValue; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/ApplicationPermissionRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import static org.springframework.data.jpa.repository.EntityGraph.EntityGraphType.FETCH; 4 | 5 | import bio.overture.ego.model.entity.Application; 6 | import bio.overture.ego.model.entity.ApplicationPermission; 7 | import java.util.Set; 8 | import java.util.UUID; 9 | import org.springframework.data.jpa.repository.EntityGraph; 10 | 11 | public interface ApplicationPermissionRepository 12 | extends NameablePermissionRepository { 13 | 14 | @EntityGraph(value = "application-permission-entity-with-relationships", type = FETCH) 15 | Set findAllByOwner_Id(UUID id); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/ApplicationRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.repository; 18 | 19 | import bio.overture.ego.model.entity.Application; 20 | import java.util.List; 21 | import java.util.Optional; 22 | import java.util.Set; 23 | import java.util.UUID; 24 | 25 | public interface ApplicationRepository extends NamedRepository { 26 | 27 | Optional getApplicationByNameIgnoreCase(String name); 28 | 29 | boolean existsByClientIdIgnoreCase(String clientId); 30 | 31 | boolean existsByNameIgnoreCase(String name); 32 | 33 | Set findAllByIdIn(List ids); 34 | 35 | /** Refer to NamedRepository.findByName Deprecation note */ 36 | @Override 37 | @Deprecated 38 | default Optional findByName(String name) { 39 | return getApplicationByNameIgnoreCase(name); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/BaseRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import java.util.Collection; 4 | import java.util.Set; 5 | import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 6 | import org.springframework.data.repository.NoRepositoryBean; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | 9 | @NoRepositoryBean 10 | public interface BaseRepository 11 | extends PagingAndSortingRepository, JpaSpecificationExecutor { 12 | T findFirstBy(); 13 | 14 | Set findAllByIdIn(Collection ids); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/DefaultProviderRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import bio.overture.ego.model.entity.DefaultProvider; 4 | import bio.overture.ego.model.enums.ProviderType; 5 | 6 | public interface DefaultProviderRepository extends BaseRepository {} 7 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/GroupPermissionRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import static org.springframework.data.jpa.repository.EntityGraph.EntityGraphType.FETCH; 4 | 5 | import bio.overture.ego.model.entity.Group; 6 | import bio.overture.ego.model.entity.GroupPermission; 7 | import java.util.Set; 8 | import java.util.UUID; 9 | import org.springframework.data.jpa.repository.EntityGraph; 10 | 11 | public interface GroupPermissionRepository 12 | extends NameablePermissionRepository { 13 | 14 | @EntityGraph(value = "group-permission-entity-with-relationships", type = FETCH) 15 | Set findAllByOwner_Id(UUID id); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/GroupRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.repository; 18 | 19 | import bio.overture.ego.model.entity.Group; 20 | import java.util.Optional; 21 | import java.util.UUID; 22 | 23 | public interface GroupRepository extends NamedRepository { 24 | 25 | Optional getGroupByNameIgnoreCase(String name); 26 | 27 | boolean existsByNameIgnoreCase(String name); 28 | 29 | /** Refer to NamedRepository.findByName Deprecation note */ 30 | @Override 31 | @Deprecated 32 | default Optional findByName(String name) { 33 | return getGroupByNameIgnoreCase(name); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/InitTripWireRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import bio.overture.ego.model.entity.InitTripWire; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface InitTripWireRepository extends JpaRepository {} 7 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/NameablePermissionRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import bio.overture.ego.model.entity.AbstractPermission; 4 | import bio.overture.ego.model.entity.NameableEntity; 5 | import java.util.UUID; 6 | import org.springframework.data.repository.NoRepositoryBean; 7 | 8 | @NoRepositoryBean 9 | public interface NameablePermissionRepository< 10 | O extends NameableEntity, T extends AbstractPermission> 11 | extends PermissionRepository {} 12 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/NamedRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import java.util.Optional; 4 | import org.springframework.data.repository.NoRepositoryBean; 5 | 6 | @NoRepositoryBean 7 | public interface NamedRepository extends BaseRepository { 8 | 9 | /** 10 | * TODO: [rtisma] Deprecated because this should be implemented at the service layer using dynamic 11 | * fetching and not the entity graph. Leaving this for now. Once all services are implementing \ 12 | * findByName, this can be removed from the NameRepository interface, and anything extending it 13 | */ 14 | @Deprecated 15 | Optional findByName(String name); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/PermissionRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import bio.overture.ego.model.entity.AbstractPermission; 4 | import bio.overture.ego.model.entity.Identifiable; 5 | import bio.overture.ego.model.enums.AccessLevel; 6 | import java.util.Optional; 7 | import java.util.Set; 8 | import java.util.UUID; 9 | import org.springframework.data.repository.NoRepositoryBean; 10 | 11 | @NoRepositoryBean 12 | public interface PermissionRepository, T extends AbstractPermission> 13 | extends BaseRepository { 14 | 15 | Set findAllByPolicy_Id(UUID id); 16 | 17 | Set findAllByOwner_Id(UUID id); 18 | 19 | Optional findByPolicy_IdAndOwner_id(UUID policyId, UUID ownerId); 20 | 21 | Set findAllByPolicy_IdAndAccessLevel(UUID policyId, AccessLevel accessLevel); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/PolicyRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import static org.springframework.data.jpa.repository.EntityGraph.EntityGraphType.FETCH; 4 | 5 | import bio.overture.ego.model.entity.Policy; 6 | import java.util.Optional; 7 | import java.util.UUID; 8 | import org.springframework.data.jpa.repository.EntityGraph; 9 | 10 | public interface PolicyRepository extends NamedRepository { 11 | 12 | @EntityGraph(value = "policy-entity-with-relationships", type = FETCH) 13 | Optional getPolicyByNameIgnoreCase(String name); 14 | 15 | boolean existsByNameIgnoreCase(String name); 16 | 17 | /** Refer to NamedRepository.findByName Deprecation note */ 18 | @Override 19 | @Deprecated 20 | default Optional findByName(String name) { 21 | return getPolicyByNameIgnoreCase(name); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/RefreshTokenRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import bio.overture.ego.model.entity.RefreshToken; 4 | import bio.overture.ego.model.entity.User; 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface RefreshTokenRepository extends BaseRepository { 9 | 10 | Optional getByUser(User user); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/TokenStoreRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import bio.overture.ego.model.entity.ApiKey; 4 | import java.util.List; 5 | import java.util.Optional; 6 | import java.util.Set; 7 | import java.util.UUID; 8 | import org.springframework.data.jpa.repository.Modifying; 9 | import org.springframework.data.jpa.repository.Query; 10 | import org.springframework.data.repository.query.Param; 11 | 12 | public interface TokenStoreRepository extends NamedRepository { 13 | 14 | Optional getTokenByNameIgnoreCase(String name); 15 | 16 | ApiKey findOneByNameIgnoreCase(String token); 17 | 18 | Set findAllByIdIn(List ids); 19 | 20 | @Modifying 21 | @Query( 22 | value = 23 | "update token set isrevoked=true where token.id in (select revokes.id from ((select token.id, string_agg(concat(cast (tokenscope.policy_id as text), '.', tokenscope.access_level), ',' order by tokenscope.policy_id, tokenscope.access_level) as policies from token left join tokenscope on token.id = tokenscope.token_id where token.owner=:userId group by token.id order by policies, token.issuedate desc) EXCEPT (select distinct on (policies) token.id, string_agg(concat(cast (tokenscope.policy_id as text), '.', tokenscope.access_level), ',' order by tokenscope.policy_id, tokenscope.access_level) as policies from token left join tokenscope on token.id = tokenscope.token_id where token.owner=:userId group by token.id order by policies, token.issuedate desc)) as revokes)", 24 | nativeQuery = true) 25 | int revokeRedundantTokens(@Param("userId") UUID userId); 26 | 27 | // Set findAllByOwnerAndScopes(List ids); 28 | 29 | @Override 30 | default Optional findByName(String name) { 31 | return getTokenByNameIgnoreCase(name); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/UserPermissionRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository; 2 | 3 | import static org.springframework.data.jpa.repository.EntityGraph.EntityGraphType.FETCH; 4 | 5 | import bio.overture.ego.model.entity.User; 6 | import bio.overture.ego.model.entity.UserPermission; 7 | import java.util.Set; 8 | import java.util.UUID; 9 | import org.springframework.data.jpa.repository.EntityGraph; 10 | 11 | public interface UserPermissionRepository extends PermissionRepository { 12 | 13 | @EntityGraph(value = "user-permission-entity-with-relationships", type = FETCH) 14 | Set findAllByOwner_Id(UUID id); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.repository; 18 | 19 | import bio.overture.ego.model.entity.User; 20 | import bio.overture.ego.model.enums.ProviderType; 21 | import java.util.Collection; 22 | import java.util.Optional; 23 | import java.util.Set; 24 | import java.util.UUID; 25 | 26 | public interface UserRepository extends BaseRepository { 27 | 28 | Set findAllByIdIn(Collection userIds); 29 | 30 | boolean existsByProviderTypeAndProviderSubjectId( 31 | ProviderType providerType, String providerSubjectId); 32 | 33 | boolean existsByProviderSubjectId(String providerSubjectId); 34 | 35 | Optional findByProviderSubjectIdIgnoreCaseAndProviderType( 36 | String providerSubjectId, ProviderType providerType); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/join/UserGroupRepository.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository.join; 2 | 3 | import bio.overture.ego.model.join.UserGroup; 4 | import bio.overture.ego.model.join.UserGroupId; 5 | import bio.overture.ego.repository.BaseRepository; 6 | 7 | public interface UserGroupRepository extends BaseRepository {} 8 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/queryspecification/ApplicationPermissionSpecification.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository.queryspecification; 2 | 3 | import bio.overture.ego.model.entity.ApplicationPermission; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | @Slf4j 7 | public class ApplicationPermissionSpecification 8 | extends AbstractPermissionSpecification {} 9 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/queryspecification/GroupPermissionSpecification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.repository.queryspecification; 18 | 19 | import bio.overture.ego.model.entity.GroupPermission; 20 | import lombok.extern.slf4j.Slf4j; 21 | 22 | @Slf4j 23 | public class GroupPermissionSpecification 24 | extends AbstractPermissionSpecification {} 25 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/queryspecification/PolicySpecification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.repository.queryspecification; 18 | 19 | import static bio.overture.ego.model.enums.JavaFields.NAME; 20 | 21 | import bio.overture.ego.model.entity.Policy; 22 | import bio.overture.ego.model.entity.User; 23 | import bio.overture.ego.utils.QueryUtils; 24 | import lombok.NonNull; 25 | import lombok.val; 26 | import org.springframework.data.jpa.domain.Specification; 27 | 28 | public class PolicySpecification extends SpecificationBase { 29 | 30 | public static Specification containsText(@NonNull String text) { 31 | val finalText = QueryUtils.prepareForQuery(text); 32 | return (root, query, builder) -> { 33 | query.distinct(true); 34 | return builder.or(getQueryPredicates(builder, root, finalText, NAME)); 35 | }; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/queryspecification/TokenStoreSpecification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.repository.queryspecification; 18 | 19 | import static bio.overture.ego.model.enums.JavaFields.*; 20 | 21 | import bio.overture.ego.model.entity.ApiKey; 22 | import bio.overture.ego.model.entity.User; 23 | import bio.overture.ego.utils.QueryUtils; 24 | import java.util.UUID; 25 | import javax.persistence.criteria.Join; 26 | import lombok.NonNull; 27 | import lombok.val; 28 | import org.springframework.data.jpa.domain.Specification; 29 | 30 | public class TokenStoreSpecification extends SpecificationBase { 31 | 32 | public static Specification containsText(@NonNull String text) { 33 | val finalText = QueryUtils.prepareForQuery(text); 34 | return (root, query, builder) -> { 35 | query.distinct(true); 36 | 37 | return builder.or(getQueryPredicates(builder, root, finalText, NAME)); 38 | }; 39 | } 40 | 41 | public static Specification containsUser(@NonNull UUID userId) { 42 | return (root, query, builder) -> { 43 | query.distinct(true); 44 | 45 | Join apiKeyJoin = root.join(OWNER); 46 | return builder.equal(apiKeyJoin.get(ID), userId); 47 | }; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/queryspecification/builder/GroupSpecificationBuilder.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository.queryspecification.builder; 2 | 3 | import static bio.overture.ego.model.enums.JavaFields.APPLICATION; 4 | import static bio.overture.ego.model.enums.JavaFields.GROUPAPPLICATIONS; 5 | import static bio.overture.ego.model.enums.JavaFields.PERMISSIONS; 6 | import static bio.overture.ego.model.enums.JavaFields.USER; 7 | import static bio.overture.ego.model.enums.JavaFields.USERGROUPS; 8 | import static javax.persistence.criteria.JoinType.LEFT; 9 | 10 | import bio.overture.ego.model.entity.Group; 11 | import java.util.UUID; 12 | import javax.persistence.criteria.Root; 13 | import lombok.Setter; 14 | import lombok.experimental.Accessors; 15 | import lombok.val; 16 | 17 | @Setter 18 | @Accessors(fluent = true, chain = true) 19 | public class GroupSpecificationBuilder extends AbstractSpecificationBuilder { 20 | 21 | private boolean fetchApplications; 22 | private boolean fetchUserGroups; 23 | private boolean fetchGroupPermissions; 24 | 25 | @Override 26 | protected Root setupFetchStrategy(Root root) { 27 | if (fetchApplications) { 28 | val fromGroupApplications = root.fetch(GROUPAPPLICATIONS, LEFT); 29 | fromGroupApplications.fetch(APPLICATION, LEFT); 30 | } 31 | if (fetchUserGroups) { 32 | val fromUserGroup = root.fetch(USERGROUPS, LEFT); 33 | fromUserGroup.fetch(USER, LEFT); 34 | } 35 | if (fetchGroupPermissions) { 36 | root.fetch(PERMISSIONS, LEFT); 37 | } 38 | return root; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/queryspecification/builder/RefreshTokenSpecificationBuilder.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository.queryspecification.builder; 2 | 3 | import static javax.persistence.criteria.JoinType.LEFT; 4 | 5 | import bio.overture.ego.model.entity.RefreshToken; 6 | import java.util.UUID; 7 | import javax.persistence.criteria.Root; 8 | import lombok.Setter; 9 | import lombok.experimental.Accessors; 10 | 11 | @Setter 12 | @Accessors(fluent = true, chain = true) 13 | public class RefreshTokenSpecificationBuilder 14 | extends AbstractSpecificationBuilder { 15 | 16 | private boolean fetchUser; 17 | 18 | @Override 19 | protected Root setupFetchStrategy(Root root) { 20 | if (fetchUser) { 21 | root.fetch(RefreshToken.Fields.user, LEFT); 22 | } 23 | return root; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/repository/queryspecification/builder/TokenSpecificationBuilder.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.repository.queryspecification.builder; 2 | 3 | import static bio.overture.ego.model.enums.JavaFields.OWNER; 4 | import static bio.overture.ego.model.enums.JavaFields.SCOPES; 5 | import static javax.persistence.criteria.JoinType.LEFT; 6 | 7 | import bio.overture.ego.model.entity.ApiKey; 8 | import java.util.UUID; 9 | import javax.persistence.criteria.Root; 10 | import lombok.Setter; 11 | import lombok.experimental.Accessors; 12 | 13 | // TODO: change name to ApiKeySpecificationBuilder... [anncatton] 14 | @Setter 15 | @Accessors(fluent = true, chain = true) 16 | public class TokenSpecificationBuilder extends AbstractSpecificationBuilder { 17 | 18 | private boolean fetchOwner; 19 | private boolean fetchTokenScopes; 20 | 21 | @Override 22 | protected Root setupFetchStrategy(Root root) { 23 | if (fetchOwner) { 24 | root.fetch(OWNER); 25 | } 26 | if (fetchTokenScopes) { 27 | root.fetch(SCOPES, LEFT); 28 | } 29 | return root; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/security/AdminScoped.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.security; 18 | 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import org.springframework.security.access.prepost.PreAuthorize; 22 | 23 | /** Method Security Meta Annotation */ 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @PreAuthorize("@authorizationManager.authorizeWithAdminRole(authentication)") 26 | public @interface AdminScoped {} 27 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/security/ApplicationScoped.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.security; 18 | 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import org.springframework.security.access.prepost.PreAuthorize; 22 | 23 | /** Method Security Meta Annotation */ 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @PreAuthorize("@authorizationManager.authorizeWithApplication(authentication)") 26 | public @interface ApplicationScoped {} 27 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/security/AuthorizationManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.security; 18 | 19 | import lombok.NonNull; 20 | import org.springframework.security.core.Authentication; 21 | 22 | public interface AuthorizationManager { 23 | boolean authorize(Authentication authentication); 24 | 25 | boolean authorizeWithAdminRole(Authentication authentication); 26 | 27 | boolean authorizeWithApplication(@NonNull Authentication authentication); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/security/BasicAuthToken.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.security; 2 | 3 | import static bio.overture.ego.utils.Splitters.COLON_SPLITTER; 4 | import static java.lang.String.format; 5 | 6 | import java.util.Base64; 7 | import java.util.Optional; 8 | import lombok.Data; 9 | import lombok.extern.slf4j.Slf4j; 10 | import lombok.val; 11 | 12 | @Slf4j 13 | @Data 14 | public class BasicAuthToken { 15 | private final String clientId; 16 | private final String clientSecret; 17 | 18 | public static final String TOKEN_PREFIX = "Basic "; 19 | 20 | public static Optional decode(String token) { 21 | log.debug("Decoding basic auth token: '" + token + "'"); 22 | val base64encoding = removeTokenPrefix(token); 23 | String contents; 24 | try { 25 | contents = new String(Base64.getDecoder().decode(base64encoding)); 26 | } catch (Exception exception) { 27 | log.error("Couldn't decode basic auth token: '" + token + "', " + exception.getMessage()); 28 | return Optional.empty(); 29 | } 30 | val parts = COLON_SPLITTER.splitToList(contents); 31 | if (parts.size() != 2) { 32 | log.error("Basic auth token '" + token + "' should have 2 parts, not " + parts.size()); 33 | return Optional.empty(); 34 | } 35 | 36 | val clientId = parts.get(0); 37 | val clientSecret = parts.get(1); 38 | 39 | log.info(format("Extracted client id '%s'", clientId)); 40 | return Optional.of(new BasicAuthToken(clientId, clientSecret)); 41 | } 42 | 43 | private static String removeTokenPrefix(String token) { 44 | return token.replace(TOKEN_PREFIX, "").trim(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/security/DefaultAuthorizationManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.security; 18 | 19 | import lombok.extern.slf4j.Slf4j; 20 | import org.springframework.security.core.Authentication; 21 | 22 | /* 23 | Default Authorization Manager allows working without actual auth headers. 24 | Meant to be used for development environment. 25 | */ 26 | @Slf4j 27 | public class DefaultAuthorizationManager implements AuthorizationManager { 28 | 29 | @Override 30 | public boolean authorize(Authentication authentication) { 31 | return true; 32 | } 33 | 34 | @Override 35 | public boolean authorizeWithAdminRole(Authentication authentication) { 36 | return true; 37 | } 38 | 39 | @Override 40 | public boolean authorizeWithApplication(Authentication authentication) { 41 | return true; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/service/AbstractNameablePermissionService.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.service; 2 | 3 | import bio.overture.ego.model.dto.PolicyResponse; 4 | import bio.overture.ego.model.entity.*; 5 | import bio.overture.ego.repository.NameablePermissionRepository; 6 | import java.util.*; 7 | import lombok.NonNull; 8 | import lombok.extern.slf4j.Slf4j; 9 | import lombok.val; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | @Slf4j 13 | @Transactional 14 | public abstract class AbstractNameablePermissionService< 15 | O extends NameableEntity, P extends AbstractPermission> 16 | extends AbstractPermissionService { 17 | 18 | /** Dependencies */ 19 | private final BaseService policyBaseService; 20 | 21 | private final BaseService ownerBaseService; 22 | private final NameablePermissionRepository nameablePermissionRepository; 23 | private final Class ownerType; 24 | 25 | public AbstractNameablePermissionService( 26 | @NonNull Class ownerType, 27 | @NonNull Class

entityType, 28 | @NonNull BaseService ownerBaseService, 29 | @NonNull BaseService policyBaseService, 30 | @NonNull NameablePermissionRepository repository) { 31 | super(ownerType, entityType, ownerBaseService, policyBaseService, repository); 32 | this.nameablePermissionRepository = repository; 33 | this.ownerType = ownerType; 34 | this.policyBaseService = policyBaseService; 35 | this.ownerBaseService = ownerBaseService; 36 | } 37 | 38 | protected PolicyResponse convertToPolicyResponse(@NonNull P p) { 39 | val name = p.getOwner().getName(); 40 | val id = p.getOwner().getId().toString(); 41 | val mask = p.getAccessLevel(); 42 | return PolicyResponse.builder().name(name).id(id).mask(mask).build(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/service/AbstractNamedService.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.service; 2 | 3 | import static bio.overture.ego.model.exceptions.NotFoundException.checkNotFound; 4 | 5 | import bio.overture.ego.model.entity.Identifiable; 6 | import bio.overture.ego.repository.NamedRepository; 7 | import java.util.Optional; 8 | import lombok.NonNull; 9 | import lombok.val; 10 | 11 | public abstract class AbstractNamedService, ID> 12 | extends AbstractBaseService implements NamedService { 13 | 14 | private final NamedRepository namedRepository; 15 | 16 | public AbstractNamedService( 17 | @NonNull Class entityType, @NonNull NamedRepository repository) { 18 | super(entityType, repository); 19 | this.namedRepository = repository; 20 | } 21 | 22 | @Override 23 | public Optional findByName(@NonNull String name) { 24 | return namedRepository.findByName(name); 25 | } 26 | 27 | @Override 28 | public T getByName(@NonNull String name) { 29 | val result = findByName(name); 30 | checkNotFound( 31 | result.isPresent(), 32 | "The '%s' entity with name '%s' was not found", 33 | getEntityTypeName(), 34 | name); 35 | return result.get(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/service/BaseService.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.service; 2 | 3 | import static java.lang.String.format; 4 | 5 | import bio.overture.ego.model.exceptions.NotFoundException; 6 | import bio.overture.ego.repository.queryspecification.builder.AbstractSpecificationBuilder; 7 | import java.util.Collection; 8 | import java.util.List; 9 | import java.util.Optional; 10 | import java.util.Set; 11 | import lombok.NonNull; 12 | import lombok.val; 13 | import org.springframework.data.domain.Page; 14 | import org.springframework.data.domain.Pageable; 15 | import org.springframework.data.jpa.domain.Specification; 16 | 17 | public interface BaseService { 18 | 19 | String getEntityTypeName(); 20 | 21 | default T getById(@NonNull ID id) { 22 | val entity = findById(id); 23 | return entity.orElseThrow( 24 | () -> 25 | new NotFoundException( 26 | format( 27 | "The '%s' entity with id '%s' does not exist", 28 | getEntityTypeName(), id.toString()))); 29 | } 30 | 31 | Optional findById(ID id); 32 | 33 | boolean isExist(ID id); 34 | 35 | void delete(ID id); 36 | 37 | long countAll(); 38 | 39 | Page findAll(Specification specification, Pageable pageable); 40 | 41 | Page findAll(AbstractSpecificationBuilder specificationBuilder, Pageable pageable); 42 | 43 | List getMany(Collection ids, AbstractSpecificationBuilder specificationBuilder); 44 | 45 | Set getMany(Collection ids); 46 | 47 | T getWithRelationships(ID id); 48 | 49 | void checkExistence(Collection ids); 50 | 51 | void checkExistence(ID id); 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/service/DefaultProviderService.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.service; 2 | 3 | import static bio.overture.ego.model.exceptions.NotFoundException.buildNotFoundException; 4 | import static bio.overture.ego.utils.CollectionUtils.convertToUnmodifiableList; 5 | 6 | import bio.overture.ego.model.entity.DefaultProvider; 7 | import bio.overture.ego.model.enums.ProviderType; 8 | import bio.overture.ego.repository.DefaultProviderRepository; 9 | import java.util.List; 10 | import lombok.NonNull; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | 15 | @Slf4j 16 | @Service 17 | public class DefaultProviderService extends AbstractBaseService { 18 | 19 | private final DefaultProviderRepository defaultProviderRepository; 20 | 21 | @Autowired 22 | public DefaultProviderService(@NonNull DefaultProviderRepository defaultProviderRepository) { 23 | super(DefaultProvider.class, defaultProviderRepository); 24 | this.defaultProviderRepository = defaultProviderRepository; 25 | } 26 | 27 | @Override 28 | public DefaultProvider getWithRelationships(@NonNull ProviderType id) { 29 | return defaultProviderRepository 30 | .findById(id) 31 | .orElseThrow(() -> buildNotFoundException("Could not find default provider type '%s'", id)); 32 | } 33 | 34 | public List findAll() { 35 | return convertToUnmodifiableList(getRepository().findAll()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/service/GithubService.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.service; 2 | 3 | import static bio.overture.ego.utils.Joiners.BLANK; 4 | 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Map; 9 | import lombok.NonNull; 10 | import lombok.val; 11 | import org.springframework.core.ParameterizedTypeReference; 12 | import org.springframework.http.HttpMethod; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.web.client.RestTemplate; 15 | 16 | @Service 17 | public class GithubService { 18 | 19 | public String getVerifiedEmail(RestTemplate restTemplate) { 20 | String email; 21 | email = 22 | (String) 23 | restTemplate 24 | .exchange( 25 | "https://api.github.com/user/emails", 26 | HttpMethod.GET, 27 | null, 28 | new ParameterizedTypeReference>>() {}) 29 | .getBody().stream() 30 | .filter(x -> x.get("verified").equals(true) && x.get("primary").equals(true)) 31 | .findAny() 32 | .orElse(Collections.emptyMap()) 33 | .get("email"); 34 | return email; 35 | } 36 | 37 | public Map parseName(@NonNull String name, Map map) { 38 | List names = Arrays.asList(name.split(" ")); 39 | val numNames = names.size(); 40 | 41 | if (numNames > 0) { 42 | if (numNames == 1) { 43 | map.put("given_name", names.get(0)); 44 | } else { 45 | List firstNames = names.subList(0, numNames - 1); 46 | List lastName = names.subList(numNames - 1, numNames); 47 | map.put("given_name", BLANK.join(firstNames)); 48 | map.put("family_name", lastName.get(0)); 49 | } 50 | } 51 | return map; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/service/NamedService.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.service; 2 | 3 | import java.util.Optional; 4 | 5 | public interface NamedService extends BaseService { 6 | 7 | Optional findByName(String name); 8 | 9 | T getByName(String name); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/service/UserGroupService.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.service; 2 | 3 | import bio.overture.ego.model.join.UserGroup; 4 | import lombok.NonNull; 5 | 6 | public class UserGroupService { 7 | 8 | public static void associateSelf(@NonNull UserGroup ug) { 9 | ug.getGroup().getUserGroups().add(ug); 10 | ug.getUser().getUserGroups().add(ug); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/token/IDToken.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.token; 18 | 19 | import bio.overture.ego.model.enums.ProviderType; 20 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import lombok.*; 23 | 24 | @Data 25 | @Builder 26 | @NoArgsConstructor 27 | @AllArgsConstructor 28 | @JsonIgnoreProperties(ignoreUnknown = true) 29 | public class IDToken { 30 | 31 | private String email; 32 | 33 | @JsonProperty("given_name") 34 | private String givenName; 35 | 36 | @JsonProperty("family_name") 37 | private String familyName; 38 | 39 | @JsonProperty("provider_type") 40 | @NonNull 41 | ProviderType providerType; 42 | 43 | @JsonProperty("provider_subject_id") 44 | @NonNull 45 | String providerSubjectId; 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/token/TokenClaims.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.token; 18 | 19 | import bio.overture.ego.view.Views; 20 | import com.fasterxml.jackson.annotation.JsonIgnore; 21 | import com.fasterxml.jackson.annotation.JsonView; 22 | import java.util.UUID; 23 | import lombok.*; 24 | 25 | @Data 26 | @NoArgsConstructor 27 | @JsonView(Views.JWTAccessToken.class) 28 | public abstract class TokenClaims { 29 | @NonNull protected Integer iat; 30 | 31 | @NonNull protected Integer exp; 32 | 33 | @NonNull @JsonIgnore protected Integer validDuration; 34 | 35 | @Getter protected String sub; 36 | 37 | @NonNull protected String iss; 38 | 39 | /* 40 | Defaults 41 | */ 42 | private String jti = UUID.randomUUID().toString(); 43 | 44 | @Getter(AccessLevel.NONE) 45 | @Setter(AccessLevel.NONE) 46 | @JsonIgnore 47 | private long initTime = System.currentTimeMillis(); 48 | 49 | public int getExp() { 50 | return ((int) ((this.initTime + validDuration) / 1000L)); 51 | } 52 | 53 | public int getIat() { 54 | return (int) (this.initTime / 1000L); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/token/app/AppTokenClaims.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.token.app; 18 | 19 | import bio.overture.ego.token.TokenClaims; 20 | import bio.overture.ego.view.Views; 21 | import com.fasterxml.jackson.annotation.JsonView; 22 | import lombok.Data; 23 | import lombok.NoArgsConstructor; 24 | import lombok.NonNull; 25 | import org.springframework.security.oauth2.core.AuthorizationGrantType; 26 | import org.springframework.util.StringUtils; 27 | 28 | @Data 29 | @NoArgsConstructor 30 | @JsonView(Views.JWTAccessToken.class) 31 | public class AppTokenClaims extends TokenClaims { 32 | 33 | /* 34 | Constants 35 | */ 36 | public static final AuthorizationGrantType[] AUTHORIZED_GRANT_TYPES = { 37 | AuthorizationGrantType.AUTHORIZATION_CODE, 38 | AuthorizationGrantType.CLIENT_CREDENTIALS, 39 | AuthorizationGrantType.REFRESH_TOKEN 40 | }; 41 | public static final String ROLE = "ROLE_CLIENT"; 42 | 43 | @NonNull private AppTokenContext context; 44 | 45 | public String getSub() { 46 | if (StringUtils.isEmpty(sub)) { 47 | return String.valueOf(this.context.getAppInfo().getId()); 48 | } else { 49 | return sub; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/token/app/AppTokenContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.token.app; 18 | 19 | import bio.overture.ego.model.entity.Application; 20 | import bio.overture.ego.view.Views; 21 | import com.fasterxml.jackson.annotation.JsonInclude; 22 | import com.fasterxml.jackson.annotation.JsonProperty; 23 | import com.fasterxml.jackson.annotation.JsonView; 24 | import java.util.Set; 25 | import lombok.*; 26 | 27 | @Data 28 | @NoArgsConstructor 29 | @RequiredArgsConstructor 30 | @JsonInclude(JsonInclude.Include.ALWAYS) 31 | @JsonView(Views.JWTAccessToken.class) 32 | public class AppTokenContext { 33 | 34 | @NonNull 35 | @JsonProperty("application") 36 | private Application appInfo; 37 | 38 | private Set scope; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/token/signer/TokenSigner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.token.signer; 18 | 19 | import java.security.Key; 20 | import java.security.KeyPair; 21 | import java.util.Optional; 22 | 23 | public interface TokenSigner { 24 | 25 | Optional getKey(); 26 | 27 | Optional getKeyPair(); 28 | 29 | Optional getEncodedPublicKey(); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/token/user/UserTokenClaims.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.token.user; 18 | 19 | import bio.overture.ego.model.entity.Application; 20 | import bio.overture.ego.model.join.UserApplication; 21 | import bio.overture.ego.token.TokenClaims; 22 | import bio.overture.ego.view.Views; 23 | import com.fasterxml.jackson.annotation.JsonView; 24 | import java.util.List; 25 | import java.util.stream.Collectors; 26 | import lombok.Data; 27 | import lombok.Getter; 28 | import lombok.NoArgsConstructor; 29 | import lombok.NonNull; 30 | import org.springframework.util.StringUtils; 31 | 32 | @Data 33 | @NoArgsConstructor 34 | @JsonView(Views.JWTAccessToken.class) 35 | public class UserTokenClaims extends TokenClaims { 36 | 37 | @NonNull private UserTokenContext context; 38 | 39 | @Getter protected List aud; 40 | 41 | public String getSub() { 42 | if (StringUtils.isEmpty(sub)) { 43 | return String.valueOf(this.context.getUserInfo().getId()); 44 | } else { 45 | return sub; 46 | } 47 | } 48 | 49 | public List getAud() { 50 | return this.context.getUserInfo().getUserApplications().stream() 51 | .map(UserApplication::getApplication) 52 | .map(Application::getName) 53 | .collect(Collectors.toList()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/token/user/UserTokenContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.token.user; 18 | 19 | import bio.overture.ego.model.entity.User; 20 | import bio.overture.ego.view.Views; 21 | import com.fasterxml.jackson.annotation.JsonInclude; 22 | import com.fasterxml.jackson.annotation.JsonProperty; 23 | import com.fasterxml.jackson.annotation.JsonView; 24 | import java.util.Set; 25 | import lombok.Data; 26 | import lombok.NoArgsConstructor; 27 | import lombok.NonNull; 28 | import lombok.RequiredArgsConstructor; 29 | 30 | @Data 31 | @NoArgsConstructor 32 | @RequiredArgsConstructor 33 | @JsonInclude(JsonInclude.Include.ALWAYS) 34 | @JsonView(Views.JWTAccessToken.class) 35 | public class UserTokenContext { 36 | @NonNull 37 | @JsonProperty("user") 38 | private User userInfo; 39 | 40 | private Set scope; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/Collectors.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import static lombok.AccessLevel.PRIVATE; 4 | 5 | import com.google.common.collect.ImmutableList; 6 | import com.google.common.collect.ImmutableMap; 7 | import com.google.common.collect.ImmutableSet; 8 | import java.util.function.BiConsumer; 9 | import java.util.function.Function; 10 | import java.util.stream.Collector; 11 | import lombok.NoArgsConstructor; 12 | import lombok.NonNull; 13 | 14 | @NoArgsConstructor(access = PRIVATE) 15 | public class Collectors { 16 | 17 | public static Collector, ImmutableList> toImmutableList() { 18 | return Collector.of( 19 | ImmutableList.Builder::new, 20 | ImmutableList.Builder::add, 21 | (b1, b2) -> b1.addAll(b2.build()), 22 | ImmutableList.Builder::build); 23 | } 24 | 25 | public static Collector, ImmutableSet> toImmutableSet() { 26 | return Collector.of( 27 | ImmutableSet.Builder::new, 28 | ImmutableSet.Builder::add, 29 | (b1, b2) -> b1.addAll(b2.build()), 30 | ImmutableSet.Builder::build); 31 | } 32 | 33 | public static 34 | Collector, ImmutableMap> toImmutableMap( 35 | @NonNull Function keyMapper, 36 | @NonNull Function valueMapper) { 37 | 38 | final BiConsumer, T> accumulator = 39 | (builder, entry) -> builder.put(keyMapper.apply(entry), valueMapper.apply(entry)); 40 | 41 | return Collector.of( 42 | ImmutableMap.Builder::new, 43 | accumulator, 44 | (b1, b2) -> b1.putAll(b2.build()), 45 | ImmutableMap.Builder::build); 46 | } 47 | 48 | public static Collector, ImmutableMap> toImmutableMap( 49 | @NonNull Function keyMapper) { 50 | return toImmutableMap(keyMapper, Function.identity()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/Defaults.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import lombok.SneakyThrows; 4 | 5 | public class Defaults { 6 | T val; 7 | 8 | @SneakyThrows 9 | Defaults(T value) { 10 | val = value; 11 | } 12 | 13 | static Defaults create(X value) { 14 | return new Defaults<>(value); 15 | } 16 | 17 | T def(T value) { 18 | return value == null ? val : value; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/HibernateSessions.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.Set; 6 | import lombok.NonNull; 7 | import lombok.extern.slf4j.Slf4j; 8 | import lombok.val; 9 | import org.hibernate.collection.internal.AbstractPersistentCollection; 10 | 11 | @Slf4j 12 | public class HibernateSessions { 13 | 14 | public static void unsetSession(@NonNull Set property) { 15 | unsetSession((Collection) property); 16 | } 17 | 18 | public static void unsetSession(@NonNull List property) { 19 | unsetSession((Collection) property); 20 | } 21 | 22 | public static void unsetSession(@NonNull Collection property) { 23 | if (property instanceof AbstractPersistentCollection) { 24 | val persistentProperty = (AbstractPersistentCollection) property; 25 | persistentProperty.unsetSession(persistentProperty.getSession()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/Ids.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import static bio.overture.ego.model.exceptions.MalformedRequestException.checkMalformedRequest; 4 | import static bio.overture.ego.utils.CollectionUtils.findDuplicates; 5 | import static bio.overture.ego.utils.Joiners.PRETTY_COMMA; 6 | import static lombok.AccessLevel.PRIVATE; 7 | 8 | import bio.overture.ego.model.entity.Identifiable; 9 | import java.util.Collection; 10 | import java.util.UUID; 11 | import lombok.NoArgsConstructor; 12 | import lombok.val; 13 | 14 | @NoArgsConstructor(access = PRIVATE) 15 | public class Ids { 16 | 17 | public static > void checkDuplicates( 18 | Class entityType, Collection ids) { 19 | // check duplicate ids 20 | val duplicateIds = findDuplicates(ids); 21 | checkMalformedRequest( 22 | duplicateIds.isEmpty(), 23 | "The following %s ids contain duplicates: [%s]", 24 | entityType.getSimpleName(), 25 | PRETTY_COMMA.join(duplicateIds)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/Joiners.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import static lombok.AccessLevel.PRIVATE; 4 | 5 | import com.google.common.base.Joiner; 6 | import lombok.NoArgsConstructor; 7 | 8 | @NoArgsConstructor(access = PRIVATE) 9 | public class Joiners { 10 | 11 | public static final Joiner COMMA = Joiner.on(","); 12 | public static final Joiner NEWLINE_COMMA = Joiner.on(",\n"); 13 | public static final Joiner PRETTY_COMMA = Joiner.on(" , "); 14 | public static final Joiner PATH = Joiner.on("/"); 15 | public static final Joiner AMPERSAND = Joiner.on("&"); 16 | public static final Joiner BLANK = Joiner.on(" "); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/PolicyPermissionUtils.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import static bio.overture.ego.utils.CollectionUtils.mapToList; 4 | 5 | import bio.overture.ego.model.entity.AbstractPermission; 6 | import java.util.Collection; 7 | import java.util.List; 8 | import lombok.NonNull; 9 | 10 | public class PolicyPermissionUtils { 11 | 12 | public static String extractPermissionString(@NonNull AbstractPermission permission) { 13 | return String.format( 14 | "%s.%s", permission.getPolicy().getName(), permission.getAccessLevel().toString()); 15 | } 16 | 17 | public static List extractPermissionStrings( 18 | @NonNull Collection permissions) { 19 | return mapToList(permissions, PolicyPermissionUtils::extractPermissionString); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/QueryUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.utils; 18 | 19 | import lombok.extern.slf4j.Slf4j; 20 | import org.springframework.util.StringUtils; 21 | 22 | @Slf4j 23 | public class QueryUtils { 24 | 25 | public static String prepareForQuery(String text) { 26 | String output = text; 27 | if (StringUtils.isEmpty(output)) { 28 | return "%"; 29 | } 30 | if (!output.contains("%")) { 31 | output = "%" + output + "%"; 32 | } 33 | return output.toLowerCase(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/Splitters.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import static lombok.AccessLevel.PRIVATE; 4 | 5 | import com.google.common.base.Splitter; 6 | import lombok.NoArgsConstructor; 7 | 8 | @NoArgsConstructor(access = PRIVATE) 9 | public class Splitters { 10 | 11 | public static final Splitter COMMA_SPLITTER = Splitter.on(','); 12 | public static final Splitter COLON_SPLITTER = Splitter.on(':'); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/Streams.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import java.util.Iterator; 5 | import java.util.stream.Stream; 6 | import java.util.stream.StreamSupport; 7 | import lombok.NonNull; 8 | 9 | public class Streams { 10 | 11 | public static Stream stream(@NonNull Iterator iterator) { 12 | return stream(() -> iterator, false); 13 | } 14 | 15 | public static Stream stream(@NonNull Iterable iterable) { 16 | return stream(iterable, false); 17 | } 18 | 19 | @SafeVarargs 20 | public static Stream stream(@NonNull T... values) { 21 | return ImmutableList.copyOf(values).stream(); 22 | } 23 | 24 | /* 25 | * Helpers 26 | */ 27 | private static Stream stream(Iterable iterable, boolean inParallel) { 28 | return StreamSupport.stream(iterable.spliterator(), inParallel); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/Strings.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import static java.util.Objects.nonNull; 4 | 5 | import lombok.NoArgsConstructor; 6 | 7 | @NoArgsConstructor 8 | public final class Strings { 9 | public static boolean isDefined(String s) { 10 | return nonNull(s) && !s.isBlank(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/SwaggerConstants.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | public class SwaggerConstants { 4 | public static final String AUTH_CONTROLLER = "auth-controller"; 5 | public static final String POST_ACCESS_TOKEN = "postAccessToken"; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/Tokens.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.utils; 19 | 20 | public class Tokens { 21 | 22 | public static String removeTokenPrefix(String token, String prefix) { 23 | return token.replace(prefix, "").trim(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/utils/TypeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.utils; 18 | 19 | import com.fasterxml.jackson.core.JsonGenerator; 20 | import com.fasterxml.jackson.databind.DeserializationFeature; 21 | import com.fasterxml.jackson.databind.MapperFeature; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import java.io.IOException; 24 | import lombok.val; 25 | 26 | public class TypeUtils { 27 | public static T convertToAnotherType( 28 | Object fromObject, Class tClass, Class serializationView) throws IOException { 29 | val mapper = new ObjectMapper(); 30 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 31 | mapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true); 32 | mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); 33 | val serializedValue = mapper.writerWithView(serializationView).writeValueAsBytes(fromObject); 34 | return mapper.readValue(serializedValue, tClass); 35 | } 36 | 37 | public static T convertToAnotherType(Object fromObject, Class tClass) { 38 | val mapper = new ObjectMapper(); 39 | mapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true); 40 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 41 | return mapper.convertValue(fromObject, tClass); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/bio/overture/ego/view/Views.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package bio.overture.ego.view; 18 | 19 | public interface Views { 20 | interface JWTAccessToken {}; 21 | 22 | interface REST {}; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/lib/libwrapper-linux-x86-64.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/src/main/lib/libwrapper-linux-x86-64.so -------------------------------------------------------------------------------- /src/main/lib/libwrapper-macosx-universal-64.jnilib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/src/main/lib/libwrapper-macosx-universal-64.jnilib -------------------------------------------------------------------------------- /src/main/lib/wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/src/main/lib/wrapper.jar -------------------------------------------------------------------------------- /src/main/proto/Ego.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | import "google/protobuf/wrappers.proto"; 3 | 4 | option java_multiple_files = true; 5 | option java_package = "bio.overture.ego.grpc"; 6 | option java_outer_classname = "EgoProto"; 7 | 8 | package bio.overture.ego.grpc; 9 | 10 | service UserService { 11 | rpc GetUser (GetUserRequest) returns (User) {} 12 | rpc ListUsers (ListUsersRequest) returns (ListUsersResponse) {} 13 | } 14 | 15 | message PagedRequest { 16 | uint32 page_number = 1; 17 | uint32 page_size = 2; 18 | string order_by = 3; 19 | } 20 | 21 | message PagedResponse { 22 | uint32 max_results = 1; 23 | google.protobuf.UInt32Value next_page = 2; 24 | } 25 | 26 | message GetUserRequest { 27 | string id = 1; 28 | } 29 | 30 | message ListUsersRequest { 31 | PagedRequest page = 1; 32 | 33 | google.protobuf.StringValue query = 2; 34 | repeated string group_ids = 3; 35 | } 36 | 37 | message ListUsersResponse { 38 | PagedResponse page = 1; 39 | 40 | repeated User users = 2; 41 | } 42 | 43 | message User { 44 | google.protobuf.StringValue id = 1; 45 | google.protobuf.StringValue email = 2; 46 | google.protobuf.StringValue first_name = 3; 47 | google.protobuf.StringValue last_name = 4; 48 | 49 | google.protobuf.StringValue created_at = 5; 50 | google.protobuf.StringValue last_login = 6; 51 | google.protobuf.StringValue preferred_language = 8; 52 | google.protobuf.StringValue status = 9; 53 | google.protobuf.StringValue type = 10; 54 | 55 | repeated string applications = 11; 56 | repeated string groups = 12; 57 | repeated string scopes = 13; 58 | 59 | google.protobuf.StringValue provider_type = 14; 60 | google.protobuf.StringValue provider_subject_id = 15; 61 | 62 | // removed name = 7 field as part of EGO-530 63 | reserved 7; 64 | } 65 | -------------------------------------------------------------------------------- /src/main/resources/bootstrap-iam.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.vault.enabled=true 2 | spring.application.name=development/oicr/ego 3 | spring.cloud.vault.generic.default-context=${spring.application.name} 4 | spring.cloud.vault.uri="" 5 | spring.cloud.vault.authentication=AWS_IAM 6 | spring.cloud.vault.aws-iam.role="" 7 | -------------------------------------------------------------------------------- /src/main/resources/bootstrap-token.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.vault.enabled=true 2 | spring.application.name=ego-dev 3 | spring.cloud.vault.generic.default-context=${spring.application.name} 4 | spring.cloud.vault.kv.backend-version=1 5 | spring.cloud.vault.generic.backend=ego 6 | spring.cloud.vault.scheme=http 7 | spring.cloud.vault.host=localhost 8 | spring.cloud.vault.port=8200 9 | spring.cloud.vault.token=00000000-0000-0000-0000-000000000000 10 | -------------------------------------------------------------------------------- /src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.cloud.vault.enabled=false 2 | -------------------------------------------------------------------------------- /src/main/resources/dummy-data/02-insert-dummy-groups.sql: -------------------------------------------------------------------------------- 1 | /* WARNING: Clears all data in the EgoGroup Table 2 | 3 | Clears the EgoGroup table and insert 5 sample groups (4 APPROVED, 1 PENDING) 4 | */ 5 | TRUNCATE public.egogroup CASCADE; 6 | 7 | INSERT INTO egogroup (name, status, description) VALUES ('XYZ Cancer Research Institute', 'APPROVED', 'Sample group for elite cancer researchers'); 8 | INSERT INTO egogroup (name, status, description) VALUES ('Extreme Research Consortium', 'APPROVED', 'Sample group for generalist researchers'); 9 | INSERT INTO egogroup (name, status, description) VALUES ('Healthcare Providers Anonymous', 'APPROVED', 'Sample group for patient care specialist'); 10 | INSERT INTO egogroup (name, status, description) VALUES ('Pediatric Patient Support Network', 'APPROVED', 'Sample group for patients and their supporters'); 11 | INSERT INTO egogroup (name, status, description) VALUES ('Generic Genomics Geniuses', 'PENDING', 'Sample group for super-duper smart genetic investigators'); -------------------------------------------------------------------------------- /src/main/resources/dummy-data/03-insert-dummy-applications.sql: -------------------------------------------------------------------------------- 1 | /* WARNING: Clears all data in the EgoApplication Table 2 | 3 | Clears the EgoApplication table and insert 4 sample Applications (3 Approved, 1 Pending) 4 | */ 5 | TRUNCATE public.egoapplication CASCADE; 6 | 7 | INSERT INTO EGOAPPLICATION (name, clientId, clientSecret, redirectUri, description, status) VALUES ('Example Data Portal', 'sample-data-portal', 'sample-data-portal-secret', 'http://google.com', 'Sample application for some data portal', 'Approved'); 8 | INSERT INTO EGOAPPLICATION (name, clientId, clientSecret, redirectUri, description, status) VALUES ('Personal Information Manager', 'personal-info-manager', 'personal-info-manager-secret', 'http://yahoo.com', 'Sample application for some user manager', 'Approved'); 9 | INSERT INTO EGOAPPLICATION (name, clientId, clientSecret, redirectUri, description, status) VALUES ('Daily News Feed', 'daily-news-feed', 'daily-news-feed-secret', 'http://bing.com', 'Sample application for some news feed', 'Approved'); 10 | INSERT INTO EGOAPPLICATION (name, clientId, clientSecret, redirectUri, description, status) VALUES ('User Notification System', 'user-notification-system', 'user-notification-system-secret', 'http://aol.com', 'Sample application for a user notification management system', 'Pending'); -------------------------------------------------------------------------------- /src/main/resources/dummy-data/05-insert-dummy-rel-user-application.sql: -------------------------------------------------------------------------------- 1 | TRUNCATE public.userapplication CASCADE; 2 | 3 | -- 6 Users to Personal Information Manager 4 | INSERT INTO public.userapplication (userId, appId) 5 | SELECT u.id, a.id 6 | FROM public.egouser AS u 7 | LEFT JOIN public.egoapplication AS a 8 | ON a.name='Personal Information Manager' 9 | WHERE u.name IN ('Brennan.Denesik@example.com','Anika.Stehr@example.com','Janessa.Cronin@example.com','Sharon.Farrell@example.com','Zane.Rath@example.com','Elisha.Weimann@example.com'); 10 | 11 | -- 35 Users to Example Data Portal 12 | INSERT INTO public.userapplication (userId, appId) 13 | SELECT u.id, a.id 14 | FROM public.egouser AS u 15 | LEFT JOIN public.egoapplication AS a 16 | ON a.name='Example Data Portal' 17 | WHERE u.name IN ('Justice.Heller@example.com','Sharon.Farrell@example.com','Janessa.Cronin@example.com','Shayne.Lubowitz@example.com','Gretchen.Wintheiser@example.com','Daija.Pacocha@example.com','Osvaldo.Bahringer@example.com','Halie.Heller@example.com','Chauncey.Schiller@example.com','Oral.Gleason@example.com','Lupe.Hilll@example.com','Jocelyn.Grant@example.com','Hollie.Kunde@example.com','Ed.Olson@example.com','Jeromy.Larkin@example.com','Marquis.Oberbrunner@example.com','Lyda.Macejkovic@example.com','Gordon.Ullrich@example.com','Kenton.Kilback@example.com','Maya.DuBuque@example.com','Jeromy.Abernathy@example.com','Furman.Volkman@example.com','Yesenia.Schmeler@example.com','Waylon.Wiza@example.com','Helen.Trantow@example.com','Claudine.McKenzie@example.com','Korbin.Sawayn@example.com','Brionna.Mertz@example.com','Orin.Mraz@example.com','Rusty.Hickle@example.com','Rafaela.Harvey@example.com','Herminio.Kub@example.com','Lera.White@example.com','Chandler.Collier@example.com','Edd.Thompson@example.com'); -------------------------------------------------------------------------------- /src/main/resources/dummy-data/06-insert-dummy-rel-group-application.sql: -------------------------------------------------------------------------------- 1 | TRUNCATE public.groupapplication CASCADE; 2 | 3 | -- Add all Approved groups to Perssonal Information Manager 4 | INSERT INTO public.groupapplication (grpId, appId) 5 | SELECT g.id, a.id 6 | FROM public.egogroup AS g 7 | LEFT JOIN public.egoapplication AS a 8 | ON a.name='Personal Information Manager' 9 | WHERE g.name IN ('Pediatric Patient Support Network', 'Extreme Research Consortium', 'XYZ Cancer Research Institute', 'Healthcare Providers Anonymous'); 10 | 11 | -- Add Research Groups to the Data Portal 12 | INSERT INTO public.groupapplication (grpId, appId) 13 | SELECT g.id, a.id 14 | FROM public.egogroup AS g 15 | LEFT JOIN public.egoapplication AS a 16 | ON a.name='Example Data Portal' 17 | WHERE g.name IN ('XYZ Cancer Research Institute', 'Extreme Research Consortium'); -------------------------------------------------------------------------------- /src/main/resources/dummy-data/reset-dummy-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset 3 | set -o errexit 4 | 5 | # usage: ./reset-dummy-data.sh --path='/srv/ego/dummy-data' --user='dbuser' --log='/path/to/logfile.log' 6 | # Note: This script assumes that there is a PGPASSFILE with the required password for that user. 7 | 8 | while [ $# -gt 0 ]; do 9 | case "$1" in 10 | --path=*) 11 | path="${1#*=}" 12 | ;; 13 | --user=*) 14 | user="${1#*=}" 15 | ;; 16 | --log=*) 17 | log="${1#*=}" 18 | ;; 19 | *) 20 | printf "***************************\n" 21 | printf "* Error: Invalid argument.*\n" 22 | printf "***************************\n" 23 | exit 1 24 | esac 25 | shift 26 | done 27 | 28 | psql -w -U $user ego -a -f $path/01-insert-dummy-users.sql -L $log 29 | psql -w -U $user ego -a -f $path/02-insert-dummy-groups.sql -L $log 30 | psql -w -U $user ego -a -f $path/03-insert-dummy-applications.sql -L $log 31 | psql -w -U $user ego -a -f $path/04-insert-dummy-rel-user-group.sql -L $log 32 | psql -w -U $user ego -a -f $path/05-insert-dummy-rel-user-application.sql -L $log 33 | psql -w -U $user ego -a -f $path/06-insert-dummy-rel-group-application.sql -L $log -------------------------------------------------------------------------------- /src/main/resources/ego-jwt.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overture-stack/ego/5034b11fefd55ad6c868fe737ed73e708feb625c/src/main/resources/ego-jwt.jks -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_10__remove_apps_from_apitokens.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE tokenapplication; -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_11__add_expiry_date_api_tokens.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE token ADD expirydate TIMESTAMP NOT NULL DEFAULT NOW(); -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_12__egoapplication_unique_constraints.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE egoapplication ADD CONSTRAINT egoapplication_name_key UNIQUE (name); 2 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_13__fname_lname_not_null_constraints.sql: -------------------------------------------------------------------------------- 1 | UPDATE egouser SET lastname = '' WHERE lastname IS NULL; 2 | ALTER TABLE egouser ALTER COLUMN lastname SET NOT NULL; 3 | ALTER TABLE egouser ALTER COLUMN lastname SET DEFAULT ''; 4 | 5 | UPDATE egouser SET firstname = '' WHERE firstname IS NULL; 6 | ALTER TABLE egouser ALTER COLUMN firstname SET NOT NULL; 7 | ALTER TABLE egouser ALTER COLUMN firstname SET DEFAULT ''; 8 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_14__indices.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX idx_usergroup_user ON usergroup(user_id); 2 | CREATE INDEX idx_usergroup_group ON usergroup(group_id); 3 | CREATE INDEX idx_usergroup_both ON usergroup(user_id, group_id); 4 | 5 | CREATE INDEX idx_userpermission_user ON userpermission(user_id); 6 | CREATE INDEX idx_userpermission_policy ON userpermission(policy_id); 7 | CREATE INDEX idx_userpermission_both ON userpermission(user_id, policy_id); 8 | 9 | CREATE INDEX idx_grouppermission_group ON grouppermission(group_id); 10 | CREATE INDEX idx_grouppermission_policy ON grouppermission(policy_id); 11 | CREATE INDEX idx_grouppermission_both ON grouppermission(group_id, policy_id); 12 | 13 | CREATE INDEX idx_token_owner ON token(owner); 14 | CREATE INDEX idx_tokenscope ON tokenscope(token_id, policy_id, access_level); 15 | CREATE INDEX idx_tokenscope_policy ON tokenscope(policy_id); 16 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_15__add_refresh_token_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE REFRESHTOKEN ( 2 | id UUID PRIMARY KEY, 3 | user_id UUID UNIQUE NOT NULL, 4 | jti UUID UNIQUE NOT NULL, 5 | issuedate TIMESTAMP NOT NULL, 6 | expirydate TIMESTAMP NOT NULL, 7 | FOREIGN KEY (user_id) REFERENCES EGOUSER(id) 8 | ); 9 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_16__add_primary_key_constraint_to_associations.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE USERGROUP ADD PRIMARY KEY (group_id,user_id); 2 | ALTER TABLE USERAPPLICATION ADD PRIMARY KEY (user_id, application_id); 3 | ALTER TABLE GROUPAPPLICATION ADD PRIMARY KEY (group_id, application_id); 4 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_17__add_application_permissions.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE APPLICATIONPERMISSION ( 2 | id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), 3 | policy_id UUID, 4 | application_id UUID, 5 | access_level ACLMASK NOT NULL, 6 | FOREIGN KEY (policy_id) REFERENCES POLICY(id), 7 | FOREIGN KEY (application_id) REFERENCES EGOAPPLICATION(id) 8 | ); 9 | 10 | ALTER TABLE APPLICATIONPERMISSION RENAME CONSTRAINT APPLICATIONPERMISSION_POLICY_ID_FKEY TO APPLICATIONPERMISSION_POLICY_FKEY; 11 | ALTER TABLE APPLICATIONPERMISSION RENAME CONSTRAINT APPLICATIONPERMISSION_APPLICATION_ID_FKEY TO APPLICATIONPERMISSION_APPLICATION_FKEY; 12 | 13 | CREATE INDEX idx_applicationpermission_application ON APPLICATIONPERMISSION(application_id); 14 | CREATE INDEX idx_applicationpermission_policy ON APPLICATIONPERMISSION(policy_id); 15 | CREATE INDEX idx_applicationpermission_both ON APPLICATIONPERMISSION(application_id, policy_id); 16 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_18__ego_init.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE inittripwire ( 2 | initialized INT PRIMARY KEY DEFAULT 0 3 | ); 4 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_19__add_identity_provider_to_user.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE egouser ALTER COLUMN email DROP NOT NULL; 2 | ALTER TABLE egouser DROP CONSTRAINT egouser_email_key; 3 | 4 | ALTER TABLE egouser DROP COLUMN name; 5 | 6 | CREATE TYPE providerType AS ENUM('GOOGLE', 'FACEBOOK', 'LINKEDIN', 'GITHUB', 'ORCID'); 7 | ALTER TABLE egouser ADD COLUMN providertype providerType; 8 | ALTER TABLE egouser ALTER COLUMN providertype SET DEFAULT '${default-provider}'; 9 | -- default values are not added to existing rows, need to explicitly update where providertype is NULL 10 | UPDATE egouser SET providertype = DEFAULT WHERE providertype IS NULL; 11 | -- then set not null constraint 12 | ALTER TABLE egouser ALTER COLUMN providertype SET NOT NULL; 13 | 14 | ALTER TABLE egouser ADD COLUMN providersubjectid VARCHAR(255); 15 | UPDATE egouser SET providersubjectid = email WHERE providersubjectid IS NULL; 16 | ALTER TABLE egouser ALTER COLUMN providersubjectid SET NOT NULL; 17 | 18 | ALTER TABLE egouser ADD UNIQUE(providertype, providersubjectid); 19 | 20 | -- create tripwire table for verifying configured default provider 21 | CREATE TABLE defaultprovidertripwire ( 22 | id providerType PRIMARY KEY 23 | ); 24 | 25 | INSERT INTO defaultprovidertripwire (id) VALUES ('${default-provider}'); 26 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_20__keycloak_provider_type.sql: -------------------------------------------------------------------------------- 1 | ALTER TYPE providerType ADD VALUE 'KEYCLOAK'; 2 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_21__add_application_error_redirect.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE egoapplication ADD COLUMN errorredirecturi text; 2 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_2__acl_expansion.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE ACLMASK AS ENUM ('READ', 'WRITE', 'DENY'); 2 | 3 | CREATE TABLE ACLENTITY ( 4 | id UUID PRIMARY KEY, 5 | owner UUID, 6 | name varchar(255) UNIQUE NOT NULL, 7 | FOREIGN KEY (owner) REFERENCES EGOGROUP(id) 8 | ); 9 | 10 | 11 | CREATE TABLE ACLUSERPERMISSION ( 12 | id UUID PRIMARY KEY, 13 | entity UUID, 14 | sid UUID, 15 | mask ACLMASK NOT NULL, 16 | FOREIGN KEY (entity) REFERENCES ACLENTITY(id), 17 | FOREIGN KEY (sid) REFERENCES EGOUSER(id) 18 | ); 19 | 20 | 21 | CREATE TABLE ACLGROUPPERMISSION ( 22 | id UUID PRIMARY KEY, 23 | entity UUID, 24 | sid UUID, 25 | mask ACLMASK NOT NULL, 26 | FOREIGN KEY (entity) REFERENCES ACLENTITY(id), 27 | FOREIGN KEY (sid) REFERENCES EGOGROUP(id) 28 | ); -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_4__score_integration.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE TOKEN( 2 | id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), 3 | token VARCHAR(2048) NOT NULL, 4 | owner UUID NOT NULL REFERENCES EGOUSER(ID), 5 | issuedate TIMESTAMP DEFAULT NOW(), 6 | isrevoked BOOLEAN DEFAULT FALSE 7 | ); 8 | 9 | CREATE TABLE TOKENSCOPE ( 10 | token_id UUID NOT NULL REFERENCES TOKEN(ID), 11 | policy_id UUID NOT NULL REFERENCES ACLENTITY(ID), 12 | access_level ACLMASK NOT NULL 13 | ); 14 | 15 | CREATE TABLE TOKENAPPLICATION ( 16 | tokenid UUID NOT NULL REFERENCES TOKEN(ID), 17 | appid UUID NOT NULL REFERENCES EGOAPPLICATION(ID) 18 | ); 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_6__add_not_null_constraint.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE EGOAPPLICATION ALTER COLUMN name SET NOT NULL; 2 | ALTER TABLE EGOAPPLICATION ALTER COLUMN clientid SET NOT NULL; 3 | ALTER TABLE EGOAPPLICATION ALTER COLUMN clientsecret SET NOT NULL; 4 | ALTER TABLE EGOAPPLICATION ALTER COLUMN status SET NOT NULL; 5 | 6 | ALTER TABLE EGOGROUP ALTER COLUMN name SET NOT NULL; 7 | ALTER TABLE EGOGROUP ALTER COLUMN status SET NOT NULL; 8 | 9 | ALTER TABLE EGOUSER ALTER COLUMN name SET NOT NULL; 10 | ALTER TABLE EGOUSER ALTER COLUMN email SET NOT NULL; 11 | ALTER TABLE EGOUSER ALTER COLUMN role SET NOT NULL; 12 | ALTER TABLE EGOUSER ALTER COLUMN createdat SET NOT NULL; 13 | -- ALTER TABLE EGOUSER ALTER COLUMN lastlogin SET NOT NULL; 14 | ALTER TABLE EGOUSER ALTER COLUMN status SET NOT NULL; 15 | -- ALTER TABLE EGOUSER ALTER COLUMN preferredlanguage SET NOT NULL; 16 | 17 | ALTER TABLE GROUPAPPLICATION ALTER COLUMN group_id SET NOT NULL; 18 | ALTER TABLE GROUPAPPLICATION ALTER COLUMN application_id SET NOT NULL; 19 | 20 | ALTER TABLE TOKEN ALTER COLUMN issuedate SET NOT NULL; 21 | ALTER TABLE TOKEN ALTER COLUMN isrevoked SET NOT NULL; 22 | 23 | ALTER TABLE USERAPPLICATION ALTER COLUMN application_id SET NOT NULL; 24 | 25 | ALTER TABLE USERGROUP ALTER COLUMN group_id SET NOT NULL; 26 | 27 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_7__token_modification.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE token RENAME COLUMN token TO name; 2 | ALTER TABLE token ADD CONSTRAINT token_name_key UNIQUE (name); 3 | ALTER TABLE token ADD description VARCHAR(255); 4 | -------------------------------------------------------------------------------- /src/main/resources/flyway/sql/V1_8__application_types.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE APPLICATIONTYPE AS ENUM('CLIENT','ADMIN'); 2 | ALTER TABLE EGOUSER RENAME COLUMN role to usertype; 3 | ALTER TABLE EGOAPPLICATION add column applicationtype APPLICATIONTYPE not null DEFAULT 'CLIENT'; 4 | -------------------------------------------------------------------------------- /src/main/resources/schemas/00-psql-drop-tables.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS EGOAPPLICATION CASCADE; 2 | DROP TABLE IF EXISTS EGOUSER CASCADE; 3 | DROP TABLE IF EXISTS EGOGROUP CASCADE; 4 | DROP TABLE IF EXISTS GROUPAPPLICATION CASCADE; 5 | DROP TABLE IF EXISTS USERGROUP CASCADE; 6 | DROP TABLE IF EXISTS USERAPPLICATION CASCADE; 7 | DROP TABLE IF EXISTS ACLENTITY CASCADE; 8 | DROP TABLE IF EXISTS ACLUSERPERMISSION CASCADE; 9 | DROP TABLE IF EXISTS ACLGROUPPERMISSION CASCADE; 10 | DROP TYPE IF EXISTS ACLMASK CASCADE; -------------------------------------------------------------------------------- /src/main/resources/scripts/env_template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### =================================================== ### 4 | # Reference file for server environment variables # 5 | ### =================================================== ### 6 | 7 | # === Install Path 8 | export EGO_INSTALL_PATH= 9 | export EGO_KEYSTORE_PATH= 10 | 11 | # === DB Config 12 | export EGO_DB= 13 | export EGO_DB_HOST= 14 | export EGO_DB_PORT= 15 | 16 | # Leave DB_USER AND DB_PASS empty if using VAULT 17 | export EGO_DB_USER= 18 | export EGO_DB_PASS= 19 | 20 | # === App Server Config 21 | export EGO_ACTIVE_PROFILES="default" 22 | export EGO_SERVER_PORT=8081 23 | 24 | # Leave IDs and Secrets empty if using VAULT 25 | export EGO_SERVER_GOOGLE_CLIENT_IDS="" 26 | export EGO_SERVER_FACEBOOK_APP_ID="" 27 | export EGO_SERVER_FACEBOOK_SECRET="" 28 | 29 | # === VAULT CONFIG 30 | # Leave all below empty if not using VAULT 31 | export VAULT_APPLICATION_NAME="development/oicr/ego" 32 | export EGO_VAULT_URI= 33 | export EGO_VAULT_SCHEME= 34 | export EGO_VAULT_HOST= 35 | export EGO_VAULT_PORT= 36 | #leave IAM Role blank if using Token authentication 37 | export EGO_IAM_ROLE= 38 | #leave Token blank if using IAM Role 39 | export VAULT_TOKEN= 40 | -------------------------------------------------------------------------------- /src/main/resources/scripts/jwt/export-pub-key.sh: -------------------------------------------------------------------------------- 1 | keytool -list -rfc --keystore $1 | openssl x509 -inform pem -pubkey 2 | -------------------------------------------------------------------------------- /src/main/resources/scripts/jwt/gen-key-pair.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # generate pubkey and private keys 4 | openssl genrsa -out private_key.pem 2048 5 | openssl rsa -in private_key.pem -pubout -out public_key.pem 6 | openssl pkcs8 -topk8 -in private_key.pem -inform pem -out private_key_pkcs8.pem -outform pem -nocrypt 7 | awk '{ printf "%s", $0 }' public_key.pem | awk '{ gsub("-----BEGIN PUBLIC KEY-----","",$0); print $0 }' | awk '{ gsub("-----END PUBLIC KEY-----","",$0); print $0 }' > public_key_text.pem 8 | awk '{ printf "%s", $0 }' private_key_pkcs8.pem | awk '{ gsub("-----BEGIN PRIVATE KEY-----","",$0); print $0 }' | awk '{ gsub("-----END PRIVATE KEY-----","",$0); print $0 }' > private_key_text.pem 9 | 10 | # cleanup 11 | rm private_key.pem private_key_pkcs8.pem public_key.pem 12 | -------------------------------------------------------------------------------- /src/main/resources/scripts/jwt/gen-keystore.sh: -------------------------------------------------------------------------------- 1 | keytool -genkeypair -alias $1 -keyalg RSA -keypass $2 -keystore ego-jwt.jks -storepass $3 2 | -------------------------------------------------------------------------------- /src/main/resources/scripts/start-server-iam.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # === Add IAM profile 4 | export EGO_IAM_PROFILE=$EGO_ACTIVE_PROFILES,app,db,iam 5 | 6 | # === Start Server 7 | $EGO_INSTALL_PATH/install/bin/ego start \ 8 | wrapper.app.parameter.4=--spring.profiles.active=$EGO_IAM_PROFILE \ 9 | wrapper.app.parameter.5=--token.key-store=$EGO_KEYSTORE_PATH \ 10 | set.SPRING_DATASOURCE_URL=jdbc:postgresql://$EGO_DB_HOST:$EGO_DB_PORT/$EGO_DB \ 11 | set.SERVER_PORT=$EGO_SERVER_PORT \ 12 | set.SPRING_APPLICATION_NAME=$VAULT_APPLICATION_NAME \ 13 | set.SPRING_CLOUD_VAULT_URI=$EGO_VAULT_URI \ 14 | set.SPRING_CLOUD_VAULT_SCHEME=$EGO_VAULT_SCHEME \ 15 | set.SPRING_CLOUD_VAULT_HOST=$EGO_VAULT_HOST \ 16 | set.SPRING_CLOUD_VAULT_PORT=$EGO_VAULT_PORT \ 17 | set.SPRING_CLOUD_VAULT_AWS-IAM_ROLE=$EGO_IAM_ROLE 18 | -------------------------------------------------------------------------------- /src/main/resources/scripts/start-server-token.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # === Add token profile 3 | export EGO_TOKEN_PROFILE=$EGO_ACTIVE_PROFILES,app,db,token 4 | 5 | # === Start Server 6 | $EGO_INSTALL_PATH/install/bin/ego start \ 7 | wrapper.app.parameter.4=--spring.profiles.active=EGO_TOKEN_PROFILE \ 8 | wrapper.app.parameter.5=--token.key-store=$EGO_KEYSTORE_PATH \ 9 | set.SPRING_DATASOURCE_URL=jdbc:postgresql://$EGO_DB_HOST:$EGO_DB_PORT/$EGO_DB \ 10 | set.SERVER_PORT=$EGO_SERVER_PORT \ 11 | set.SPRING_APPLICATION_NAME=$VAULT_APPLICATION_NAME \ 12 | set.SPRING_CLOUD_VAULT_URI=$EGO_VAULT_URI \ 13 | set.SPRING_CLOUD_VAULT_SCHEME=$EGO_VAULT_SCHEME \ 14 | set.SPRING_CLOUD_VAULT_HOST=$EGO_VAULT_HOST \ 15 | set.SPRING_CLOUD_VAULT_PORT=$EGO_VAULT_PORT \ 16 | set.SPRING_CLOUD_VAULT_TOKEN=$VAULT_TOKEN 17 | -------------------------------------------------------------------------------- /src/main/resources/scripts/start-server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | $EGO_INSTALL_PATH/install/bin/ego start \ 3 | wrapper.app.parameter.4=--spring.profiles.active=$EGO_ACTIVE_PROFILES,jks \ 4 | wrapper.app.parameter.5=--token.key-store=$EGO_KEYSTORE_PATH \ 5 | set.SPRING_DATASOURCE_URL=jdbc:postgresql://$EGO_DB_HOST:$EGO_DB_PORT/$EGO_DB \ 6 | set.SPRING_DATASOURCE_USERNAME=$EGO_DB_USER \ 7 | set.SPRING_DATASOURCE_PASSWORD=$EGO_DB_PASS \ 8 | set.SERVER_PORT=$EGO_SERVER_PORT \ 9 | set.GOOGLE_CLIENT_IDS=$EGO_SERVER_GOOGLE_CLIENT_IDS \ 10 | set.FACEBOOK_CLIENT_ID=$EGO_SERVER_FACEBOOK_APP_ID \ 11 | set.FACEBOOK_CLIENT_SECRET=$EGO_SERVER_FACEBOOK_SECRET 12 | -------------------------------------------------------------------------------- /src/main/resources/scripts/stop-server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | $EGO_INSTALL_PATH/install/bin/ego stop 3 | -------------------------------------------------------------------------------- /src/main/resources/scripts/vault/setup-local-vault.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo 'To test vault locally: download vault from: https://www.vaultproject.io/downloads.html and unzip in this folder' 4 | echo 'start vault server using : ./vault server -config ./vault.conf' 5 | echo 'Once server is running, execute this file again to setup required keys in vault' 6 | 7 | # Vault server address 8 | export VAULT_ADDR=http://localhost:8200 9 | 10 | # initialize vault 11 | export OUTPUT=$(./vault operator init) 12 | 13 | # set token 14 | export VAULT_TOKEN=$(echo $(echo $OUTPUT | awk -F'Token: ' '{print$2}' | awk -F' Vault' '{print $1}')) 15 | 16 | echo 'User this token in bootstrap-token.properties:' $VAULT_TOKEN 17 | 18 | # grab all unseal keys 19 | export VAULT_UNSEAL_KEY1=$(echo $(echo $OUTPUT | awk -F'Unseal Key 1:' '{print$2}' | awk -F' Unseal' '{print $1}')) 20 | export VAULT_UNSEAL_KEY2=$(echo $(echo $OUTPUT | awk -F'Unseal Key 2:' '{print$2}' | awk -F' Unseal' '{print $1}')) 21 | export VAULT_UNSEAL_KEY3=$(echo $(echo $OUTPUT | awk -F'Unseal Key 3:' '{print$2}' | awk -F' Unseal' '{print $1}')) 22 | 23 | # unseal vault 24 | ./vault operator unseal $VAULT_UNSEAL_KEY1 25 | ./vault operator unseal $VAULT_UNSEAL_KEY2 26 | ./vault operator unseal $VAULT_UNSEAL_KEY3 27 | 28 | ./vault write secret/development/oicr/ego/dev spring.datasource.username=postgres spring.datasource.password=postgres facebook.client.id=140524976574963 facebook.client.secret=2439abe7ae008bda7ab5cfdf706b4d66 google.client.Ids=808545688838-99s198l9lhl2hsvkpo5u91f3sflegemp.apps.googleusercontent.com,911372380614-7m296bg4eadc7m43e2mm6fs1a0ggkke1.apps.googleusercontent.com,814606937527-v7tr5dfqegjijicq3jeu5arv5tcl4ks0.apps.googleusercontent.com,814606937527-kk7ooglk6pj2tvpn7ldip6g3b74f8o72.apps.googleusercontent.com token.key-alias=ego-jwt token.keystore-password:=eG0tistic@lly 29 | ./vault read /secret/development/oicr/ego/dev 30 | -------------------------------------------------------------------------------- /src/main/resources/scripts/vault/vault.conf: -------------------------------------------------------------------------------- 1 | backend "inmem" { 2 | } 3 | 4 | listener "tcp" { 5 | address = "0.0.0.0:8200" 6 | tls_disable = 1 7 | } 8 | 9 | disable_mlock = true 10 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/controller/AbstractNameableResolvablePermissionControllerTest.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.controller; 2 | 3 | import bio.overture.ego.model.entity.AbstractPermission; 4 | import bio.overture.ego.model.entity.NameableEntity; 5 | import java.util.UUID; 6 | 7 | public abstract class AbstractNameableResolvablePermissionControllerTest< 8 | O extends NameableEntity, P extends AbstractPermission> 9 | extends AbstractResolvablePermissionControllerTest {} 10 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/model/enums/AccessLevelTest.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.model.enums; 2 | 3 | import static bio.overture.ego.model.enums.AccessLevel.DENY; 4 | import static bio.overture.ego.model.enums.AccessLevel.READ; 5 | import static bio.overture.ego.model.enums.AccessLevel.WRITE; 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.assertFalse; 8 | import static org.junit.Assert.assertTrue; 9 | 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.junit.Test; 12 | import org.junit.runner.RunWith; 13 | import org.springframework.boot.test.context.SpringBootTest; 14 | import org.springframework.test.context.ActiveProfiles; 15 | import org.springframework.test.context.junit4.SpringRunner; 16 | import org.springframework.transaction.annotation.Transactional; 17 | 18 | @Slf4j 19 | @SpringBootTest 20 | @RunWith(SpringRunner.class) 21 | @ActiveProfiles("test") 22 | @Transactional 23 | public class AccessLevelTest { 24 | @Test 25 | public void testFromValue() { 26 | assertEquals(AccessLevel.fromValue("read"), AccessLevel.READ); 27 | assertEquals(AccessLevel.fromValue("write"), AccessLevel.WRITE); 28 | assertEquals(AccessLevel.fromValue("deny"), AccessLevel.DENY); 29 | } 30 | 31 | @Test 32 | public void testAllows() { 33 | allows(READ, READ); 34 | allows(WRITE, READ); 35 | denies(DENY, READ); 36 | 37 | denies(READ, WRITE); 38 | allows(WRITE, WRITE); 39 | denies(DENY, WRITE); 40 | 41 | denies(READ, DENY); 42 | denies(WRITE, DENY); 43 | denies(DENY, DENY); 44 | } 45 | 46 | public void allows(AccessLevel have, AccessLevel want) { 47 | assertTrue(AccessLevel.allows(have, want)); 48 | } 49 | 50 | public void denies(AccessLevel have, AccessLevel want) { 51 | assertFalse(AccessLevel.allows(have, want)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/model/params/ScopeNameTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package bio.overture.ego.model.params; 19 | 20 | import static org.junit.Assert.assertEquals; 21 | 22 | import bio.overture.ego.model.enums.AccessLevel; 23 | import lombok.val; 24 | import org.junit.Test; 25 | 26 | public class ScopeNameTest { 27 | @Test 28 | public void testRead() { 29 | val s = new ScopeName("song.READ"); 30 | assertEquals("song", s.getName()); 31 | assertEquals(AccessLevel.READ, s.getAccessLevel()); 32 | } 33 | 34 | @Test 35 | public void testNamedStudy() { 36 | val s = new ScopeName("song.ABC.WRITE"); 37 | assertEquals("song.ABC", s.getName()); 38 | assertEquals(AccessLevel.WRITE, s.getAccessLevel()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/service/FirstUserAsAdminTest.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.service; 2 | 3 | import bio.overture.ego.model.entity.User; 4 | import bio.overture.ego.model.enums.UserType; 5 | import bio.overture.ego.utils.EntityGenerator; 6 | import lombok.extern.slf4j.Slf4j; 7 | import lombok.val; 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.boot.test.context.SpringBootTest; 13 | import org.springframework.test.context.ActiveProfiles; 14 | import org.springframework.test.context.TestPropertySource; 15 | import org.springframework.test.context.junit4.SpringRunner; 16 | import org.springframework.transaction.annotation.Transactional; 17 | 18 | @Slf4j 19 | @SpringBootTest 20 | @RunWith(SpringRunner.class) 21 | @ActiveProfiles("test") 22 | @TestPropertySource(properties = "default.user.firstUserAsAdmin=true") 23 | @Transactional 24 | public class FirstUserAsAdminTest { 25 | 26 | @Autowired private UserService userService; 27 | @Autowired private EntityGenerator entityGenerator; 28 | 29 | @Test 30 | public void testOnlyFirstUserShouldBeAdminByDefault() { 31 | userService.getRepository().deleteAll(); 32 | val usersCount = userService.countAll(); 33 | Assert.assertEquals(0, usersCount); 34 | User u = entityGenerator.setupUser("First User", UserType.USER); 35 | val user = userService.findById(u.getId()).get(); 36 | Assert.assertEquals(user.getType(), UserType.ADMIN); 37 | 38 | // add another user make sure they don't get ADMIN type 39 | User u2 = entityGenerator.setupUser("Second User", UserType.USER); 40 | val user2 = userService.findById(u2.getId()).get(); 41 | Assert.assertEquals(user2.getType(), UserType.USER); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/service/initialization/InitializationEventTest.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.service.initialization; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import bio.overture.ego.repository.InitTripWireRepository; 6 | import bio.overture.ego.service.InitializationService; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | import org.springframework.test.context.ActiveProfiles; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | 15 | @Slf4j 16 | @ActiveProfiles("test") 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest(properties = "initialization.enabled=true") 19 | public class InitializationEventTest { 20 | 21 | @Autowired private InitializationService service; 22 | @Autowired private InitTripWireRepository repository; 23 | 24 | @Test 25 | public void testInitializationUsingSpringEvents() { 26 | assertTrue(service.isInitialized()); 27 | // Note: this is necessary since this will persist the initialization flag for other tests. 28 | // This is out of context of a test transaction because the initialization happens at when 29 | // spring boots, 30 | // which is before the execution of this test. 31 | // Because of this, we need to delete the initialization value from the database for other 32 | // tests. 33 | repository.deleteAll(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/utils/EntityTools.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import bio.overture.ego.model.entity.Application; 4 | import bio.overture.ego.model.entity.Group; 5 | import bio.overture.ego.model.entity.Identifiable; 6 | import bio.overture.ego.model.entity.User; 7 | import java.util.Collection; 8 | import java.util.List; 9 | import java.util.Set; 10 | import java.util.UUID; 11 | import java.util.stream.Collectors; 12 | 13 | public class EntityTools { 14 | public static List extractGroupIds(Set entities) { 15 | return entities.stream().map(Group::getId).collect(java.util.stream.Collectors.toList()); 16 | } 17 | 18 | public static List extractGroupNames(List entities) { 19 | return entities.stream().map(Group::getName).collect(java.util.stream.Collectors.toList()); 20 | } 21 | 22 | public static List extractUserIds(Set entities) { 23 | return entities.stream().map(User::getId).collect(java.util.stream.Collectors.toList()); 24 | } 25 | 26 | public static List extractAppIds(Set entities) { 27 | return entities.stream().map(Application::getId).collect(Collectors.toList()); 28 | } 29 | 30 | public static > List extractIDs(Collection entities) { 31 | return entities.stream().map(Identifiable::getId).collect(Collectors.toList()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/utils/WithMockCustomApplication.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import static bio.overture.ego.model.enums.ApplicationType.ADMIN; 4 | 5 | import bio.overture.ego.model.enums.ApplicationType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import org.springframework.security.test.context.support.WithSecurityContext; 9 | 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @WithSecurityContext(factory = WithMockCustomApplicationSecurityContextFactory.class) 12 | public @interface WithMockCustomApplication { 13 | 14 | String name() default "Admin Security App"; 15 | 16 | String clientId() default "Admin-Security-APP-ID"; 17 | 18 | String clientSecret() default "Admin-Security-APP-Secret"; 19 | 20 | String redirectUri() default "mock.com"; 21 | 22 | String description() default "Mock Application"; 23 | 24 | String errorRedirectUri() default "mock.com/error"; 25 | 26 | ApplicationType type() default ADMIN; 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/utils/WithMockCustomUser.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils; 2 | 3 | import static bio.overture.ego.model.enums.ProviderType.GOOGLE; 4 | import static bio.overture.ego.model.enums.UserType.ADMIN; 5 | 6 | import bio.overture.ego.model.enums.ProviderType; 7 | import bio.overture.ego.model.enums.UserType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import org.springframework.security.test.context.support.WithSecurityContext; 11 | 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class) 14 | public @interface WithMockCustomUser { 15 | 16 | String firstName() default "Admin"; 17 | 18 | String lastName() default "User"; 19 | 20 | UserType type() default ADMIN; 21 | 22 | ProviderType providerType() default GOOGLE; 23 | 24 | String providerSubjectId() default "0123"; 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/utils/web/BasicWebResource.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils.web; 2 | 3 | import org.springframework.boot.test.web.client.TestRestTemplate; 4 | import org.springframework.http.ResponseEntity; 5 | 6 | public class BasicWebResource> 7 | extends AbstractWebResource> { 8 | 9 | public BasicWebResource(TestRestTemplate restTemplate, String serverUrl, Class responseType) { 10 | super(restTemplate, serverUrl, responseType); 11 | } 12 | 13 | @Override 14 | protected O createResponseOption(ResponseEntity responseEntity) { 15 | return (O) new ResponseOption(responseEntity); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/utils/web/CleanResponse.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils.web; 2 | 3 | import lombok.Builder; 4 | import lombok.NonNull; 5 | import lombok.Value; 6 | 7 | @Value 8 | @Builder 9 | public class CleanResponse { 10 | @NonNull private final String statusCodeName; 11 | private final int statusCodeValue; 12 | private final Object body; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/utils/web/QueryParam.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils.web; 2 | 3 | import static bio.overture.ego.utils.Joiners.COMMA; 4 | import static java.lang.String.format; 5 | 6 | import lombok.Builder; 7 | import lombok.NonNull; 8 | import lombok.Value; 9 | 10 | @Value 11 | @Builder 12 | public class QueryParam { 13 | @NonNull private final String key; 14 | @NonNull private final Object value; 15 | 16 | public static QueryParam createQueryParam(String key, Object... values) { 17 | return new QueryParam(key, COMMA.join(values)); 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return format("%s=%s", key, value); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/utils/web/ResponseOption.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils.web; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.springframework.http.HttpStatus.BAD_REQUEST; 5 | import static org.springframework.http.HttpStatus.CONFLICT; 6 | import static org.springframework.http.HttpStatus.NOT_FOUND; 7 | import static org.springframework.http.HttpStatus.OK; 8 | 9 | import java.util.function.Function; 10 | import lombok.Getter; 11 | import lombok.NonNull; 12 | import lombok.RequiredArgsConstructor; 13 | import org.junit.Assert; 14 | import org.springframework.http.HttpStatus; 15 | import org.springframework.http.ResponseEntity; 16 | 17 | @RequiredArgsConstructor 18 | public class ResponseOption> { 19 | 20 | @Getter @NonNull private final ResponseEntity response; 21 | 22 | public O assertStatusCode(HttpStatus code) { 23 | 24 | assertEquals(code, response.getStatusCode()); 25 | return thisInstance(); 26 | } 27 | 28 | public O assertOk() { 29 | return assertStatusCode(OK); 30 | } 31 | 32 | public O assertNotFound() { 33 | return assertStatusCode(NOT_FOUND); 34 | } 35 | 36 | public O assertConflict() { 37 | return assertStatusCode(CONFLICT); 38 | } 39 | 40 | public O assertBadRequest() { 41 | return assertStatusCode(BAD_REQUEST); 42 | } 43 | 44 | public O assertHasBody() { 45 | Assert.assertTrue(response.hasBody()); 46 | Assert.assertNotNull(response.getBody()); 47 | return thisInstance(); 48 | } 49 | 50 | public R map(Function, R> transformingFunction) { 51 | return transformingFunction.apply(getResponse()); 52 | } 53 | 54 | private O thisInstance() { 55 | return (O) this; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/bio/overture/ego/utils/web/StringWebResource.java: -------------------------------------------------------------------------------- 1 | package bio.overture.ego.utils.web; 2 | 3 | import org.springframework.boot.test.web.client.TestRestTemplate; 4 | import org.springframework.http.ResponseEntity; 5 | 6 | public class StringWebResource 7 | extends AbstractWebResource { 8 | 9 | public StringWebResource(TestRestTemplate restTemplate, String serverUrl) { 10 | super(restTemplate, serverUrl, String.class); 11 | } 12 | 13 | @Override 14 | protected StringResponseOption createResponseOption(ResponseEntity responseEntity) { 15 | return new StringResponseOption(responseEntity); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/selenium/driver/BrowserStackDriverProxy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package selenium.driver; 19 | 20 | import com.browserstack.local.Local; 21 | import java.net.URL; 22 | import lombok.SneakyThrows; 23 | import org.openqa.selenium.remote.DesiredCapabilities; 24 | import org.openqa.selenium.remote.RemoteWebDriver; 25 | 26 | public class BrowserStackDriverProxy extends RemoteWebDriver { 27 | 28 | /** State */ 29 | private final Local local; 30 | 31 | @SneakyThrows 32 | public BrowserStackDriverProxy(URL url, DesiredCapabilities capabilities, Local local) { 33 | super(url, capabilities); 34 | this.local = local; 35 | } 36 | 37 | @Override 38 | @SneakyThrows 39 | public void quit() { 40 | if (local != null) local.stop(); 41 | super.quit(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/selenium/rule/AssumingSeleniumEnvironment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package selenium.rule; 19 | 20 | import org.junit.AssumptionViolatedException; 21 | import org.junit.rules.TestRule; 22 | import org.junit.runner.Description; 23 | import org.junit.runners.model.Statement; 24 | import selenium.driver.WebDriverFactory.DriverType; 25 | 26 | public class AssumingSeleniumEnvironment implements TestRule { 27 | 28 | private SeleniumEnvironmentChecker checker; 29 | 30 | public AssumingSeleniumEnvironment(SeleniumEnvironmentChecker checker) { 31 | this.checker = checker; 32 | } 33 | 34 | public DriverType getDriverType() { 35 | return checker.getType(); 36 | } 37 | 38 | @Override 39 | public Statement apply(Statement base, Description description) { 40 | return new Statement() { 41 | @Override 42 | public void evaluate() throws Throwable { 43 | if (!checker.shouldRunTest()) { 44 | throw new AssumptionViolatedException("Could not connect. Skipping test!"); 45 | } else { 46 | base.evaluate(); 47 | } 48 | } 49 | }; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/selenium/rule/SeleniumEnvironmentChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019. The Ontario Institute for Cancer Research. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package selenium.rule; 19 | 20 | import lombok.Getter; 21 | import selenium.driver.WebDriverFactory.DriverType; 22 | 23 | public class SeleniumEnvironmentChecker { 24 | 25 | @Getter private DriverType type; 26 | 27 | public SeleniumEnvironmentChecker() { 28 | String envVar = System.getenv("SELENIUM_TEST_TYPE"); 29 | if (envVar != null) { 30 | type = DriverType.valueOf(envVar); 31 | } 32 | } 33 | 34 | public boolean shouldRunTest() { 35 | if (type == DriverType.BROWSERSTACK || type == DriverType.LOCAL) { 36 | return true; 37 | } else { 38 | return false; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/resources/conf/bs.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": "hub-cloud.browserstack.com", 3 | "user": "*", 4 | "key": "*", 5 | 6 | "capabilities": { 7 | "os": "Windows", 8 | "os_version": "10", 9 | "browser": "Chrome", 10 | "browser_version": "62.0", 11 | "browserstack.debug": true, 12 | "browserstack.local": true, 13 | "project": "ego" 14 | }, 15 | 16 | "environments": [{ 17 | "browser": "chrome" 18 | }] 19 | } --------------------------------------------------------------------------------