aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-server
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2019-08-12 15:24:22 +0200
committerSonarTech <sonartech@sonarsource.com>2019-08-14 20:21:14 +0200
commit2528f0d148c0f0c0f6e4022c423ac5d67dcb650a (patch)
treecfdd97e8868cffa3beb0d74011e3eec9dd7ab973 /server/sonar-server
parente9ae396829a95e449d2e02934fc0567e7f09f833 (diff)
downloadsonarqube-2528f0d148c0f0c0f6e4022c423ac5d67dcb650a.tar.gz
sonarqube-2528f0d148c0f0c0f6e4022c423ac5d67dcb650a.zip
create webserver-auth and webserver-common from sonar-server
actual module names are sonar-webserver-auth and sonar-webserver-common
Diffstat (limited to 'server/sonar-server')
-rw-r--r--server/sonar-server/build.gradle5
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationError.java74
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationFilter.java71
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationModule.java50
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationRedirection.java53
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/BaseContextFactory.java93
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/BasicAuthentication.java125
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/Cookies.java122
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/Credentials.java73
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsAuthentication.java76
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsExternalAuthentication.java192
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsLocalAuthentication.java202
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/CustomAuthentication.java41
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/HttpHeadersAuthentication.java218
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/IdentityProviderRepository.java91
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/InitFilter.java133
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/JwtCsrfVerifier.java96
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/JwtHttpHandler.java202
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/JwtSerializer.java183
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/LogOAuthWarning.java61
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2AuthenticationParameters.java46
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2AuthenticationParametersImpl.java159
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2CallbackContext.java31
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2CallbackFilter.java126
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2ContextFactory.java153
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/OAuthCsrfVerifier.java73
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/RequestAuthenticator.java35
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/RequestAuthenticatorImpl.java83
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/SafeModeUserSession.java108
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/UserLastConnectionDatesUpdater.java31
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/UserLastConnectionDatesUpdaterImpl.java73
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistrar.java28
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistrarImpl.java292
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistration.java137
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java136
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEvent.java182
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEventImpl.java106
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationException.java106
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/event/package-info.java23
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/exception/EmailAlreadyExistsRedirectionException.java73
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/exception/RedirectionException.java25
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/exception/package-info.java23
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/authentication/package-info.java23
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/DefaultOrganizationEnforcer.java41
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/MemberUpdater.java148
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/NoopDefaultOrganizationCache.java37
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/OrganisationSupport.java121
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java30
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdater.java180
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java250
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidation.java107
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java83
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/package-info.java23
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/GroupId.java56
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/GroupIdOrAnyone.java67
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java10
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/PermissionPrivilegeChecker.java58
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java30
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/PermissionServiceImpl.java69
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/ProjectId.java56
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/RequestValidator.java89
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/UserId.java54
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java34
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotification.java30
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationBuilder.java220
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationHandler.java62
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTemplate.java113
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfile.java135
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileDefinitionsBridge.java91
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileInsert.java30
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImpl.java234
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileLoader.java44
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepository.java41
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImpl.java216
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdate.java32
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImpl.java89
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesUpdateListener.java76
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/DescendantProfilesSupplier.java55
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileName.java71
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java91
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivationContext.java368
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java479
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/AbstractUserSession.java205
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/CompatibilityRealm.java51
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/DoPrivileged.java154
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/ExternalIdentity.java51
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/NewUser.java142
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/NewUserNotifier.java48
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/SecurityRealmFactory.java131
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/ServerUserSession.java266
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/SystemPasscode.java40
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/SystemPasscodeImpl.java76
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java189
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/UpdateUser.java135
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java277
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/UserSessionFactory.java32
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/UserSessionFactoryImpl.java58
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/UserUpdater.java485
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/package-info.java23
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupCreator.java32
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupCreatorImpl.java51
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupFinder.java43
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/usergroups/package-info.java23
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/usertoken/TokenGenerator.java49
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/usertoken/TokenGeneratorImpl.java39
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/usertoken/UserTokenAuthentication.java58
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/usertoken/UserTokenModule.java31
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/usertoken/package-info.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/BooleanTypeValidation.java42
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/FloatTypeValidation.java45
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/IntegerTypeValidation.java45
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/LongTypeValidation.java43
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/MetricKeyValidator.java60
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java44
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/StringListTypeValidation.java41
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/StringTypeValidation.java40
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/TextTypeValidation.java40
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/TypeValidation.java34
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/TypeValidationModule.java39
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/TypeValidations.java70
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/util/Validation.java33
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/AuthenticationModuleTest.java37
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/BaseContextFactoryTest.java101
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/BasicAuthenticationTest.java195
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/CookiesTest.java121
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsAuthenticationTest.java171
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsExternalAuthenticationTest.java293
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsLocalAuthenticationTest.java188
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsTest.java69
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/FakeBasicIdentityProvider.java43
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/FakeOAuth2IdentityProvider.java52
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java457
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/IdentityProviderRepositoryRule.java48
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/IdentityProviderRepositoryTest.java90
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/InitFilterTest.java371
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/JwtCsrfVerifierTest.java197
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/JwtHttpHandlerTest.java356
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/JwtSerializerTest.java324
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/LogOAuthWarningTest.java83
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2AuthenticationParametersImplTest.java201
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2CallbackFilterTest.java334
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2ContextFactoryTest.java248
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/OAuthCsrfVerifierTest.java152
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/RequestAuthenticatorImplTest.java134
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/SafeModeUserSessionTest.java51
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/TestIdentityProvider.java100
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/TestUserRegistrar.java48
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/UserLastConnectionDatesUpdaterImplTest.java115
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/UserRegistrarImplOrgMembershipSyncTest.java241
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java791
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java218
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventImplTest.java375
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventSourceTest.java218
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationExceptionMatcher.java147
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationExceptionTest.java74
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java85
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/exceptions/MessageTest.java88
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java40
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/language/LanguageTesting.java55
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/organization/DefaultOrganizationEnforcerTest.java46
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/organization/MemberUpdaterTest.java517
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/organization/OrganisationSupportTest.java219
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java415
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java240
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/permission/PermissionServiceImplTest.java45
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationHandlerTest.java136
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTemplateTest.java283
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTest.java145
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileDefinitionsBridgeTest.java106
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImplTest.java225
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileLoaderTest.java39
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImplTest.java211
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryRule.java103
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java449
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesUpdateListenerTest.java183
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/tester/AbstractMockUserSession.java123
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/tester/AnonymousMockUserSession.java82
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/tester/AttributeHolderServletContext.java308
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/tester/AttributeHolderServletContextTest.java373
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/tester/MockUserSession.java147
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/tester/MockUserSessionTest.java39
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/tester/UserSessionRule.java373
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/tester/package-info.java23
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/CompatibilityRealmTest.java41
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/DefaultUserTest.java53
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/DoPrivilegedTest.java95
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/ExternalIdentityTest.java65
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/NewUserNotifierTest.java51
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/NewUserTest.java90
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/SecurityRealmFactoryTest.java156
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/ServerUserSessionTest.java710
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/SystemPasscodeImplTest.java106
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/TestUserSessionFactory.java139
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/ThreadLocalUserSessionTest.java91
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java665
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java386
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterUpdateTest.java636
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/usergroups/DefaultGroupCreatorImplTest.java69
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/usergroups/DefaultGroupFinderTest.java75
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/usertoken/TokenGeneratorImplTest.java55
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/usertoken/UserTokenAuthenticationTest.java76
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/usertoken/UserTokenModuleTest.java35
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/util/MetricKeyValidatorTest.java49
203 files changed, 12 insertions, 26914 deletions
diff --git a/server/sonar-server/build.gradle b/server/sonar-server/build.gradle
index d15997a4a14..f225dbac9ca 100644
--- a/server/sonar-server/build.gradle
+++ b/server/sonar-server/build.gradle
@@ -50,6 +50,8 @@ dependencies {
compile project(':server:sonar-db-migration')
compile project(':server:sonar-process')
compile project(':server:sonar-server-common')
+ compile project(':server:sonar-webserver-auth')
+ compile project(':server:sonar-webserver-common')
compile project(':server:sonar-webserver-ws')
compile project(':sonar-core')
compile project(':sonar-duplications')
@@ -80,8 +82,9 @@ dependencies {
testCompile 'org.subethamail:subethasmtp'
testCompile project(':server:sonar-db-testing')
testCompile project(path: ":server:sonar-server-common", configuration: "tests")
- testCompile project(':sonar-testing-harness')
+ testCompile project(path: ":server:sonar-webserver-auth", configuration: "tests")
testCompile project(path: ":server:sonar-webserver-ws", configuration: "tests")
+ testCompile project(':sonar-testing-harness')
runtime 'io.jsonwebtoken:jjwt-jackson'
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationError.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationError.java
deleted file mode 100644
index b0a79c33687..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationError.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.authentication.event.AuthenticationException;
-
-import static org.sonar.server.authentication.AuthenticationRedirection.encodeMessage;
-import static org.sonar.server.authentication.AuthenticationRedirection.redirectTo;
-import static org.sonar.server.authentication.Cookies.newCookieBuilder;
-
-public final class AuthenticationError {
-
- private static final String UNAUTHORIZED_PATH = "/sessions/unauthorized";
-
- private static final Logger LOGGER = Loggers.get(AuthenticationError.class);
- private static final String AUTHENTICATION_ERROR_COOKIE = "AUTHENTICATION-ERROR";
- private static final int FIVE_MINUTES_IN_SECONDS = 5 * 60;
-
- private AuthenticationError() {
- // Utility class
- }
-
- static void handleError(Exception e, HttpServletRequest request, HttpServletResponse response, String message) {
- LOGGER.warn(message, e);
- redirectToUnauthorized(request, response);
- }
-
- static void handleError(HttpServletRequest request, HttpServletResponse response, String message) {
- LOGGER.warn(message);
- redirectToUnauthorized(request, response);
- }
-
- static void handleAuthenticationError(AuthenticationException e, HttpServletRequest request, HttpServletResponse response) {
- String publicMessage = e.getPublicMessage();
- if (publicMessage != null && !publicMessage.isEmpty()) {
- addErrorCookie(request, response, publicMessage);
- }
- redirectToUnauthorized(request, response);
- }
-
- public static void addErrorCookie(HttpServletRequest request, HttpServletResponse response, String value) {
- response.addCookie(newCookieBuilder(request)
- .setName(AUTHENTICATION_ERROR_COOKIE)
- .setValue(encodeMessage(value))
- .setHttpOnly(false)
- .setExpiry(FIVE_MINUTES_IN_SECONDS)
- .build());
- }
-
- private static void redirectToUnauthorized(HttpServletRequest request, HttpServletResponse response) {
- redirectTo(response, request.getContextPath() + UNAUTHORIZED_PATH);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationFilter.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationFilter.java
deleted file mode 100644
index 244ccfbc2a8..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationFilter.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.annotation.CheckForNull;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.api.web.ServletFilter;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static java.lang.String.format;
-import static org.sonar.server.authentication.AuthenticationError.handleError;
-
-public abstract class AuthenticationFilter extends ServletFilter {
-
- static final String CALLBACK_PATH = "/oauth2/callback/";
- private final IdentityProviderRepository identityProviderRepository;
-
- public AuthenticationFilter(IdentityProviderRepository identityProviderRepository) {
- this.identityProviderRepository = identityProviderRepository;
- }
-
- /**
- * @return the {@link IdentityProvider} for the key extracted in the request if is exists, or {@code null}, in which
- * case the request is fully handled and caller should not handle it
- */
- @CheckForNull
- IdentityProvider resolveProviderOrHandleResponse(HttpServletRequest request, HttpServletResponse response, String path) {
- String requestUri = request.getRequestURI();
- String providerKey = extractKeyProvider(requestUri, request.getContextPath() + path);
- if (providerKey == null) {
- handleError(request, response, "No provider key found in URI");
- return null;
- }
- try {
- return identityProviderRepository.getEnabledByKey(providerKey);
- } catch (Exception e) {
- handleError(e, request, response, format("Failed to retrieve IdentityProvider for key '%s'", providerKey));
- return null;
- }
- }
-
- @CheckForNull
- private static String extractKeyProvider(String requestUri, String context) {
- if (requestUri.contains(context)) {
- String key = requestUri.replace(context, "");
- if (!isNullOrEmpty(key)) {
- return key;
- }
- }
- return null;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationModule.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationModule.java
deleted file mode 100644
index 8309447b400..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationModule.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.sonar.core.platform.Module;
-import org.sonar.server.authentication.event.AuthenticationEventImpl;
-
-public class AuthenticationModule extends Module {
- @Override
- protected void configureModule() {
- add(
- AuthenticationEventImpl.class,
- InitFilter.class,
- OAuth2CallbackFilter.class,
- IdentityProviderRepository.class,
- BaseContextFactory.class,
- OAuth2ContextFactory.class,
- UserRegistrarImpl.class,
- OAuthCsrfVerifier.class,
- UserSessionInitializer.class,
- JwtSerializer.class,
- JwtHttpHandler.class,
- JwtCsrfVerifier.class,
- OAuth2AuthenticationParametersImpl.class,
- CredentialsAuthentication.class,
- CredentialsLocalAuthentication.class,
- CredentialsExternalAuthentication.class,
- BasicAuthentication.class,
- HttpHeadersAuthentication.class,
- RequestAuthenticatorImpl.class,
- UserLastConnectionDatesUpdaterImpl.class);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationRedirection.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationRedirection.java
deleted file mode 100644
index b3e91772dd1..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationRedirection.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import javax.servlet.http.HttpServletResponse;
-
-import static java.lang.String.format;
-import static java.net.URLEncoder.encode;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-public class AuthenticationRedirection {
-
- private AuthenticationRedirection() {
- // Only static methods
- }
-
- public static String encodeMessage(String message) {
- try {
- return encode(message, UTF_8.name())
- // In order for Javascript to be able to decode this message, + must be replaced by %20
- .replace("+", "%20");
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException(format("Fail to encode %s", message), e);
- }
- }
-
- public static void redirectTo(HttpServletResponse response, String url) {
- try {
- response.sendRedirect(url);
- } catch (IOException e) {
- throw new IllegalStateException(format("Fail to redirect to %s", url), e);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/BaseContextFactory.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/BaseContextFactory.java
deleted file mode 100644
index 0c9385b2e4e..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/BaseContextFactory.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.platform.Server;
-import org.sonar.api.server.authentication.BaseIdentityProvider;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.user.ThreadLocalUserSession;
-import org.sonar.server.user.UserSessionFactory;
-
-public class BaseContextFactory {
-
- private final ThreadLocalUserSession threadLocalUserSession;
- private final UserRegistrar userRegistrar;
- private final Server server;
- private final JwtHttpHandler jwtHttpHandler;
- private final UserSessionFactory userSessionFactory;
-
- public BaseContextFactory(UserRegistrar userRegistrar, Server server, JwtHttpHandler jwtHttpHandler,
- ThreadLocalUserSession threadLocalUserSession, UserSessionFactory userSessionFactory) {
- this.userSessionFactory = userSessionFactory;
- this.userRegistrar = userRegistrar;
- this.server = server;
- this.jwtHttpHandler = jwtHttpHandler;
- this.threadLocalUserSession = threadLocalUserSession;
- }
-
- public BaseIdentityProvider.Context newContext(HttpServletRequest request, HttpServletResponse response, BaseIdentityProvider identityProvider) {
- return new ContextImpl(request, response, identityProvider);
- }
-
- private class ContextImpl implements BaseIdentityProvider.Context {
- private final HttpServletRequest request;
- private final HttpServletResponse response;
- private final BaseIdentityProvider identityProvider;
-
- public ContextImpl(HttpServletRequest request, HttpServletResponse response, BaseIdentityProvider identityProvider) {
- this.request = request;
- this.response = response;
- this.identityProvider = identityProvider;
- }
-
- @Override
- public HttpServletRequest getRequest() {
- return request;
- }
-
- @Override
- public HttpServletResponse getResponse() {
- return response;
- }
-
- @Override
- public String getServerBaseURL() {
- return server.getPublicRootUrl();
- }
-
- @Override
- public void authenticate(UserIdentity userIdentity) {
- UserDto userDto = userRegistrar.register(
- UserRegistration.builder()
- .setUserIdentity(userIdentity)
- .setProvider(identityProvider)
- .setSource(Source.external(identityProvider))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
- jwtHttpHandler.generateToken(userDto, request, response);
- threadLocalUserSession.set(userSessionFactory.create(userDto));
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/BasicAuthentication.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/BasicAuthentication.java
deleted file mode 100644
index 71dbd0428fa..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/BasicAuthentication.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Base64;
-import java.util.Optional;
-import javax.servlet.http.HttpServletRequest;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.usertoken.UserTokenAuthentication;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.commons.lang.StringUtils.startsWithIgnoreCase;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-/**
- * HTTP BASIC authentication relying on tuple {login, password}.
- * Login can represent a user access token.
- *
- * @see CredentialsAuthentication for standard login/password authentication
- * @see UserTokenAuthentication for user access token
- */
-public class BasicAuthentication {
-
- private final DbClient dbClient;
- private final CredentialsAuthentication credentialsAuthentication;
- private final UserTokenAuthentication userTokenAuthentication;
- private final AuthenticationEvent authenticationEvent;
-
- public BasicAuthentication(DbClient dbClient, CredentialsAuthentication credentialsAuthentication,
- UserTokenAuthentication userTokenAuthentication, AuthenticationEvent authenticationEvent) {
- this.dbClient = dbClient;
- this.credentialsAuthentication = credentialsAuthentication;
- this.userTokenAuthentication = userTokenAuthentication;
- this.authenticationEvent = authenticationEvent;
- }
-
- public Optional<UserDto> authenticate(HttpServletRequest request) {
- return extractCredentialsFromHeader(request)
- .flatMap(credentials -> Optional.of(authenticate(credentials, request)));
- }
-
- public static Optional<Credentials> extractCredentialsFromHeader(HttpServletRequest request) {
- String authorizationHeader = request.getHeader("Authorization");
- if (authorizationHeader == null || !startsWithIgnoreCase(authorizationHeader, "BASIC")) {
- return Optional.empty();
- }
-
- String basicAuthEncoded = authorizationHeader.substring(6);
- String basicAuthDecoded = getDecodedBasicAuth(basicAuthEncoded);
-
- int semiColonPos = basicAuthDecoded.indexOf(':');
- if (semiColonPos <= 0) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(Method.BASIC))
- .setMessage("Decoded basic auth does not contain ':'")
- .build();
- }
- String login = basicAuthDecoded.substring(0, semiColonPos);
- String password = basicAuthDecoded.substring(semiColonPos + 1);
- return Optional.of(new Credentials(login, password));
- }
-
- private static String getDecodedBasicAuth(String basicAuthEncoded) {
- try {
- return new String(Base64.getDecoder().decode(basicAuthEncoded.getBytes(UTF_8)), UTF_8);
- } catch (Exception e) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(Method.BASIC))
- .setMessage("Invalid basic header")
- .build();
- }
- }
-
- private UserDto authenticate(Credentials credentials, HttpServletRequest request) {
- if (!credentials.getPassword().isPresent()) {
- UserDto userDto = authenticateFromUserToken(credentials.getLogin());
- authenticationEvent.loginSuccess(request, userDto.getLogin(), Source.local(Method.BASIC_TOKEN));
- return userDto;
- }
- return credentialsAuthentication.authenticate(credentials, request, Method.BASIC);
- }
-
- private UserDto authenticateFromUserToken(String token) {
- Optional<String> authenticatedUserUuid = userTokenAuthentication.authenticate(token);
- if (!authenticatedUserUuid.isPresent()) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(Method.BASIC_TOKEN))
- .setMessage("Token doesn't exist")
- .build();
- }
- try (DbSession dbSession = dbClient.openSession(false)) {
- UserDto userDto = dbClient.userDao().selectByUuid(dbSession, authenticatedUserUuid.get());
- if (userDto == null || !userDto.isActive()) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(Method.BASIC_TOKEN))
- .setMessage("User doesn't exist")
- .build();
- }
- return userDto;
- }
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/Cookies.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/Cookies.java
deleted file mode 100644
index 1af5276cbcd..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/Cookies.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Arrays;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static java.util.Objects.requireNonNull;
-
-/**
- * Helper class to create a {@link javax.servlet.http.Cookie}.
- *
- * The {@link javax.servlet.http.Cookie#setSecure(boolean)} will automatically be set to true.
- */
-public class Cookies {
-
- private static final String HTTPS_HEADER = "X-Forwarded-Proto";
- private static final String HTTPS_VALUE = "https";
-
- private Cookies() {
- // Only static methods
- }
-
- public static Optional<Cookie> findCookie(String cookieName, HttpServletRequest request) {
- Cookie[] cookies = request.getCookies();
- if (cookies == null) {
- return Optional.empty();
- }
- return Arrays.stream(cookies)
- .filter(cookie -> cookieName.equals(cookie.getName()))
- .findFirst();
- }
-
- public static CookieBuilder newCookieBuilder(HttpServletRequest request) {
- return new CookieBuilder(request);
- }
-
- public static class CookieBuilder {
-
- private final HttpServletRequest request;
-
- private String name;
- private String value;
- private boolean httpOnly;
- private int expiry;
-
- CookieBuilder(HttpServletRequest request) {
- this.request = request;
- }
-
- /**
- * Name of the cookie
- */
- public CookieBuilder setName(String name) {
- this.name = requireNonNull(name);
- return this;
- }
-
- /**
- * Name of the cookie
- */
- public CookieBuilder setValue(@Nullable String value) {
- this.value = value;
- return this;
- }
-
- /**
- * Sets the flag that controls if this cookie will be hidden from scripts on the client side.
- */
- public CookieBuilder setHttpOnly(boolean httpOnly) {
- this.httpOnly = httpOnly;
- return this;
- }
-
- /**
- * Sets the maximum age of the cookie in seconds.
- */
- public CookieBuilder setExpiry(int expiry) {
- this.expiry = expiry;
- return this;
- }
-
- public Cookie build() {
- Cookie cookie = new Cookie(requireNonNull(name), value);
- cookie.setPath(getContextPath(request));
- cookie.setSecure(isHttps(request));
- cookie.setHttpOnly(httpOnly);
- cookie.setMaxAge(expiry);
- return cookie;
- }
-
- private static boolean isHttps(HttpServletRequest request) {
- return HTTPS_VALUE.equalsIgnoreCase(request.getHeader(HTTPS_HEADER));
- }
-
- private static String getContextPath(HttpServletRequest request) {
- String path = request.getContextPath();
- return isNullOrEmpty(path) ? "/" : path;
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/Credentials.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/Credentials.java
deleted file mode 100644
index fc92b9580c0..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/Credentials.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Objects;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
-
-@Immutable
-public class Credentials {
-
- private final String login;
- private final String password;
-
- public Credentials(String login, @Nullable String password) {
- checkArgument(login != null && !login.isEmpty(), "login must not be null nor empty");
- this.login = login;
- this.password = defaultIfEmpty(password, null);
- }
-
- /**
- * Non-empty login
- */
- public String getLogin() {
- return login;
- }
-
- /**
- * Non-empty password. {@code Optional.empty()} is returned if the password is not set
- * or initially empty. {@code Optional.of("")} is never returned.
- */
- public Optional<String> getPassword() {
- return Optional.ofNullable(password);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- Credentials that = (Credentials) o;
- return login.equals(that.login) && password.equals(that.password);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(login, password);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsAuthentication.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsAuthentication.java
deleted file mode 100644
index 52083037cab..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsAuthentication.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Optional;
-import javax.servlet.http.HttpServletRequest;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationException;
-
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-/**
- * Authentication based on the tuple {login, password}. Validation can be
- * delegated to an external system, e.g. LDAP.
- */
-public class CredentialsAuthentication {
-
- private final DbClient dbClient;
- private final AuthenticationEvent authenticationEvent;
- private final CredentialsExternalAuthentication externalAuthentication;
- private final CredentialsLocalAuthentication localAuthentication;
-
- public CredentialsAuthentication(DbClient dbClient, AuthenticationEvent authenticationEvent,
- CredentialsExternalAuthentication externalAuthentication, CredentialsLocalAuthentication localAuthentication) {
- this.dbClient = dbClient;
- this.authenticationEvent = authenticationEvent;
- this.externalAuthentication = externalAuthentication;
- this.localAuthentication = localAuthentication;
- }
-
- public UserDto authenticate(Credentials credentials, HttpServletRequest request, Method method) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- return authenticate(dbSession, credentials, request, method);
- }
- }
-
- private UserDto authenticate(DbSession dbSession, Credentials credentials, HttpServletRequest request, Method method) {
- UserDto localUser = dbClient.userDao().selectActiveUserByLogin(dbSession, credentials.getLogin());
- if (localUser != null && localUser.isLocal()) {
- localAuthentication.authenticate(dbSession, localUser, credentials.getPassword().orElse(null), method);
- dbSession.commit();
- authenticationEvent.loginSuccess(request, localUser.getLogin(), Source.local(method));
- return localUser;
- }
- Optional<UserDto> externalUser = externalAuthentication.authenticate(credentials, request, method);
- if (externalUser.isPresent()) {
- return externalUser.get();
- }
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(method))
- .setLogin(credentials.getLogin())
- .setMessage(localUser != null && !localUser.isLocal() ? "User is not local" : "No active user for login")
- .build();
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsExternalAuthentication.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsExternalAuthentication.java
deleted file mode 100644
index 6a0187e35c9..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsExternalAuthentication.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Optional;
-import javax.servlet.http.HttpServletRequest;
-import org.sonar.api.Startable;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.security.Authenticator;
-import org.sonar.api.security.ExternalGroupsProvider;
-import org.sonar.api.security.ExternalUsersProvider;
-import org.sonar.api.security.SecurityRealm;
-import org.sonar.api.security.UserDetails;
-import org.sonar.api.server.authentication.Display;
-import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.user.SecurityRealmFactory;
-
-import static java.util.Objects.requireNonNull;
-import static org.apache.commons.lang.StringUtils.isEmpty;
-import static org.apache.commons.lang.StringUtils.trimToNull;
-import static org.sonar.server.user.ExternalIdentity.SQ_AUTHORITY;
-
-/**
- * Delegates the validation of credentials to an external system, e.g. LDAP.
- */
-public class CredentialsExternalAuthentication implements Startable {
-
- private static final Logger LOG = Loggers.get(CredentialsExternalAuthentication.class);
-
- private final Configuration config;
- private final SecurityRealmFactory securityRealmFactory;
- private final UserRegistrar userRegistrar;
- private final AuthenticationEvent authenticationEvent;
-
- private SecurityRealm realm;
- private Authenticator authenticator;
- private ExternalUsersProvider externalUsersProvider;
- private ExternalGroupsProvider externalGroupsProvider;
-
- public CredentialsExternalAuthentication(Configuration config, SecurityRealmFactory securityRealmFactory,
- UserRegistrar userRegistrar, AuthenticationEvent authenticationEvent) {
- this.config = config;
- this.securityRealmFactory = securityRealmFactory;
- this.userRegistrar = userRegistrar;
- this.authenticationEvent = authenticationEvent;
- }
-
- @Override
- public void start() {
- realm = securityRealmFactory.getRealm();
- if (realm != null) {
- authenticator = requireNonNull(realm.doGetAuthenticator(), "No authenticator available");
- externalUsersProvider = requireNonNull(realm.getUsersProvider(), "No users provider available");
- externalGroupsProvider = realm.getGroupsProvider();
- }
- }
-
- public Optional<UserDto> authenticate(Credentials credentials, HttpServletRequest request, AuthenticationEvent.Method method) {
- if (realm == null) {
- return Optional.empty();
- }
- return Optional.of(doAuthenticate(fixCase(credentials), request, method));
- }
-
- private UserDto doAuthenticate(Credentials credentials, HttpServletRequest request, AuthenticationEvent.Method method) {
- try {
- ExternalUsersProvider.Context externalUsersProviderContext = new ExternalUsersProvider.Context(credentials.getLogin(), request);
- UserDetails details = externalUsersProvider.doGetUserDetails(externalUsersProviderContext);
- if (details == null) {
- throw AuthenticationException.newBuilder()
- .setSource(realmEventSource(method))
- .setLogin(credentials.getLogin())
- .setMessage("No user details")
- .build();
- }
- Authenticator.Context authenticatorContext = new Authenticator.Context(credentials.getLogin(), credentials.getPassword().orElse(null), request);
- boolean status = authenticator.doAuthenticate(authenticatorContext);
- if (!status) {
- throw AuthenticationException.newBuilder()
- .setSource(realmEventSource(method))
- .setLogin(credentials.getLogin())
- .setMessage("Realm returned authenticate=false")
- .build();
- }
- UserDto userDto = synchronize(credentials.getLogin(), details, request, method);
- authenticationEvent.loginSuccess(request, credentials.getLogin(), realmEventSource(method));
- return userDto;
- } catch (AuthenticationException e) {
- throw e;
- } catch (Exception e) {
- // It seems that with Realm API it's expected to log the error and to not authenticate the user
- LOG.error("Error during authentication", e);
- throw AuthenticationException.newBuilder()
- .setSource(realmEventSource(method))
- .setLogin(credentials.getLogin())
- .setMessage(e.getMessage())
- .build();
- }
- }
-
- private Source realmEventSource(AuthenticationEvent.Method method) {
- return Source.realm(method, realm.getName());
- }
-
- private UserDto synchronize(String userLogin, UserDetails details, HttpServletRequest request, AuthenticationEvent.Method method) {
- String name = details.getName();
- UserIdentity.Builder userIdentityBuilder = UserIdentity.builder()
- .setLogin(userLogin)
- .setName(isEmpty(name) ? userLogin : name)
- .setEmail(trimToNull(details.getEmail()))
- .setProviderLogin(userLogin);
- if (externalGroupsProvider != null) {
- ExternalGroupsProvider.Context context = new ExternalGroupsProvider.Context(userLogin, request);
- Collection<String> groups = externalGroupsProvider.doGetGroups(context);
- userIdentityBuilder.setGroups(new HashSet<>(groups));
- }
- return userRegistrar.register(
- UserRegistration.builder()
- .setUserIdentity(userIdentityBuilder.build())
- .setProvider(new ExternalIdentityProvider())
- .setSource(realmEventSource(method))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
- }
-
- private Credentials fixCase(Credentials credentials) {
- if (config.getBoolean("sonar.authenticator.downcase").orElse(false)) {
- return new Credentials(credentials.getLogin().toLowerCase(Locale.ENGLISH), credentials.getPassword().orElse(null));
- }
- return credentials;
- }
-
- private static class ExternalIdentityProvider implements IdentityProvider {
- @Override
- public String getKey() {
- return SQ_AUTHORITY;
- }
-
- @Override
- public String getName() {
- return SQ_AUTHORITY;
- }
-
- @Override
- public Display getDisplay() {
- return null;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
-
- @Override
- public boolean allowsUsersToSignUp() {
- return true;
- }
- }
-
- @Override
- public void stop() {
- // Nothing to do
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsLocalAuthentication.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsLocalAuthentication.java
deleted file mode 100644
index de76fc27447..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/CredentialsLocalAuthentication.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.security.SecureRandom;
-import javax.annotation.Nullable;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.mindrot.jbcrypt.BCrypt;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.event.AuthenticationEvent.Method;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.authentication.event.AuthenticationException;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-
-/**
- * Validates the password of a "local" user (password is stored in
- * database).
- */
-public class CredentialsLocalAuthentication {
-
- private final DbClient dbClient;
- private static final SecureRandom SECURE_RANDOM = new SecureRandom();
- // The default hash method that must be used is BCRYPT
- private static final HashMethod DEFAULT = HashMethod.BCRYPT;
-
- public CredentialsLocalAuthentication(DbClient dbClient) {
- this.dbClient = dbClient;
- }
-
- /**
- * This method authenticate a user with his password against the value stored in user.
- * If authentication failed an AuthenticationException will be thrown containing the failure message.
- * If the password must be updated because an old algorithm is used, the UserDto is updated but the session
- * is not committed
- */
- public void authenticate(DbSession session, UserDto user, @Nullable String password, Method method) {
- if (user.getHashMethod() == null) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(method))
- .setLogin(user.getLogin())
- .setMessage("null hash method")
- .build();
- }
-
- HashMethod hashMethod;
- try {
- hashMethod = HashMethod.valueOf(user.getHashMethod());
- } catch (IllegalArgumentException ex) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(method))
- .setLogin(user.getLogin())
- .setMessage(format("Unknown hash method [%s]", user.getHashMethod()))
- .build();
- }
-
- AuthenticationResult result = hashMethod.checkCredentials(user, password);
- if (!result.isSuccessful()) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(method))
- .setLogin(user.getLogin())
- .setMessage(result.getFailureMessage())
- .build();
- }
-
- // Upgrade the password if it's an old hashMethod
- if (hashMethod != DEFAULT) {
- DEFAULT.storeHashPassword(user, password);
- dbClient.userDao().update(session, user);
- }
- }
-
- /**
- * Method used to store the password as a hash in database.
- * The crypted_password, salt and hash_method are set
- */
- public void storeHashPassword(UserDto user, String password) {
- DEFAULT.storeHashPassword(user, password);
- }
-
- public enum HashMethod implements HashFunction {
- SHA1(new Sha1Function()), BCRYPT(new BcryptFunction());
-
- private HashFunction hashFunction;
-
- HashMethod(HashFunction hashFunction) {
- this.hashFunction = hashFunction;
- }
-
- @Override
- public AuthenticationResult checkCredentials(UserDto user, String password) {
- return hashFunction.checkCredentials(user, password);
- }
-
- @Override
- public void storeHashPassword(UserDto user, String password) {
- hashFunction.storeHashPassword(user, password);
- }
- }
-
- private static class AuthenticationResult {
- private final boolean successful;
- private final String failureMessage;
-
- private AuthenticationResult(boolean successful, String failureMessage) {
- checkArgument((successful && failureMessage.isEmpty()) || (!successful && !failureMessage.isEmpty()), "Incorrect parameters");
- this.successful = successful;
- this.failureMessage = failureMessage;
- }
-
- public boolean isSuccessful() {
- return successful;
- }
-
- public String getFailureMessage() {
- return failureMessage;
- }
- }
-
- public interface HashFunction {
- AuthenticationResult checkCredentials(UserDto user, String password);
-
- void storeHashPassword(UserDto user, String password);
- }
-
- /**
- * Implementation of deprecated SHA1 hash function
- */
- private static final class Sha1Function implements HashFunction {
- @Override
- public AuthenticationResult checkCredentials(UserDto user, String password) {
- if (user.getCryptedPassword() == null) {
- return new AuthenticationResult(false, "null password in DB");
- }
- if (user.getSalt() == null) {
- return new AuthenticationResult(false, "null salt");
- }
- if (!user.getCryptedPassword().equals(hash(user.getSalt(), password))) {
- return new AuthenticationResult(false, "wrong password");
- }
- return new AuthenticationResult(true, "");
- }
-
- @Override
- public void storeHashPassword(UserDto user, String password) {
- requireNonNull(password, "Password cannot be null");
- byte[] saltRandom = new byte[20];
- SECURE_RANDOM.nextBytes(saltRandom);
- String salt = DigestUtils.sha1Hex(saltRandom);
-
- user.setHashMethod(HashMethod.SHA1.name())
- .setCryptedPassword(hash(salt, password))
- .setSalt(salt);
- }
-
- private static String hash(String salt, String password) {
- return DigestUtils.sha1Hex("--" + salt + "--" + password + "--");
- }
- }
-
- /**
- * Implementation of bcrypt hash function
- */
- private static final class BcryptFunction implements HashFunction {
- @Override
- public AuthenticationResult checkCredentials(UserDto user, String password) {
- if (!BCrypt.checkpw(password, user.getCryptedPassword())) {
- return new AuthenticationResult(false, "wrong password");
- }
- return new AuthenticationResult(true, "");
- }
-
- @Override
- public void storeHashPassword(UserDto user, String password) {
- requireNonNull(password, "Password cannot be null");
- user.setHashMethod(HashMethod.BCRYPT.name())
- .setCryptedPassword(BCrypt.hashpw(password, BCrypt.gensalt(12)))
- .setSalt(null);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/CustomAuthentication.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/CustomAuthentication.java
deleted file mode 100644
index ee80b12c135..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/CustomAuthentication.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Optional;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.server.ServerSide;
-import org.sonar.server.user.UserSession;
-
-/**
- * Authentication that can create {@link org.sonar.server.user.UserSession}
- * that are not associated to a user.
- * That is convenient for authenticating bots that need special permissions.
- *
- * This is not an extension point, plugins can not provide their own
- * implementations.
- */
-@ServerSide
-public interface CustomAuthentication {
-
- Optional<UserSession> authenticate(HttpServletRequest request, HttpServletResponse response);
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/HttpHeadersAuthentication.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/HttpHeadersAuthentication.java
deleted file mode 100644
index 29ed2e65195..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/HttpHeadersAuthentication.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableMap;
-import java.util.Collections;
-import java.util.Date;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Optional;
-import javax.annotation.CheckForNull;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.Startable;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.server.authentication.Display;
-import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.db.user.UserDto;
-import org.sonar.process.ProcessProperties;
-import org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.exceptions.BadRequestException;
-
-import static org.apache.commons.lang.time.DateUtils.addMinutes;
-import static org.sonar.process.ProcessProperties.Property.SONAR_WEB_SSO_EMAIL_HEADER;
-import static org.sonar.process.ProcessProperties.Property.SONAR_WEB_SSO_ENABLE;
-import static org.sonar.process.ProcessProperties.Property.SONAR_WEB_SSO_GROUPS_HEADER;
-import static org.sonar.process.ProcessProperties.Property.SONAR_WEB_SSO_LOGIN_HEADER;
-import static org.sonar.process.ProcessProperties.Property.SONAR_WEB_SSO_NAME_HEADER;
-import static org.sonar.process.ProcessProperties.Property.SONAR_WEB_SSO_REFRESH_INTERVAL_IN_MINUTES;
-import static org.sonar.server.user.ExternalIdentity.SQ_AUTHORITY;
-
-/**
- * Authentication based on the HTTP request headers. The front proxy
- * is responsible for validating user identity.
- */
-public class HttpHeadersAuthentication implements Startable {
-
- private static final Logger LOG = Loggers.get(HttpHeadersAuthentication.class);
-
- private static final Splitter COMA_SPLITTER = Splitter.on(",").trimResults().omitEmptyStrings();
-
- private static final String LAST_REFRESH_TIME_TOKEN_PARAM = "ssoLastRefreshTime";
-
- private static final EnumSet<ProcessProperties.Property> PROPERTIES = EnumSet.of(
- SONAR_WEB_SSO_LOGIN_HEADER,
- SONAR_WEB_SSO_NAME_HEADER,
- SONAR_WEB_SSO_EMAIL_HEADER,
- SONAR_WEB_SSO_GROUPS_HEADER,
- SONAR_WEB_SSO_REFRESH_INTERVAL_IN_MINUTES);
-
- private final System2 system2;
- private final Configuration config;
- private final UserRegistrar userRegistrar;
- private final JwtHttpHandler jwtHttpHandler;
- private final AuthenticationEvent authenticationEvent;
- private final Map<String, String> settingsByKey = new HashMap<>();
-
- private boolean enabled = false;
-
- public HttpHeadersAuthentication(System2 system2, Configuration config, UserRegistrar userRegistrar,
- JwtHttpHandler jwtHttpHandler, AuthenticationEvent authenticationEvent) {
- this.system2 = system2;
- this.config = config;
- this.userRegistrar = userRegistrar;
- this.jwtHttpHandler = jwtHttpHandler;
- this.authenticationEvent = authenticationEvent;
- }
-
- @Override
- public void start() {
- if (config.getBoolean(SONAR_WEB_SSO_ENABLE.getKey()).orElse(false)) {
- LOG.info("HTTP headers authentication enabled");
- enabled = true;
- PROPERTIES.forEach(entry -> settingsByKey.put(entry.getKey(), config.get(entry.getKey()).orElse(entry.getDefaultValue())));
- }
- }
-
- @Override
- public void stop() {
- // Nothing to do
- }
-
- public Optional<UserDto> authenticate(HttpServletRequest request, HttpServletResponse response) {
- try {
- return doAuthenticate(request, response);
- } catch (BadRequestException e) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.sso())
- .setMessage(e.getMessage())
- .build();
- }
- }
-
- private Optional<UserDto> doAuthenticate(HttpServletRequest request, HttpServletResponse response) {
- if (!enabled) {
- return Optional.empty();
- }
- Map<String, String> headerValuesByNames = getHeaders(request);
- String login = getHeaderValue(headerValuesByNames, SONAR_WEB_SSO_LOGIN_HEADER.getKey());
- if (login == null) {
- return Optional.empty();
- }
- Optional<UserDto> user = getUserFromToken(request, response);
- if (user.isPresent() && login.equals(user.get().getLogin())) {
- return user;
- }
-
- UserDto userDto = doAuthenticate(headerValuesByNames, login);
- jwtHttpHandler.generateToken(userDto, ImmutableMap.of(LAST_REFRESH_TIME_TOKEN_PARAM, system2.now()), request, response);
- authenticationEvent.loginSuccess(request, userDto.getLogin(), Source.sso());
- return Optional.of(userDto);
- }
-
- private Optional<UserDto> getUserFromToken(HttpServletRequest request, HttpServletResponse response) {
- Optional<JwtHttpHandler.Token> token = jwtHttpHandler.getToken(request, response);
- if (!token.isPresent()) {
- return Optional.empty();
- }
- Date now = new Date(system2.now());
- int refreshIntervalInMinutes = Integer.parseInt(settingsByKey.get(SONAR_WEB_SSO_REFRESH_INTERVAL_IN_MINUTES.getKey()));
- Long lastFreshTime = (Long) token.get().getProperties().get(LAST_REFRESH_TIME_TOKEN_PARAM);
- if (lastFreshTime == null || now.after(addMinutes(new Date(lastFreshTime), refreshIntervalInMinutes))) {
- return Optional.empty();
- }
- return Optional.of(token.get().getUserDto());
- }
-
- private UserDto doAuthenticate(Map<String, String> headerValuesByNames, String login) {
- String name = getHeaderValue(headerValuesByNames, SONAR_WEB_SSO_NAME_HEADER.getKey());
- String email = getHeaderValue(headerValuesByNames, SONAR_WEB_SSO_EMAIL_HEADER.getKey());
- UserIdentity.Builder userIdentityBuilder = UserIdentity.builder()
- .setLogin(login)
- .setName(name == null ? login : name)
- .setEmail(email)
- .setProviderLogin(login);
- if (hasHeader(headerValuesByNames, SONAR_WEB_SSO_GROUPS_HEADER.getKey())) {
- String groupsValue = getHeaderValue(headerValuesByNames, SONAR_WEB_SSO_GROUPS_HEADER.getKey());
- userIdentityBuilder.setGroups(groupsValue == null ? Collections.emptySet() : new HashSet<>(COMA_SPLITTER.splitToList(groupsValue)));
- }
- return userRegistrar.register(
- UserRegistration.builder()
- .setUserIdentity(userIdentityBuilder.build())
- .setProvider(new SsoIdentityProvider())
- .setSource(Source.sso())
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
- }
-
- @CheckForNull
- private String getHeaderValue(Map<String, String> headerValuesByNames, String settingKey) {
- return headerValuesByNames.get(settingsByKey.get(settingKey).toLowerCase(Locale.ENGLISH));
- }
-
- private static Map<String, String> getHeaders(HttpServletRequest request) {
- Map<String, String> headers = new HashMap<>();
- Collections.list(request.getHeaderNames()).forEach(header -> headers.put(header.toLowerCase(Locale.ENGLISH), request.getHeader(header)));
- return headers;
- }
-
- private boolean hasHeader(Map<String, String> headerValuesByNames, String settingKey) {
- return headerValuesByNames.keySet().contains(settingsByKey.get(settingKey).toLowerCase(Locale.ENGLISH));
- }
-
- private static class SsoIdentityProvider implements IdentityProvider {
- @Override
- public String getKey() {
- return SQ_AUTHORITY;
- }
-
- @Override
- public String getName() {
- return getKey();
- }
-
- @Override
- public Display getDisplay() {
- return null;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
-
- @Override
- public boolean allowsUsersToSignUp() {
- return true;
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/IdentityProviderRepository.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/IdentityProviderRepository.java
deleted file mode 100644
index c1484f905c8..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/IdentityProviderRepository.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Ordering;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import org.sonar.api.server.authentication.IdentityProvider;
-
-import static com.google.common.collect.FluentIterable.from;
-
-public class IdentityProviderRepository {
-
- protected final Map<String, IdentityProvider> providersByKey = new HashMap<>();
-
- public IdentityProviderRepository(List<IdentityProvider> identityProviders) {
- this.providersByKey.putAll(FluentIterable.from(identityProviders).uniqueIndex(ToKey.INSTANCE));
- }
-
- /**
- * Used by pico when no identity provider available
- */
- public IdentityProviderRepository() {
- this.providersByKey.clear();
- }
-
- public IdentityProvider getEnabledByKey(String key) {
- IdentityProvider identityProvider = providersByKey.get(key);
- if (identityProvider != null && IsEnabledFilter.INSTANCE.apply(identityProvider)) {
- return identityProvider;
- }
- throw new IllegalArgumentException(String.format("Identity provider %s does not exist or is not enabled", key));
- }
-
- public List<IdentityProvider> getAllEnabledAndSorted() {
- return from(providersByKey.values())
- .filter(IsEnabledFilter.INSTANCE)
- .toSortedList(
- Ordering.natural().onResultOf(ToName.INSTANCE)
- );
- }
-
- private enum IsEnabledFilter implements Predicate<IdentityProvider> {
- INSTANCE;
-
- @Override
- public boolean apply(@Nonnull IdentityProvider input) {
- return input.isEnabled();
- }
- }
-
- private enum ToKey implements Function<IdentityProvider, String> {
- INSTANCE;
-
- @Override
- public String apply(@Nonnull IdentityProvider input) {
- return input.getKey();
- }
- }
-
- private enum ToName implements Function<IdentityProvider, String> {
- INSTANCE;
-
- @Override
- public String apply(@Nonnull IdentityProvider input) {
- return input.getName();
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/InitFilter.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/InitFilter.java
deleted file mode 100644
index 5b90a220d67..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/InitFilter.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.server.authentication.BaseIdentityProvider;
-import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.api.server.authentication.UnauthorizedException;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.authentication.exception.EmailAlreadyExistsRedirectionException;
-
-import static java.lang.String.format;
-import static org.sonar.server.authentication.AuthenticationError.handleAuthenticationError;
-import static org.sonar.server.authentication.AuthenticationError.handleError;
-import static org.sonar.server.authentication.AuthenticationRedirection.redirectTo;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-public class InitFilter extends AuthenticationFilter {
-
- private static final String INIT_CONTEXT = "/sessions/init/";
-
- private final BaseContextFactory baseContextFactory;
- private final OAuth2ContextFactory oAuth2ContextFactory;
- private final AuthenticationEvent authenticationEvent;
- private final OAuth2AuthenticationParameters oAuthOAuth2AuthenticationParameters;
-
- public InitFilter(IdentityProviderRepository identityProviderRepository, BaseContextFactory baseContextFactory,
- OAuth2ContextFactory oAuth2ContextFactory, AuthenticationEvent authenticationEvent, OAuth2AuthenticationParameters oAuthOAuth2AuthenticationParameters) {
- super(identityProviderRepository);
- this.baseContextFactory = baseContextFactory;
- this.oAuth2ContextFactory = oAuth2ContextFactory;
- this.authenticationEvent = authenticationEvent;
- this.oAuthOAuth2AuthenticationParameters = oAuthOAuth2AuthenticationParameters;
- }
-
- @Override
- public UrlPattern doGetPattern() {
- return UrlPattern.create(INIT_CONTEXT + "*");
- }
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- HttpServletResponse httpResponse = (HttpServletResponse) response;
-
- IdentityProvider provider = resolveProviderOrHandleResponse(httpRequest, httpResponse, INIT_CONTEXT);
- if (provider != null) {
- handleProvider(httpRequest, httpResponse, provider);
- }
- }
-
- private void handleProvider(HttpServletRequest request, HttpServletResponse response, IdentityProvider provider) {
- try {
- if (provider instanceof BaseIdentityProvider) {
- handleBaseIdentityProvider(request, response, (BaseIdentityProvider) provider);
- } else if (provider instanceof OAuth2IdentityProvider) {
- oAuthOAuth2AuthenticationParameters.init(request, response);
- handleOAuth2IdentityProvider(request, response, (OAuth2IdentityProvider) provider);
- } else {
- handleError(request, response, format("Unsupported IdentityProvider class: %s", provider.getClass()));
- }
- } catch (EmailAlreadyExistsRedirectionException e) {
- oAuthOAuth2AuthenticationParameters.delete(request, response);
- e.addCookie(request, response);
- redirectTo(response, e.getPath(request.getContextPath()));
- } catch (AuthenticationException e) {
- oAuthOAuth2AuthenticationParameters.delete(request, response);
- authenticationEvent.loginFailure(request, e);
- handleAuthenticationError(e, request, response);
- } catch (Exception e) {
- oAuthOAuth2AuthenticationParameters.delete(request, response);
- handleError(e, request, response, format("Fail to initialize authentication with provider '%s'", provider.getKey()));
- }
- }
-
- private void handleBaseIdentityProvider(HttpServletRequest request, HttpServletResponse response, BaseIdentityProvider provider) {
- try {
- provider.init(baseContextFactory.newContext(request, response, provider));
- } catch (UnauthorizedException e) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.external(provider))
- .setMessage(e.getMessage())
- .setPublicMessage(e.getMessage())
- .build();
- }
- }
-
- private void handleOAuth2IdentityProvider(HttpServletRequest request, HttpServletResponse response, OAuth2IdentityProvider provider) {
- try {
- provider.init(oAuth2ContextFactory.newContext(request, response, provider));
- } catch (UnauthorizedException e) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.oauth2(provider))
- .setMessage(e.getMessage())
- .setPublicMessage(e.getMessage())
- .build();
- }
- }
-
- @Override
- public void init(FilterConfig filterConfig) {
- // Nothing to do
- }
-
- @Override
- public void destroy() {
- // Nothing to do
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/JwtCsrfVerifier.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/JwtCsrfVerifier.java
deleted file mode 100644
index f94d1673364..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/JwtCsrfVerifier.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.collect.ImmutableSet;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.server.authentication.event.AuthenticationException;
-
-import static org.apache.commons.lang.StringUtils.isBlank;
-import static org.sonar.server.authentication.Cookies.newCookieBuilder;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-public class JwtCsrfVerifier {
-
- private static final String CSRF_STATE_COOKIE = "XSRF-TOKEN";
- private static final String CSRF_HEADER = "X-XSRF-TOKEN";
-
- private static final Set<String> UPDATE_METHODS = ImmutableSet.of("POST", "PUT", "DELETE");
- private static final String API_URL = "/api";
-
- public String generateState(HttpServletRequest request, HttpServletResponse response, int timeoutInSeconds) {
- // Create a state token to prevent request forgery.
- // Store it in the cookie for later validation.
- String state = new BigInteger(130, new SecureRandom()).toString(32);
- response.addCookie(newCookieBuilder(request).setName(CSRF_STATE_COOKIE).setValue(state).setHttpOnly(false).setExpiry(timeoutInSeconds).build());
- return state;
- }
-
- public void verifyState(HttpServletRequest request, @Nullable String csrfState, @Nullable String login) {
- if (!shouldRequestBeChecked(request)) {
- return;
- }
-
- String failureCause = checkCsrf(csrfState, request.getHeader(CSRF_HEADER));
- if (failureCause != null) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(Method.JWT))
- .setLogin(login)
- .setMessage(failureCause)
- .build();
- }
- }
-
- @CheckForNull
- private static String checkCsrf(@Nullable String csrfState, @Nullable String stateInHeader) {
- if (isBlank(csrfState)) {
- return "Missing reference CSRF value";
- }
- if (!StringUtils.equals(csrfState, stateInHeader)) {
- return "Wrong CSFR in request";
- }
- return null;
- }
-
- public void refreshState(HttpServletRequest request, HttpServletResponse response, String csrfState, int timeoutInSeconds) {
- response.addCookie(newCookieBuilder(request).setName(CSRF_STATE_COOKIE).setValue(csrfState).setHttpOnly(false).setExpiry(timeoutInSeconds).build());
- }
-
- public void removeState(HttpServletRequest request, HttpServletResponse response) {
- response.addCookie(newCookieBuilder(request).setName(CSRF_STATE_COOKIE).setValue(null).setHttpOnly(false).setExpiry(0).build());
- }
-
- private static boolean shouldRequestBeChecked(HttpServletRequest request) {
- if (UPDATE_METHODS.contains(request.getMethod())) {
- String path = request.getRequestURI().replaceFirst(request.getContextPath(), "");
- return path.startsWith(API_URL);
- }
- return false;
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/JwtHttpHandler.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/JwtHttpHandler.java
deleted file mode 100644
index b961187789f..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/JwtHttpHandler.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.collect.ImmutableMap;
-import io.jsonwebtoken.Claims;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Map;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.user.UserDto;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.requireNonNull;
-import static org.apache.commons.lang.StringUtils.isEmpty;
-import static org.apache.commons.lang.time.DateUtils.addSeconds;
-import static org.sonar.server.authentication.Cookies.findCookie;
-import static org.sonar.server.authentication.Cookies.newCookieBuilder;
-
-@ServerSide
-public class JwtHttpHandler {
-
- private static final String SESSION_TIMEOUT_IN_MINUTES_PROPERTY = "sonar.web.sessionTimeoutInMinutes";
- private static final int SESSION_TIMEOUT_DEFAULT_VALUE_IN_MINUTES = 3 * 24 * 60;
- private static final int MAX_SESSION_TIMEOUT_IN_MINUTES = 3 * 30 * 24 * 60;
-
- private static final String JWT_COOKIE = "JWT-SESSION";
- private static final String LAST_REFRESH_TIME_PARAM = "lastRefreshTime";
-
- private static final String CSRF_JWT_PARAM = "xsrfToken";
-
- // Time after which a user will be disconnected
- private static final int SESSION_DISCONNECT_IN_SECONDS = 3 * 30 * 24 * 60 * 60;
-
- // This refresh time is used to refresh the session
- // The value must be lower than sessionTimeoutInSeconds
- private static final int SESSION_REFRESH_IN_SECONDS = 5 * 60;
-
- private final System2 system2;
- private final DbClient dbClient;
- private final JwtSerializer jwtSerializer;
-
- // This timeout is used to disconnect the user we he has not browse any page for a while
- private final int sessionTimeoutInSeconds;
- private final JwtCsrfVerifier jwtCsrfVerifier;
-
- public JwtHttpHandler(System2 system2, DbClient dbClient, Configuration config, JwtSerializer jwtSerializer, JwtCsrfVerifier jwtCsrfVerifier) {
- this.jwtSerializer = jwtSerializer;
- this.dbClient = dbClient;
- this.system2 = system2;
- this.sessionTimeoutInSeconds = getSessionTimeoutInSeconds(config);
- this.jwtCsrfVerifier = jwtCsrfVerifier;
- }
-
- public void generateToken(UserDto user, Map<String, Object> properties, HttpServletRequest request, HttpServletResponse response) {
- String csrfState = jwtCsrfVerifier.generateState(request, response, sessionTimeoutInSeconds);
-
- String token = jwtSerializer.encode(new JwtSerializer.JwtSession(
- user.getUuid(),
- sessionTimeoutInSeconds,
- ImmutableMap.<String, Object>builder()
- .putAll(properties)
- .put(LAST_REFRESH_TIME_PARAM, system2.now())
- .put(CSRF_JWT_PARAM, csrfState)
- .build()));
- response.addCookie(createCookie(request, JWT_COOKIE, token, sessionTimeoutInSeconds));
- }
-
- public void generateToken(UserDto user, HttpServletRequest request, HttpServletResponse response) {
- generateToken(user, Collections.emptyMap(), request, response);
- }
-
- public Optional<UserDto> validateToken(HttpServletRequest request, HttpServletResponse response) {
- Optional<Token> token = getToken(request, response);
- if (token.isPresent()) {
- return Optional.of(token.get().getUserDto());
- }
- return Optional.empty();
- }
-
- public Optional<Token> getToken(HttpServletRequest request, HttpServletResponse response) {
- Optional<String> encodedToken = getTokenFromCookie(request);
- if (!encodedToken.isPresent()) {
- return Optional.empty();
- }
- return validateToken(encodedToken.get(), request, response);
- }
-
- private static Optional<String> getTokenFromCookie(HttpServletRequest request) {
- Optional<Cookie> jwtCookie = findCookie(JWT_COOKIE, request);
- if (!jwtCookie.isPresent()) {
- return Optional.empty();
- }
- Cookie cookie = jwtCookie.get();
- String token = cookie.getValue();
- if (isEmpty(token)) {
- return Optional.empty();
- }
- return Optional.of(token);
- }
-
- private Optional<Token> validateToken(String tokenEncoded, HttpServletRequest request, HttpServletResponse response) {
- Optional<Claims> claims = jwtSerializer.decode(tokenEncoded);
- if (!claims.isPresent()) {
- return Optional.empty();
- }
-
- Date now = new Date(system2.now());
- Claims token = claims.get();
- if (now.after(addSeconds(token.getIssuedAt(), SESSION_DISCONNECT_IN_SECONDS))) {
- return Optional.empty();
- }
- jwtCsrfVerifier.verifyState(request, (String) token.get(CSRF_JWT_PARAM), token.getSubject());
-
- if (now.after(addSeconds(getLastRefreshDate(token), SESSION_REFRESH_IN_SECONDS))) {
- refreshToken(token, request, response);
- }
-
- Optional<UserDto> user = selectUserFromUuid(token.getSubject());
- return user.map(userDto -> new Token(userDto, claims.get()));
- }
-
- private static Date getLastRefreshDate(Claims token) {
- Long lastFreshTime = (Long) token.get(LAST_REFRESH_TIME_PARAM);
- requireNonNull(lastFreshTime, "last refresh time is missing in token");
- return new Date(lastFreshTime);
- }
-
- private void refreshToken(Claims token, HttpServletRequest request, HttpServletResponse response) {
- String refreshToken = jwtSerializer.refresh(token, sessionTimeoutInSeconds);
- response.addCookie(createCookie(request, JWT_COOKIE, refreshToken, sessionTimeoutInSeconds));
- jwtCsrfVerifier.refreshState(request, response, (String) token.get(CSRF_JWT_PARAM), sessionTimeoutInSeconds);
- }
-
- public void removeToken(HttpServletRequest request, HttpServletResponse response) {
- response.addCookie(createCookie(request, JWT_COOKIE, null, 0));
- jwtCsrfVerifier.removeState(request, response);
- }
-
- private static Cookie createCookie(HttpServletRequest request, String name, @Nullable String value, int expirationInSeconds) {
- return newCookieBuilder(request).setName(name).setValue(value).setHttpOnly(true).setExpiry(expirationInSeconds).build();
- }
-
- private Optional<UserDto> selectUserFromUuid(String userUuid) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- UserDto user = dbClient.userDao().selectByUuid(dbSession, userUuid);
- return Optional.ofNullable(user != null && user.isActive() ? user : null);
- }
- }
-
- private static int getSessionTimeoutInSeconds(Configuration config) {
- int minutes = config.getInt(SESSION_TIMEOUT_IN_MINUTES_PROPERTY).orElse(SESSION_TIMEOUT_DEFAULT_VALUE_IN_MINUTES);
- checkArgument(minutes > 0, "Property %s must be strictly positive. Got %s", SESSION_TIMEOUT_IN_MINUTES_PROPERTY, minutes);
- checkArgument(minutes <= MAX_SESSION_TIMEOUT_IN_MINUTES, "Property %s must not be greater than 3 months (%s minutes). Got %s minutes",
- SESSION_TIMEOUT_IN_MINUTES_PROPERTY, MAX_SESSION_TIMEOUT_IN_MINUTES, minutes);
- return minutes * 60;
- }
-
- public static class Token {
- private final UserDto userDto;
- private final Map<String, Object> properties;
-
- public Token(UserDto userDto, Map<String, Object> properties) {
- this.userDto = userDto;
- this.properties = properties;
- }
-
- public UserDto getUserDto() {
- return userDto;
- }
-
- public Map<String, Object> getProperties() {
- return properties;
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/JwtSerializer.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/JwtSerializer.java
deleted file mode 100644
index 33d5aa3d958..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/JwtSerializer.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.annotations.VisibleForTesting;
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.ExpiredJwtException;
-import io.jsonwebtoken.JwtBuilder;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.SignatureAlgorithm;
-import io.jsonwebtoken.SignatureException;
-import java.util.Base64;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Map;
-import java.util.Optional;
-import javax.annotation.concurrent.Immutable;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-import org.sonar.api.Startable;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.UuidFactory;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.authentication.event.AuthenticationException;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static io.jsonwebtoken.impl.crypto.MacProvider.generateKey;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.process.ProcessProperties.Property.AUTH_JWT_SECRET;
-
-/**
- * This class can be used to encode or decode a JWT token
- */
-@ServerSide
-public class JwtSerializer implements Startable {
-
- private static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256;
-
- private final Configuration config;
- private final System2 system2;
- private final UuidFactory uuidFactory;
-
- private SecretKey secretKey;
-
- public JwtSerializer(Configuration config, System2 system2, UuidFactory uuidFactory) {
- this.config = config;
- this.system2 = system2;
- this.uuidFactory = uuidFactory;
- }
-
- @VisibleForTesting
- SecretKey getSecretKey() {
- return secretKey;
- }
-
- @Override
- public void start() {
- Optional<String> encodedKey = config.get(AUTH_JWT_SECRET.getKey());
- if (encodedKey.isPresent()) {
- this.secretKey = decodeSecretKeyProperty(encodedKey.get());
- } else {
- this.secretKey = generateSecretKey();
- }
- }
-
- String encode(JwtSession jwtSession) {
- checkIsStarted();
- long now = system2.now();
- JwtBuilder jwtBuilder = Jwts.builder()
- .setId(uuidFactory.create())
- .setSubject(jwtSession.getUserLogin())
- .setIssuedAt(new Date(now))
- .setExpiration(new Date(now + jwtSession.getExpirationTimeInSeconds() * 1000))
- .signWith(SIGNATURE_ALGORITHM, secretKey);
- for (Map.Entry<String, Object> entry : jwtSession.getProperties().entrySet()) {
- jwtBuilder.claim(entry.getKey(), entry.getValue());
- }
- return jwtBuilder.compact();
- }
-
- Optional<Claims> decode(String token) {
- checkIsStarted();
- Claims claims = null;
- try {
- claims = Jwts.parser()
- .setSigningKey(secretKey)
- .parseClaimsJws(token)
- .getBody();
- requireNonNull(claims.getId(), "Token id hasn't been found");
- requireNonNull(claims.getSubject(), "Token subject hasn't been found");
- requireNonNull(claims.getExpiration(), "Token expiration date hasn't been found");
- requireNonNull(claims.getIssuedAt(), "Token creation date hasn't been found");
- return Optional.of(claims);
- } catch (ExpiredJwtException | SignatureException e) {
- return Optional.empty();
- } catch (Exception e) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.jwt())
- .setLogin(claims == null ? null : claims.getSubject())
- .setMessage(e.getMessage())
- .build();
- }
- }
-
- String refresh(Claims token, int expirationTimeInSeconds) {
- checkIsStarted();
- long now = system2.now();
- JwtBuilder jwtBuilder = Jwts.builder();
- for (Map.Entry<String, Object> entry : token.entrySet()) {
- jwtBuilder.claim(entry.getKey(), entry.getValue());
- }
- jwtBuilder.setExpiration(new Date(now + expirationTimeInSeconds * 1_000L))
- .signWith(SIGNATURE_ALGORITHM, secretKey);
- return jwtBuilder.compact();
- }
-
- private static SecretKey generateSecretKey() {
- return generateKey(SIGNATURE_ALGORITHM);
- }
-
- private static SecretKey decodeSecretKeyProperty(String base64SecretKey) {
- byte[] decodedKey = Base64.getDecoder().decode(base64SecretKey);
- return new SecretKeySpec(decodedKey, 0, decodedKey.length, SIGNATURE_ALGORITHM.getJcaName());
- }
-
- private void checkIsStarted() {
- checkNotNull(secretKey, "%s not started", getClass().getName());
- }
-
- @Override
- public void stop() {
- secretKey = null;
- }
-
- @Immutable
- static class JwtSession {
-
- private final String userLogin;
- private final long expirationTimeInSeconds;
- private final Map<String, Object> properties;
-
- JwtSession(String userLogin, long expirationTimeInSeconds) {
- this(userLogin, expirationTimeInSeconds, Collections.emptyMap());
- }
-
- JwtSession(String userLogin, long expirationTimeInSeconds, Map<String, Object> properties) {
- this.userLogin = requireNonNull(userLogin, "User login cannot be null");
- this.expirationTimeInSeconds = expirationTimeInSeconds;
- this.properties = properties;
- }
-
- String getUserLogin() {
- return userLogin;
- }
-
- long getExpirationTimeInSeconds() {
- return expirationTimeInSeconds;
- }
-
- Map<String, Object> getProperties() {
- return properties;
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/LogOAuthWarning.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/LogOAuthWarning.java
deleted file mode 100644
index fbc751cc034..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/LogOAuthWarning.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.Startable;
-import org.sonar.api.platform.Server;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.api.utils.log.Loggers;
-
-public class LogOAuthWarning implements Startable {
-
- private final Server server;
- private final OAuth2IdentityProvider[] providers;
-
- public LogOAuthWarning(Server server, OAuth2IdentityProvider[] providers) {
- this.server = server;
- this.providers = providers;
- }
-
- /**
- * Used by default by picocontainer when no OAuth2IdentityProvider are present
- */
- public LogOAuthWarning(Server server) {
- this(server, new OAuth2IdentityProvider[0]);
- }
-
- @Override
- public void start() {
- if (providers.length == 0) {
- return;
- }
- String publicRootUrl = server.getPublicRootUrl();
- if (StringUtils.startsWithIgnoreCase(publicRootUrl, "http:")) {
- Loggers.get(getClass()).warn(
- "For security reasons, OAuth authentication should use HTTPS. You should set the property 'Administration > Configuration > Server base URL' to a HTTPS URL.");
- }
- }
-
- @Override
- public void stop() {
- // nothing to do
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2AuthenticationParameters.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2AuthenticationParameters.java
deleted file mode 100644
index 45c314c21de..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2AuthenticationParameters.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Optional;
-import javax.servlet.FilterConfig;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-
-/**
- * This class is used to store some parameters during the OAuth2 authentication process, by using a cookie.
- *
- * Parameters are read from the request during {@link InitFilter#init(FilterConfig)}
- * and reset when {@link OAuth2IdentityProvider.CallbackContext#redirectToRequestedPage()} is called.
- */
-public interface OAuth2AuthenticationParameters {
-
- void init(HttpServletRequest request, HttpServletResponse response);
-
- Optional<String> getReturnTo(HttpServletRequest request);
-
- Optional<Boolean> getAllowEmailShift(HttpServletRequest request);
-
- Optional<Boolean> getAllowUpdateLogin(HttpServletRequest request);
-
- void delete(HttpServletRequest request, HttpServletResponse response);
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2AuthenticationParametersImpl.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2AuthenticationParametersImpl.java
deleted file mode 100644
index debc6a677f1..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2AuthenticationParametersImpl.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.base.Strings;
-import com.google.common.reflect.TypeToken;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import static java.net.URLDecoder.decode;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.Optional.empty;
-import static org.apache.commons.lang.StringUtils.isNotBlank;
-import static org.sonar.server.authentication.AuthenticationRedirection.encodeMessage;
-import static org.sonar.server.authentication.Cookies.findCookie;
-import static org.sonar.server.authentication.Cookies.newCookieBuilder;
-
-public class OAuth2AuthenticationParametersImpl implements OAuth2AuthenticationParameters {
-
- private static final String AUTHENTICATION_COOKIE_NAME = "AUTH-PARAMS";
- private static final int FIVE_MINUTES_IN_SECONDS = 5 * 60;
-
- /**
- * The HTTP parameter that contains the path where the user should be redirect to.
- * Please note that the web context is included.
- */
- private static final String RETURN_TO_PARAMETER = "return_to";
-
- /**
- * This parameter is used to allow the shift of email from an existing user to the authenticating user
- */
- private static final String ALLOW_EMAIL_SHIFT_PARAMETER = "allowEmailShift";
-
- /**
- * This parameter is used to allow the update of login
- */
- private static final String ALLOW_LOGIN_UPDATE_PARAMETER = "allowUpdateLogin";
-
- private static final Type JSON_MAP_TYPE = new TypeToken<HashMap<String, String>>() {
- }.getType();
-
- @Override
- public void init(HttpServletRequest request, HttpServletResponse response) {
- String returnTo = request.getParameter(RETURN_TO_PARAMETER);
- String allowEmailShift = request.getParameter(ALLOW_EMAIL_SHIFT_PARAMETER);
- Map<String, String> parameters = new HashMap<>();
- Optional<String> sanitizeRedirectUrl = sanitizeRedirectUrl(returnTo);
- sanitizeRedirectUrl.ifPresent(s -> parameters.put(RETURN_TO_PARAMETER, s));
- if (isNotBlank(allowEmailShift)) {
- parameters.put(ALLOW_EMAIL_SHIFT_PARAMETER, allowEmailShift);
- }
- if (parameters.isEmpty()) {
- return;
- }
- response.addCookie(newCookieBuilder(request)
- .setName(AUTHENTICATION_COOKIE_NAME)
- .setValue(toJson(parameters))
- .setHttpOnly(true)
- .setExpiry(FIVE_MINUTES_IN_SECONDS)
- .build());
- }
-
- @Override
- public Optional<String> getReturnTo(HttpServletRequest request) {
- return getParameter(request, RETURN_TO_PARAMETER);
- }
-
- @Override
- public Optional<Boolean> getAllowEmailShift(HttpServletRequest request) {
- Optional<String> parameter = getParameter(request, ALLOW_EMAIL_SHIFT_PARAMETER);
- return parameter.map(Boolean::parseBoolean);
- }
-
- @Override
- public Optional<Boolean> getAllowUpdateLogin(HttpServletRequest request) {
- Optional<String> parameter = getParameter(request, ALLOW_LOGIN_UPDATE_PARAMETER);
- return parameter.map(Boolean::parseBoolean);
- }
-
- private static Optional<String> getParameter(HttpServletRequest request, String parameterKey) {
- Optional<javax.servlet.http.Cookie> cookie = findCookie(AUTHENTICATION_COOKIE_NAME, request);
- if (!cookie.isPresent()) {
- return empty();
- }
-
- Map<String, String> parameters = fromJson(cookie.get().getValue());
- if (parameters.isEmpty()) {
- return empty();
- }
- return Optional.ofNullable(parameters.get(parameterKey));
- }
-
- @Override
- public void delete(HttpServletRequest request, HttpServletResponse response) {
- response.addCookie(newCookieBuilder(request)
- .setName(AUTHENTICATION_COOKIE_NAME)
- .setValue(null)
- .setHttpOnly(true)
- .setExpiry(0)
- .build());
- }
-
- private static String toJson(Map<String, String> map) {
- Gson gson = new GsonBuilder().create();
- return encodeMessage(gson.toJson(map));
- }
-
- private static Map<String, String> fromJson(String json) {
- Gson gson = new GsonBuilder().create();
- try {
- return gson.fromJson(decode(json, UTF_8.name()), JSON_MAP_TYPE);
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException(e);
- }
- }
-
- /**
- * This sanitization has been inspired by 'IsUrlLocalToHost()' method in
- * https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/preventing-open-redirection-attacks
- */
- private static Optional<String> sanitizeRedirectUrl(@Nullable String url) {
- if (Strings.isNullOrEmpty(url)) {
- return empty();
- }
- if (url.startsWith("//") || url.startsWith("/\\")) {
- return empty();
- }
- if (!url.startsWith("/")) {
- return empty();
- }
- return Optional.of(url);
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2CallbackContext.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2CallbackContext.java
deleted file mode 100644
index 1a0413b3fcf..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2CallbackContext.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Set;
-import javax.annotation.Nullable;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.api.server.authentication.UserIdentity;
-
-public interface OAuth2CallbackContext extends OAuth2IdentityProvider.CallbackContext {
-
- void authenticate(UserIdentity userIdentity, @Nullable Set<String> organizationAlmIds);
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2CallbackFilter.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2CallbackFilter.java
deleted file mode 100644
index eba7efbdabd..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2CallbackFilter.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.api.server.authentication.UnauthorizedException;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.authentication.exception.EmailAlreadyExistsRedirectionException;
-import org.sonar.server.user.ThreadLocalUserSession;
-
-import static java.lang.String.format;
-import static org.sonar.server.authentication.AuthenticationError.handleAuthenticationError;
-import static org.sonar.server.authentication.AuthenticationError.handleError;
-import static org.sonar.server.authentication.AuthenticationRedirection.redirectTo;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-public class OAuth2CallbackFilter extends AuthenticationFilter {
-
- private final OAuth2ContextFactory oAuth2ContextFactory;
- private final AuthenticationEvent authenticationEvent;
- private final OAuth2AuthenticationParameters oauth2Parameters;
- private final ThreadLocalUserSession threadLocalUserSession;
-
- public OAuth2CallbackFilter(IdentityProviderRepository identityProviderRepository, OAuth2ContextFactory oAuth2ContextFactory,
- AuthenticationEvent authenticationEvent, OAuth2AuthenticationParameters oauth2Parameters, ThreadLocalUserSession threadLocalUserSession) {
- super(identityProviderRepository);
- this.oAuth2ContextFactory = oAuth2ContextFactory;
- this.authenticationEvent = authenticationEvent;
- this.oauth2Parameters = oauth2Parameters;
- this.threadLocalUserSession = threadLocalUserSession;
- }
-
- @Override
- public UrlPattern doGetPattern() {
- return UrlPattern.create(CALLBACK_PATH + "*");
- }
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- HttpServletResponse httpResponse = (HttpServletResponse) response;
-
- IdentityProvider provider = resolveProviderOrHandleResponse(httpRequest, httpResponse, CALLBACK_PATH);
- if (provider != null) {
- handleProvider(httpRequest, (HttpServletResponse) response, provider);
- }
- }
-
- private void handleProvider(HttpServletRequest request, HttpServletResponse response, IdentityProvider provider) {
- try {
- if (provider instanceof OAuth2IdentityProvider) {
- handleOAuth2Provider(response, request, (OAuth2IdentityProvider) provider);
- } else {
- handleError(request, response, format("Not an OAuth2IdentityProvider: %s", provider.getClass()));
- }
- } catch (EmailAlreadyExistsRedirectionException e) {
- oauth2Parameters.delete(request, response);
- e.addCookie(request, response);
- redirectTo(response, e.getPath(request.getContextPath()));
- } catch (AuthenticationException e) {
- oauth2Parameters.delete(request, response);
- authenticationEvent.loginFailure(request, e);
- handleAuthenticationError(e, request, response);
- } catch (Exception e) {
- oauth2Parameters.delete(request, response);
- handleError(e, request, response, format("Fail to callback authentication with '%s'", provider.getKey()));
- }
- }
-
- private void handleOAuth2Provider(HttpServletResponse response, HttpServletRequest httpRequest, OAuth2IdentityProvider oAuth2Provider) {
- OAuth2IdentityProvider.CallbackContext context = oAuth2ContextFactory.newCallback(httpRequest, response, oAuth2Provider);
- try {
- oAuth2Provider.callback(context);
- } catch (UnauthorizedException e) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.oauth2(oAuth2Provider))
- .setMessage(e.getMessage())
- .setPublicMessage(e.getMessage())
- .build();
- }
- if (threadLocalUserSession.hasSession()) {
- authenticationEvent.loginSuccess(httpRequest, threadLocalUserSession.getLogin(), Source.oauth2(oAuth2Provider));
- } else {
- throw AuthenticationException.newBuilder()
- .setSource(Source.oauth2(oAuth2Provider))
- .setMessage("Plugin did not call authenticate")
- .build();
- }
- }
-
- @Override
- public void init(FilterConfig filterConfig) {
- // Nothing to do
- }
-
- @Override
- public void destroy() {
- // Nothing to do
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2ContextFactory.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2ContextFactory.java
deleted file mode 100644
index 6d9b3810a1b..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2ContextFactory.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.io.IOException;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.platform.Server;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.user.ThreadLocalUserSession;
-import org.sonar.server.user.UserSessionFactory;
-
-import static java.lang.String.format;
-import static org.sonar.server.authentication.OAuth2CallbackFilter.CALLBACK_PATH;
-
-@ServerSide
-public class OAuth2ContextFactory {
-
- private final ThreadLocalUserSession threadLocalUserSession;
- private final UserRegistrar userRegistrar;
- private final Server server;
- private final OAuthCsrfVerifier csrfVerifier;
- private final JwtHttpHandler jwtHttpHandler;
- private final UserSessionFactory userSessionFactory;
- private final OAuth2AuthenticationParameters oAuthParameters;
-
- public OAuth2ContextFactory(ThreadLocalUserSession threadLocalUserSession, UserRegistrar userRegistrar, Server server,
- OAuthCsrfVerifier csrfVerifier, JwtHttpHandler jwtHttpHandler, UserSessionFactory userSessionFactory, OAuth2AuthenticationParameters oAuthParameters) {
- this.threadLocalUserSession = threadLocalUserSession;
- this.userRegistrar = userRegistrar;
- this.server = server;
- this.csrfVerifier = csrfVerifier;
- this.jwtHttpHandler = jwtHttpHandler;
- this.userSessionFactory = userSessionFactory;
- this.oAuthParameters = oAuthParameters;
- }
-
- public OAuth2IdentityProvider.InitContext newContext(HttpServletRequest request, HttpServletResponse response, OAuth2IdentityProvider identityProvider) {
- return new OAuthContextImpl(request, response, identityProvider);
- }
-
- public OAuth2IdentityProvider.CallbackContext newCallback(HttpServletRequest request, HttpServletResponse response, OAuth2IdentityProvider identityProvider) {
- return new OAuthContextImpl(request, response, identityProvider);
- }
-
- public class OAuthContextImpl implements OAuth2IdentityProvider.InitContext, OAuth2CallbackContext {
-
- private final HttpServletRequest request;
- private final HttpServletResponse response;
- private final OAuth2IdentityProvider identityProvider;
-
- public OAuthContextImpl(HttpServletRequest request, HttpServletResponse response, OAuth2IdentityProvider identityProvider) {
- this.request = request;
- this.response = response;
- this.identityProvider = identityProvider;
- }
-
- @Override
- public String getCallbackUrl() {
- return server.getPublicRootUrl() + CALLBACK_PATH + identityProvider.getKey();
- }
-
- @Override
- public String generateCsrfState() {
- return csrfVerifier.generateState(request, response);
- }
-
- @Override
- public HttpServletRequest getRequest() {
- return request;
- }
-
- @Override
- public HttpServletResponse getResponse() {
- return response;
- }
-
- @Override
- public void redirectTo(String url) {
- try {
- response.sendRedirect(url);
- } catch (IOException e) {
- throw new IllegalStateException(format("Fail to redirect to %s", url), e);
- }
- }
-
- @Override
- public void verifyCsrfState() {
- csrfVerifier.verifyState(request, response, identityProvider);
- }
-
- @Override
- public void verifyCsrfState(String parameterName) {
- csrfVerifier.verifyState(request, response, identityProvider, parameterName);
- }
-
- @Override
- public void redirectToRequestedPage() {
- try {
- Optional<String> redirectTo = oAuthParameters.getReturnTo(request);
- oAuthParameters.delete(request, response);
- getResponse().sendRedirect(redirectTo.orElse(server.getContextPath() + "/"));
- } catch (IOException e) {
- throw new IllegalStateException("Fail to redirect to requested page", e);
- }
- }
-
- @Override
- public void authenticate(UserIdentity userIdentity) {
- authenticate(userIdentity, null);
- }
-
- @Override
- public void authenticate(UserIdentity userIdentity, @Nullable Set<String> organizationAlmIds) {
- Boolean allowEmailShift = oAuthParameters.getAllowEmailShift(request).orElse(false);
- UserDto userDto = userRegistrar.register(
- UserRegistration.builder()
- .setUserIdentity(userIdentity)
- .setProvider(identityProvider)
- .setSource(AuthenticationEvent.Source.oauth2(identityProvider))
- .setExistingEmailStrategy(allowEmailShift ? ExistingEmailStrategy.ALLOW : ExistingEmailStrategy.WARN)
- .setOrganizationAlmIds(organizationAlmIds)
- .build());
- jwtHttpHandler.generateToken(userDto, request, response);
- threadLocalUserSession.set(userSessionFactory.create(userDto));
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuthCsrfVerifier.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuthCsrfVerifier.java
deleted file mode 100644
index 0f6c17fc49c..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/OAuthCsrfVerifier.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.server.authentication.event.AuthenticationException;
-
-import static java.lang.String.format;
-import static org.apache.commons.codec.digest.DigestUtils.sha256Hex;
-import static org.apache.commons.lang.StringUtils.isBlank;
-import static org.sonar.server.authentication.Cookies.findCookie;
-import static org.sonar.server.authentication.Cookies.newCookieBuilder;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-public class OAuthCsrfVerifier {
-
- private static final String CSRF_STATE_COOKIE = "OAUTHSTATE";
- private static final String DEFAULT_STATE_PARAMETER_NAME = "state";
-
- public String generateState(HttpServletRequest request, HttpServletResponse response) {
- // Create a state token to prevent request forgery.
- // Store it in the session for later validation.
- String state = new BigInteger(130, new SecureRandom()).toString(32);
- response.addCookie(newCookieBuilder(request).setName(CSRF_STATE_COOKIE).setValue(sha256Hex(state)).setHttpOnly(true).setExpiry(-1).build());
- return state;
- }
-
- public void verifyState(HttpServletRequest request, HttpServletResponse response, OAuth2IdentityProvider provider) {
- verifyState(request, response, provider, DEFAULT_STATE_PARAMETER_NAME);
- }
-
- public void verifyState(HttpServletRequest request, HttpServletResponse response, OAuth2IdentityProvider provider, String parameterName) {
- Cookie cookie = findCookie(CSRF_STATE_COOKIE, request)
- .orElseThrow(AuthenticationException.newBuilder()
- .setSource(Source.oauth2(provider))
- .setMessage(format("Cookie '%s' is missing", CSRF_STATE_COOKIE))::build);
- String hashInCookie = cookie.getValue();
-
- // remove cookie
- response.addCookie(newCookieBuilder(request).setName(CSRF_STATE_COOKIE).setValue(null).setHttpOnly(true).setExpiry(0).build());
-
- String stateInRequest = request.getParameter(parameterName);
- if (isBlank(stateInRequest) || !sha256Hex(stateInRequest).equals(hashInCookie)) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.oauth2(provider))
- .setMessage("CSRF state value is invalid")
- .build();
- }
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/RequestAuthenticator.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/RequestAuthenticator.java
deleted file mode 100644
index 48c4b269bb2..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/RequestAuthenticator.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.server.ServerSide;
-import org.sonar.server.user.UserSession;
-
-@ServerSide
-public interface RequestAuthenticator {
-
- /**
- * @throws org.sonar.server.authentication.event.AuthenticationException if user is not authenticated
- */
- UserSession authenticate(HttpServletRequest request, HttpServletResponse response);
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/RequestAuthenticatorImpl.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/RequestAuthenticatorImpl.java
deleted file mode 100644
index 0d5643cc5b9..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/RequestAuthenticatorImpl.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.user.UserSession;
-import org.sonar.server.user.UserSessionFactory;
-
-public class RequestAuthenticatorImpl implements RequestAuthenticator {
-
- private final JwtHttpHandler jwtHttpHandler;
- private final BasicAuthentication basicAuthentication;
- private final HttpHeadersAuthentication httpHeadersAuthentication;
- private final UserSessionFactory userSessionFactory;
- private final List<CustomAuthentication> customAuthentications;
-
- public RequestAuthenticatorImpl(JwtHttpHandler jwtHttpHandler, BasicAuthentication basicAuthentication, HttpHeadersAuthentication httpHeadersAuthentication,
- UserSessionFactory userSessionFactory, CustomAuthentication[] customAuthentications) {
- this.jwtHttpHandler = jwtHttpHandler;
- this.basicAuthentication = basicAuthentication;
- this.httpHeadersAuthentication = httpHeadersAuthentication;
- this.userSessionFactory = userSessionFactory;
- this.customAuthentications = Arrays.asList(customAuthentications);
- }
-
- public RequestAuthenticatorImpl(JwtHttpHandler jwtHttpHandler, BasicAuthentication basicAuthentication, HttpHeadersAuthentication httpHeadersAuthentication,
- UserSessionFactory userSessionFactory) {
- this(jwtHttpHandler, basicAuthentication, httpHeadersAuthentication, userSessionFactory, new CustomAuthentication[0]);
- }
-
- @Override
- public UserSession authenticate(HttpServletRequest request, HttpServletResponse response) {
- for (CustomAuthentication customAuthentication : customAuthentications) {
- Optional<UserSession> session = customAuthentication.authenticate(request, response);
- if (session.isPresent()) {
- return session.get();
- }
- }
-
- Optional<UserDto> userOpt = loadUser(request, response);
- if (userOpt.isPresent()) {
- return userSessionFactory.create(userOpt.get());
- }
- return userSessionFactory.createAnonymous();
- }
-
- private Optional<UserDto> loadUser(HttpServletRequest request, HttpServletResponse response) {
- // Try first to authenticate from SSO, then JWT token, then try from basic http header
-
- // SSO authentication should come first in order to update JWT if user from header is not the same is user from JWT
- Optional<UserDto> user = httpHeadersAuthentication.authenticate(request, response);
- if (user.isPresent()) {
- return user;
- }
- user = jwtHttpHandler.validateToken(request, response);
- if (user.isPresent()) {
- return user;
- }
- return basicAuthentication.authenticate(request);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/SafeModeUserSession.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/SafeModeUserSession.java
deleted file mode 100644
index 85828432ad1..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/SafeModeUserSession.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Optional;
-import javax.annotation.CheckForNull;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.user.GroupDto;
-import org.sonar.server.user.AbstractUserSession;
-
-@Immutable
-public class SafeModeUserSession extends AbstractUserSession {
-
- @Override
- protected boolean hasPermissionImpl(OrganizationPermission permission, String organizationUuid) {
- return false;
- }
-
- @Override
- protected Optional<String> componentUuidToProjectUuid(String componentUuid) {
- return Optional.empty();
- }
-
- @Override
- protected boolean hasProjectUuidPermission(String permission, String projectUuid) {
- return false;
- }
-
- @Override
- protected boolean hasMembershipImpl(OrganizationDto organizationDto) {
- return false;
- }
-
- @CheckForNull
- @Override
- public String getLogin() {
- return null;
- }
-
- @CheckForNull
- @Override
- public String getUuid() {
- return null;
- }
-
- @CheckForNull
- @Override
- public String getName() {
- return null;
- }
-
- @CheckForNull
- @Override
- public Integer getUserId() {
- return null;
- }
-
- @Override
- public Collection<GroupDto> getGroups() {
- return Collections.emptyList();
- }
-
- @Override
- public Optional<IdentityProvider> getIdentityProvider() {
- return Optional.empty();
- }
-
- @Override
- public Optional<ExternalIdentity> getExternalIdentity() {
- return Optional.empty();
- }
-
- @Override
- public boolean isLoggedIn() {
- return false;
- }
-
- @Override
- public boolean isRoot() {
- return false;
- }
-
- @Override
- public boolean isSystemAdministrator() {
- return false;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserLastConnectionDatesUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/UserLastConnectionDatesUpdater.java
deleted file mode 100644
index aa55e9e1adb..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserLastConnectionDatesUpdater.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.authentication;
-
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTokenDto;
-
-public interface UserLastConnectionDatesUpdater {
-
- void updateLastConnectionDateIfNeeded(UserDto user);
-
- void updateLastConnectionDateIfNeeded(UserTokenDto userToken);
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserLastConnectionDatesUpdaterImpl.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/UserLastConnectionDatesUpdaterImpl.java
deleted file mode 100644
index 87326e6c236..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserLastConnectionDatesUpdaterImpl.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.authentication;
-
-import javax.annotation.Nullable;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTokenDto;
-
-public class UserLastConnectionDatesUpdaterImpl implements UserLastConnectionDatesUpdater {
-
- private static final long ONE_HOUR_IN_MILLISECONDS = 60 * 60 * 1000L;
-
- private final DbClient dbClient;
- private final System2 system2;
-
- public UserLastConnectionDatesUpdaterImpl(DbClient dbClient, System2 system2) {
- this.dbClient = dbClient;
- this.system2 = system2;
- }
-
- @Override
- public void updateLastConnectionDateIfNeeded(UserDto user) {
- Long lastConnectionDate = user.getLastConnectionDate();
- long now = system2.now();
- if (doesNotRequireUpdate(lastConnectionDate, now)) {
- return;
- }
- try (DbSession dbSession = dbClient.openSession(false)) {
- dbClient.userDao().update(dbSession, user.setLastConnectionDate(now));
- dbSession.commit();
- }
- }
-
- @Override
- public void updateLastConnectionDateIfNeeded(UserTokenDto userToken) {
- Long lastConnectionDate = userToken.getLastConnectionDate();
- long now = system2.now();
- if (doesNotRequireUpdate(lastConnectionDate, now)) {
- return;
- }
- try (DbSession dbSession = dbClient.openSession(false)) {
- dbClient.userTokenDao().update(dbSession, userToken.setLastConnectionDate(now));
- userToken.setLastConnectionDate(now);
- dbSession.commit();
- }
- }
-
- private static boolean doesNotRequireUpdate(@Nullable Long lastConnectionDate, long now) {
- // Update date only once per hour in order to decrease pressure on DB
- return lastConnectionDate != null && (now - lastConnectionDate) < ONE_HOUR_IN_MILLISECONDS;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistrar.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistrar.java
deleted file mode 100644
index e398d2249b2..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistrar.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.sonar.db.user.UserDto;
-
-public interface UserRegistrar {
-
- UserDto register(UserRegistration registration);
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistrarImpl.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistrarImpl.java
deleted file mode 100644
index 6f408e3c7fc..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistrarImpl.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.collect.Sets;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Consumer;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.alm.ALM;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserGroupDto;
-import org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.authentication.exception.EmailAlreadyExistsRedirectionException;
-import org.sonar.server.organization.DefaultOrganization;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.organization.MemberUpdater;
-import org.sonar.server.organization.OrganizationFlags;
-import org.sonar.server.user.ExternalIdentity;
-import org.sonar.server.user.NewUser;
-import org.sonar.server.user.UpdateUser;
-import org.sonar.server.user.UserSession;
-import org.sonar.server.user.UserUpdater;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static java.lang.String.format;
-import static java.util.Collections.singletonList;
-import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
-
-public class UserRegistrarImpl implements UserRegistrar {
-
- private static final Logger LOGGER = Loggers.get(UserRegistrarImpl.class);
-
- private final DbClient dbClient;
- private final UserUpdater userUpdater;
- private final DefaultOrganizationProvider defaultOrganizationProvider;
- private final OrganizationFlags organizationFlags;
- private final DefaultGroupFinder defaultGroupFinder;
- private final MemberUpdater memberUpdater;
-
- public UserRegistrarImpl(DbClient dbClient, UserUpdater userUpdater, DefaultOrganizationProvider defaultOrganizationProvider, OrganizationFlags organizationFlags,
- DefaultGroupFinder defaultGroupFinder, MemberUpdater memberUpdater) {
- this.dbClient = dbClient;
- this.userUpdater = userUpdater;
- this.defaultOrganizationProvider = defaultOrganizationProvider;
- this.organizationFlags = organizationFlags;
- this.defaultGroupFinder = defaultGroupFinder;
- this.memberUpdater = memberUpdater;
- }
-
- @Override
- public UserDto register(UserRegistration registration) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- UserDto userDto = getUser(dbSession, registration.getUserIdentity(), registration.getProvider());
- if (userDto == null) {
- return registerNewUser(dbSession, null, registration);
- }
- if (!userDto.isActive()) {
- return registerNewUser(dbSession, userDto, registration);
- }
- return registerExistingUser(dbSession, userDto, registration);
- }
- }
-
- @CheckForNull
- private UserDto getUser(DbSession dbSession, UserIdentity userIdentity, IdentityProvider provider) {
- // First, try to authenticate using the external ID
- UserDto user = dbClient.userDao().selectByExternalIdAndIdentityProvider(dbSession, getProviderIdOrProviderLogin(userIdentity), provider.getKey());
- if (user != null) {
- return user;
- }
- // Then, try with the external login, for instance when external ID has changed
- user = dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, userIdentity.getProviderLogin(), provider.getKey());
- if (user != null) {
- return user;
- }
- // Last, try with login, for instance when external ID and external login has been updated
- String login = userIdentity.getLogin();
- if (login == null) {
- return null;
- }
- return dbClient.userDao().selectByLogin(dbSession, login);
- }
-
- private UserDto registerNewUser(DbSession dbSession, @Nullable UserDto disabledUser, UserRegistration authenticatorParameters) {
- Optional<UserDto> otherUserToIndex = detectEmailUpdate(dbSession, authenticatorParameters);
- NewUser newUser = createNewUser(authenticatorParameters);
- if (disabledUser == null) {
- return userUpdater.createAndCommit(dbSession, newUser, beforeCommit(dbSession, true, authenticatorParameters), toArray(otherUserToIndex));
- }
- return userUpdater.reactivateAndCommit(dbSession, disabledUser, newUser, beforeCommit(dbSession, true, authenticatorParameters), toArray(otherUserToIndex));
- }
-
- private UserDto registerExistingUser(DbSession dbSession, UserDto userDto, UserRegistration authenticatorParameters) {
- UpdateUser update = new UpdateUser()
- .setEmail(authenticatorParameters.getUserIdentity().getEmail())
- .setName(authenticatorParameters.getUserIdentity().getName())
- .setExternalIdentity(new ExternalIdentity(
- authenticatorParameters.getProvider().getKey(),
- authenticatorParameters.getUserIdentity().getProviderLogin(),
- authenticatorParameters.getUserIdentity().getProviderId()));
- String login = authenticatorParameters.getUserIdentity().getLogin();
- if (login != null) {
- update.setLogin(login);
- }
- Optional<UserDto> otherUserToIndex = detectEmailUpdate(dbSession, authenticatorParameters);
- userUpdater.updateAndCommit(dbSession, userDto, update, beforeCommit(dbSession, false, authenticatorParameters), toArray(otherUserToIndex));
- return userDto;
- }
-
- private Consumer<UserDto> beforeCommit(DbSession dbSession, boolean isNewUser, UserRegistration authenticatorParameters) {
- return user -> {
- syncGroups(dbSession, authenticatorParameters.getUserIdentity(), user);
- synchronizeOrganizationMembership(dbSession, user, authenticatorParameters, isNewUser);
- };
- }
-
- private Optional<UserDto> detectEmailUpdate(DbSession dbSession, UserRegistration authenticatorParameters) {
- String email = authenticatorParameters.getUserIdentity().getEmail();
- if (email == null) {
- return Optional.empty();
- }
- List<UserDto> existingUsers = dbClient.userDao().selectByEmail(dbSession, email);
- if (existingUsers.isEmpty()) {
- return Optional.empty();
- }
- if (existingUsers.size() > 1) {
- throw generateExistingEmailError(authenticatorParameters, email);
- }
-
- UserDto existingUser = existingUsers.get(0);
- if (existingUser == null || isSameUser(existingUser, authenticatorParameters)) {
- return Optional.empty();
- }
- ExistingEmailStrategy existingEmailStrategy = authenticatorParameters.getExistingEmailStrategy();
- switch (existingEmailStrategy) {
- case ALLOW:
- existingUser.setEmail(null);
- dbClient.userDao().update(dbSession, existingUser);
- return Optional.of(existingUser);
- case WARN:
- throw new EmailAlreadyExistsRedirectionException(email, existingUser, authenticatorParameters.getUserIdentity(), authenticatorParameters.getProvider());
- case FORBID:
- throw generateExistingEmailError(authenticatorParameters, email);
- default:
- throw new IllegalStateException(format("Unknown strategy %s", existingEmailStrategy));
- }
- }
-
- private static boolean isSameUser(UserDto existingUser, UserRegistration authenticatorParameters) {
- // Check if same login
- return Objects.equals(existingUser.getLogin(), authenticatorParameters.getUserIdentity().getLogin()) ||
- // Check if same identity provider and same provider id or provider login
- (Objects.equals(existingUser.getExternalIdentityProvider(), authenticatorParameters.getProvider().getKey()) &&
- (Objects.equals(existingUser.getExternalId(), getProviderIdOrProviderLogin(authenticatorParameters.getUserIdentity()))
- || Objects.equals(existingUser.getExternalLogin(), authenticatorParameters.getUserIdentity().getProviderLogin())));
- }
-
- private void syncGroups(DbSession dbSession, UserIdentity userIdentity, UserDto userDto) {
- if (!userIdentity.shouldSyncGroups()) {
- return;
- }
- String userLogin = userDto.getLogin();
- Set<String> userGroups = new HashSet<>(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(userLogin)).get(userLogin));
- Set<String> identityGroups = userIdentity.getGroups();
- LOGGER.debug("List of groups returned by the identity provider '{}'", identityGroups);
-
- Collection<String> groupsToAdd = Sets.difference(identityGroups, userGroups);
- Collection<String> groupsToRemove = Sets.difference(userGroups, identityGroups);
- Collection<String> allGroups = new ArrayList<>(groupsToAdd);
- allGroups.addAll(groupsToRemove);
- DefaultOrganization defaultOrganization = defaultOrganizationProvider.get();
- Map<String, GroupDto> groupsByName = dbClient.groupDao().selectByNames(dbSession, defaultOrganization.getUuid(), allGroups)
- .stream()
- .collect(uniqueIndex(GroupDto::getName));
-
- addGroups(dbSession, userDto, groupsToAdd, groupsByName);
- removeGroups(dbSession, userDto, groupsToRemove, groupsByName);
- }
-
- private void addGroups(DbSession dbSession, UserDto userDto, Collection<String> groupsToAdd, Map<String, GroupDto> groupsByName) {
- groupsToAdd.stream().map(groupsByName::get).filter(Objects::nonNull).forEach(
- groupDto -> {
- LOGGER.debug("Adding group '{}' to user '{}'", groupDto.getName(), userDto.getLogin());
- dbClient.userGroupDao().insert(dbSession, new UserGroupDto().setGroupId(groupDto.getId()).setUserId(userDto.getId()));
- });
- }
-
- private void removeGroups(DbSession dbSession, UserDto userDto, Collection<String> groupsToRemove, Map<String, GroupDto> groupsByName) {
- Optional<GroupDto> defaultGroup = getDefaultGroup(dbSession);
- groupsToRemove.stream().map(groupsByName::get)
- .filter(Objects::nonNull)
- // user should be member of default group only when organizations are disabled, as the IdentityProvider API doesn't handle yet
- // organizations
- .filter(group -> !defaultGroup.isPresent() || !group.getId().equals(defaultGroup.get().getId()))
- .forEach(groupDto -> {
- LOGGER.debug("Removing group '{}' from user '{}'", groupDto.getName(), userDto.getLogin());
- dbClient.userGroupDao().delete(dbSession, groupDto.getId(), userDto.getId());
- });
- }
-
- private Optional<GroupDto> getDefaultGroup(DbSession dbSession) {
- return organizationFlags.isEnabled(dbSession) ? Optional.empty() : Optional.of(defaultGroupFinder.findDefaultGroup(dbSession, defaultOrganizationProvider.get().getUuid()));
- }
-
- private void synchronizeOrganizationMembership(DbSession dbSession, UserDto userDto, UserRegistration authenticatorParameters, boolean isNewUser) {
- Set<String> almOrganizationIds = authenticatorParameters.getOrganizationAlmIds();
- if (almOrganizationIds == null || !isNewUser || !organizationFlags.isEnabled(dbSession)) {
- return;
- }
- UserSession.IdentityProvider identityProvider = UserSession.IdentityProvider.getFromKey(authenticatorParameters.getProvider().getKey());
- if (identityProvider != UserSession.IdentityProvider.GITHUB) {
- return;
- }
- memberUpdater.synchronizeUserOrganizationMembership(dbSession, userDto, ALM.GITHUB, almOrganizationIds);
- }
-
- private static NewUser createNewUser(UserRegistration authenticatorParameters) {
- String identityProviderKey = authenticatorParameters.getProvider().getKey();
- if (!authenticatorParameters.getProvider().allowsUsersToSignUp()) {
- throw AuthenticationException.newBuilder()
- .setSource(authenticatorParameters.getSource())
- .setLogin(authenticatorParameters.getUserIdentity().getProviderLogin())
- .setMessage(format("User signup disabled for provider '%s'", identityProviderKey))
- .setPublicMessage(format("'%s' users are not allowed to sign up", identityProviderKey))
- .build();
- }
- return NewUser.builder()
- .setLogin(authenticatorParameters.getUserIdentity().getLogin())
- .setEmail(authenticatorParameters.getUserIdentity().getEmail())
- .setName(authenticatorParameters.getUserIdentity().getName())
- .setExternalIdentity(
- new ExternalIdentity(
- identityProviderKey,
- authenticatorParameters.getUserIdentity().getProviderLogin(),
- authenticatorParameters.getUserIdentity().getProviderId()))
- .build();
- }
-
- private static UserDto[] toArray(Optional<UserDto> userDto) {
- return userDto.map(u -> new UserDto[] {u}).orElse(new UserDto[] {});
- }
-
- private static AuthenticationException generateExistingEmailError(UserRegistration authenticatorParameters, String email) {
- return AuthenticationException.newBuilder()
- .setSource(authenticatorParameters.getSource())
- .setLogin(authenticatorParameters.getUserIdentity().getProviderLogin())
- .setMessage(format("Email '%s' is already used", email))
- .setPublicMessage(format(
- "You can't sign up because email '%s' is already used by an existing user. This means that you probably already registered with another account.",
- email))
- .build();
- }
-
- private static String getProviderIdOrProviderLogin(UserIdentity userIdentity) {
- String providerId = userIdentity.getProviderId();
- return providerId == null ? userIdentity.getProviderLogin() : providerId;
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistration.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistration.java
deleted file mode 100644
index fc6dc4a8d4d..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserRegistration.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-
-import static java.util.Objects.requireNonNull;
-
-class UserRegistration {
-
- /**
- * Strategy to be executed when the email of the user is already used by another user
- */
- enum ExistingEmailStrategy {
- /**
- * Authentication is allowed, the email is moved from other user to current user
- */
- ALLOW,
- /**
- * Authentication process is stopped, the user is redirected to a page explaining that the email is already used
- */
- WARN,
- /**
- * Forbid authentication of the user
- */
- FORBID
- }
-
- private final UserIdentity userIdentity;
- private final IdentityProvider provider;
- private final AuthenticationEvent.Source source;
- private final ExistingEmailStrategy existingEmailStrategy;
- private final Set<String> organizationAlmIds;
-
- UserRegistration(Builder builder) {
- this.userIdentity = builder.userIdentity;
- this.provider = builder.provider;
- this.source = builder.source;
- this.existingEmailStrategy = builder.existingEmailStrategy;
- this.organizationAlmIds = builder.organizationAlmIds;
- }
-
- public UserIdentity getUserIdentity() {
- return userIdentity;
- }
-
- public IdentityProvider getProvider() {
- return provider;
- }
-
- public AuthenticationEvent.Source getSource() {
- return source;
- }
-
- public ExistingEmailStrategy getExistingEmailStrategy() {
- return existingEmailStrategy;
- }
-
- @CheckForNull
- public Set<String> getOrganizationAlmIds() {
- return organizationAlmIds;
- }
-
- static UserRegistration.Builder builder() {
- return new Builder();
- }
-
- public static class Builder {
- private UserIdentity userIdentity;
- private IdentityProvider provider;
- private AuthenticationEvent.Source source;
- private ExistingEmailStrategy existingEmailStrategy;
- private Set<String> organizationAlmIds;
-
- public Builder setUserIdentity(UserIdentity userIdentity) {
- this.userIdentity = userIdentity;
- return this;
- }
-
- public Builder setProvider(IdentityProvider provider) {
- this.provider = provider;
- return this;
- }
-
- public Builder setSource(AuthenticationEvent.Source source) {
- this.source = source;
- return this;
- }
-
- /**
- * Strategy to be executed when the email of the user is already used by another user
- */
- public Builder setExistingEmailStrategy(ExistingEmailStrategy existingEmailStrategy) {
- this.existingEmailStrategy = existingEmailStrategy;
- return this;
- }
-
- /**
- * List of ALM organization the user is member of.
- * When set to null, it means that no organization membership synchronization should be done.
- */
- public Builder setOrganizationAlmIds(@Nullable Set<String> organizationAlmIds) {
- this.organizationAlmIds = organizationAlmIds;
- return this;
- }
-
- public UserRegistration build() {
- requireNonNull(userIdentity, "userIdentity must be set");
- requireNonNull(provider, "identityProvider must be set");
- requireNonNull(source, "Source must be set");
- requireNonNull(existingEmailStrategy, "existingEmailStrategy must be set ");
- return new UserRegistration(this);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java
deleted file mode 100644
index 4f28a4cad4e..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.collect.ImmutableSet;
-import java.util.Set;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.web.ServletFilter.UrlPattern;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.user.ThreadLocalUserSession;
-import org.sonar.server.user.UserSession;
-
-import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
-import static org.apache.commons.lang.StringUtils.defaultString;
-import static org.sonar.api.CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY;
-import static org.sonar.api.web.ServletFilter.UrlPattern.Builder.staticResourcePatterns;
-import static org.sonar.server.authentication.AuthenticationError.handleAuthenticationError;
-
-@ServerSide
-public class UserSessionInitializer {
-
- /**
- * Key of attribute to be used for displaying user login
- * in logs/access.log. The pattern to be configured
- * in property sonar.web.accessLogs.pattern is "%reqAttribute{LOGIN}"
- */
- private static final String ACCESS_LOG_LOGIN = "LOGIN";
-
- // SONAR-6546 these urls should be get from WebService
- private static final Set<String> SKIPPED_URLS = ImmutableSet.of(
- "/batch/index", "/batch/file",
- "/maintenance/*", "/setup/*",
- "/sessions/*", "/oauth2/callback/*",
- "/api/system/db_migration_status", "/api/system/status", "/api/system/migrate_db",
- "/api/server/version",
- "/api/users/identity_providers", "/api/l10n/index",
- "/api/authentication/login", "/api/authentication/logout", "/api/authentication/validate");
-
- private static final Set<String> URL_USING_PASSCODE = ImmutableSet.of(
- "/api/ce/info", "/api/ce/pause", "/api/ce/resume", "/api/system/health", "/api/system/analytics", "/api/system/migrate_es");
-
- private static final UrlPattern URL_PATTERN = UrlPattern.builder()
- .includes("/*")
- .excludes(staticResourcePatterns())
- .excludes(SKIPPED_URLS)
- .build();
-
- private static final UrlPattern PASSCODE_URLS = UrlPattern.builder()
- .includes(URL_USING_PASSCODE)
- .build();
-
- private final Configuration config;
- private final ThreadLocalUserSession threadLocalSession;
- private final AuthenticationEvent authenticationEvent;
- private final RequestAuthenticator requestAuthenticator;
-
- public UserSessionInitializer(Configuration config, ThreadLocalUserSession threadLocalSession, AuthenticationEvent authenticationEvent,
- RequestAuthenticator requestAuthenticator) {
- this.config = config;
- this.threadLocalSession = threadLocalSession;
- this.authenticationEvent = authenticationEvent;
- this.requestAuthenticator = requestAuthenticator;
- }
-
- public boolean initUserSession(HttpServletRequest request, HttpServletResponse response) {
- String path = request.getRequestURI().replaceFirst(request.getContextPath(), "");
- try {
- // Do not set user session when url is excluded
- if (URL_PATTERN.matches(path)) {
- loadUserSession(request, response, PASSCODE_URLS.matches(path));
- }
- return true;
- } catch (AuthenticationException e) {
- authenticationEvent.loginFailure(request, e);
- if (isWsUrl(path)) {
- response.setStatus(HTTP_UNAUTHORIZED);
- return false;
- }
- if (isNotLocalOrJwt(e.getSource())) {
- // redirect to Unauthorized error page
- handleAuthenticationError(e, request, response);
- return false;
- }
- // Web pages should redirect to the index.html file
- return true;
- }
- }
-
- private static boolean isNotLocalOrJwt(Source source) {
- AuthenticationEvent.Provider provider = source.getProvider();
- return provider != AuthenticationEvent.Provider.LOCAL && provider != AuthenticationEvent.Provider.JWT;
- }
-
- private void loadUserSession(HttpServletRequest request, HttpServletResponse response, boolean urlSupportsSystemPasscode) {
- UserSession session = requestAuthenticator.authenticate(request, response);
- if (!session.isLoggedIn() && !urlSupportsSystemPasscode && config.getBoolean(CORE_FORCE_AUTHENTICATION_PROPERTY).orElse(false)) {
- // authentication is required
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(AuthenticationEvent.Method.BASIC))
- .setMessage("User must be authenticated")
- .build();
- }
- threadLocalSession.set(session);
- request.setAttribute(ACCESS_LOG_LOGIN, defaultString(session.getLogin(), "-"));
- }
-
- public void removeUserSession() {
- threadLocalSession.unload();
- }
-
- private static boolean isWsUrl(String path) {
- return path.startsWith("/batch/") || path.startsWith("/api/");
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEvent.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEvent.java
deleted file mode 100644
index 0e61085c6cc..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEvent.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication.event;
-
-import java.io.Serializable;
-import java.util.Objects;
-import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
-import org.sonar.api.server.authentication.BaseIdentityProvider;
-import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.requireNonNull;
-
-public interface AuthenticationEvent {
-
- void loginSuccess(HttpServletRequest request, @Nullable String login, Source source);
-
- void loginFailure(HttpServletRequest request, AuthenticationException e);
-
- void logoutSuccess(HttpServletRequest request, @Nullable String login);
-
- void logoutFailure(HttpServletRequest request, String errorMessage);
-
- enum Method {
- /**
- * HTTP basic authentication with a login and password.
- */
- BASIC,
- /**
- * HTTP basic authentication with a security token.
- */
- BASIC_TOKEN,
- /**
- * SQ login form authentication with a login and password.
- */
- FORM,
- /**
- * SSO authentication (ie. with HTTP headers)
- */
- SSO,
- /**
- * OAUTH2 authentication.
- */
- OAUTH2,
- /**
- * JWT authentication (ie. with a session token).
- */
- JWT,
- /**
- * External authentication (ie. fully implemented out of SQ's core code, see {@link BaseIdentityProvider}).
- */
- EXTERNAL
- }
-
- enum Provider {
- /**
- * User authentication made against data in SQ's User table.
- */
- LOCAL,
- /**
- * User authentication made by SSO provider.
- */
- SSO,
- /**
- * User authentication made by Realm based provider (eg. LDAP).
- */
- REALM,
- /**
- * User authentication made by JWT token information.
- */
- JWT,
- /**
- * User authentication made by external provider (see {@link BaseIdentityProvider}).
- */
- EXTERNAL
- }
-
- final class Source implements Serializable {
- private static final String LOCAL_PROVIDER_NAME = "local";
- private static final Source SSO_INSTANCE = new Source(Method.SSO, Provider.SSO, "sso");
- private static final Source JWT_INSTANCE = new Source(Method.JWT, Provider.JWT, "jwt");
-
- private final Method method;
- private final Provider provider;
- private final String providerName;
-
- private Source(Method method, Provider provider, String providerName) {
- this.method = requireNonNull(method, "method can't be null");
- this.provider = requireNonNull(provider, "provider can't be null");
- this.providerName = requireNonNull(providerName, "provider name can't be null");
- checkArgument(!providerName.isEmpty(), "provider name can't be empty");
- }
-
- public static Source local(Method method) {
- return new Source(method, Provider.LOCAL, LOCAL_PROVIDER_NAME);
- }
-
- public static Source oauth2(OAuth2IdentityProvider identityProvider) {
- return new Source(
- Method.OAUTH2, Provider.EXTERNAL,
- requireNonNull(identityProvider, "identityProvider can't be null").getName());
- }
-
- public static Source realm(Method method, String providerName) {
- return new Source(method, Provider.REALM, providerName);
- }
-
- public static Source sso() {
- return SSO_INSTANCE;
- }
-
- public static Source jwt() {
- return JWT_INSTANCE;
- }
-
- public static Source external(IdentityProvider identityProvider) {
- return new Source(
- Method.EXTERNAL, Provider.EXTERNAL,
- requireNonNull(identityProvider, "identityProvider can't be null").getName());
- }
-
- public Method getMethod() {
- return method;
- }
-
- public Provider getProvider() {
- return provider;
- }
-
- public String getProviderName() {
- return providerName;
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- Source source = (Source) o;
- return method == source.method &&
- provider == source.provider &&
- providerName.equals(source.providerName);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(method, provider, providerName);
- }
-
- @Override
- public String toString() {
- return "Source{" +
- "method=" + method +
- ", provider=" + provider +
- ", providerName='" + providerName + '\'' +
- '}';
- }
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEventImpl.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEventImpl.java
deleted file mode 100644
index 42a5c90acf0..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEventImpl.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication.event;
-
-import com.google.common.base.Joiner;
-import java.util.Collections;
-import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.util.stream.MoreCollectors;
-
-import static java.util.Objects.requireNonNull;
-
-public class AuthenticationEventImpl implements AuthenticationEvent {
- private static final Logger LOGGER = Loggers.get("auth.event");
- private static final int FLOOD_THRESHOLD = 128;
-
- @Override
- public void loginSuccess(HttpServletRequest request, @Nullable String login, Source source) {
- checkRequest(request);
- requireNonNull(source, "source can't be null");
- if (!LOGGER.isDebugEnabled()) {
- return;
- }
- LOGGER.debug("login success [method|{}][provider|{}|{}][IP|{}|{}][login|{}]",
- source.getMethod(), source.getProvider(), source.getProviderName(),
- request.getRemoteAddr(), getAllIps(request),
- preventLogFlood(emptyIfNull(login)));
- }
-
- private static String getAllIps(HttpServletRequest request) {
- return Collections.list(request.getHeaders("X-Forwarded-For")).stream().collect(MoreCollectors.join(Joiner.on(",")));
- }
-
- @Override
- public void loginFailure(HttpServletRequest request, AuthenticationException e) {
- checkRequest(request);
- requireNonNull(e, "AuthenticationException can't be null");
- if (!LOGGER.isDebugEnabled()) {
- return;
- }
- Source source = e.getSource();
- LOGGER.debug("login failure [cause|{}][method|{}][provider|{}|{}][IP|{}|{}][login|{}]",
- emptyIfNull(e.getMessage()),
- source.getMethod(), source.getProvider(), source.getProviderName(),
- request.getRemoteAddr(), getAllIps(request),
- preventLogFlood(emptyIfNull(e.getLogin())));
- }
-
- @Override
- public void logoutSuccess(HttpServletRequest request, @Nullable String login) {
- checkRequest(request);
- if (!LOGGER.isDebugEnabled()) {
- return;
- }
- LOGGER.debug("logout success [IP|{}|{}][login|{}]",
- request.getRemoteAddr(), getAllIps(request),
- preventLogFlood(emptyIfNull(login)));
- }
-
- @Override
- public void logoutFailure(HttpServletRequest request, String errorMessage) {
- checkRequest(request);
- requireNonNull(errorMessage, "error message can't be null");
- if (!LOGGER.isDebugEnabled()) {
- return;
- }
- LOGGER.debug("logout failure [error|{}][IP|{}|{}]",
- emptyIfNull(errorMessage),
- request.getRemoteAddr(), getAllIps(request));
- }
-
- private static void checkRequest(HttpServletRequest request) {
- requireNonNull(request, "request can't be null");
- }
-
- private static String emptyIfNull(@Nullable String login) {
- return login == null ? "" : login;
- }
-
- private static String preventLogFlood(String str) {
- if (str.length() > FLOOD_THRESHOLD) {
- return str.substring(0, FLOOD_THRESHOLD) + "...(" + str.length() + ")";
- }
- return str;
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationException.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationException.java
deleted file mode 100644
index a4b7196232a..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationException.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication.event;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * Exception thrown in case of authentication failure.
- * <p>
- * This exception contains the source of authentication and, if present, the login on which the login attempt occurred.
- * </p>
- * <p>
- * Given that {@link #source} and {@link #login} will be logged to file, be very careful <strong>not to set the login
- * when the login is a security token</strong>.
- * </p>
- */
-public class AuthenticationException extends RuntimeException {
- private final AuthenticationEvent.Source source;
- @CheckForNull
- private final String login;
- private final String publicMessage;
-
- private AuthenticationException(Builder builder) {
- super(builder.message);
- this.source = requireNonNull(builder.source, "source can't be null");
- this.login = builder.login;
- this.publicMessage = builder.publicMessage;
- }
-
- public AuthenticationEvent.Source getSource() {
- return source;
- }
-
- @CheckForNull
- public String getLogin() {
- return login;
- }
-
- @CheckForNull
- public String getPublicMessage() {
- return publicMessage;
- }
-
- public static Builder newBuilder() {
- return new Builder();
- }
-
- public static class Builder {
- @CheckForNull
- private AuthenticationEvent.Source source;
- @CheckForNull
- private String login;
- @CheckForNull
- private String message;
- @CheckForNull
- private String publicMessage;
-
- private Builder() {
- // use static factory method
- }
-
- public Builder setSource(AuthenticationEvent.Source source) {
- this.source = source;
- return this;
- }
-
- public Builder setLogin(@Nullable String login) {
- this.login = login;
- return this;
- }
-
- public Builder setMessage(String message) {
- this.message = message;
- return this;
- }
-
- public Builder setPublicMessage(String publicMessage) {
- this.publicMessage = publicMessage;
- return this;
- }
-
- public AuthenticationException build() {
- return new AuthenticationException(this);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/event/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/event/package-info.java
deleted file mode 100644
index 329add30331..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/event/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.server.authentication.event;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/exception/EmailAlreadyExistsRedirectionException.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/exception/EmailAlreadyExistsRedirectionException.java
deleted file mode 100644
index c2d103709b4..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/exception/EmailAlreadyExistsRedirectionException.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication.exception;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.db.user.UserDto;
-
-import static org.sonar.server.authentication.AuthenticationError.addErrorCookie;
-
-/**
- * This exception is used to redirect the user to a page explaining him that his email is already used by another account,
- * and where he has the ability to authenticate by "steeling" this email.
- */
-public class EmailAlreadyExistsRedirectionException extends RedirectionException {
-
- private static final String PATH = "/sessions/email_already_exists";
- private static final String EMAIL_FIELD = "email";
- private static final String LOGIN_FIELD = "login";
- private static final String PROVIDER_FIELD = "provider";
- private static final String EXISTING_LOGIN_FIELD = "existingLogin";
- private static final String EXISTING_PROVIDER_FIELD = "existingProvider";
-
- private final String email;
- private final UserDto existingUser;
- private final UserIdentity userIdentity;
- private final IdentityProvider provider;
-
- public EmailAlreadyExistsRedirectionException(String email, UserDto existingUser, UserIdentity userIdentity, IdentityProvider provider) {
- this.email = email;
- this.existingUser = existingUser;
- this.userIdentity = userIdentity;
- this.provider = provider;
- }
-
- public void addCookie(HttpServletRequest request, HttpServletResponse response) {
- Gson gson = new GsonBuilder().create();
- String message = gson.toJson(ImmutableMap.of(
- EMAIL_FIELD, email,
- LOGIN_FIELD, userIdentity.getProviderLogin(),
- PROVIDER_FIELD, provider.getKey(),
- EXISTING_LOGIN_FIELD, existingUser.getExternalLogin(),
- EXISTING_PROVIDER_FIELD, existingUser.getExternalIdentityProvider()));
- addErrorCookie(request, response, message);
- }
-
- @Override
- public String getPath(String contextPath) {
- return contextPath + PATH;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/exception/RedirectionException.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/exception/RedirectionException.java
deleted file mode 100644
index b566ef376c4..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/exception/RedirectionException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication.exception;
-
-public abstract class RedirectionException extends RuntimeException {
-
- public abstract String getPath(String contextPath);
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/exception/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/exception/package-info.java
deleted file mode 100644
index af6555c0df2..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/exception/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.server.authentication.exception;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/package-info.java
deleted file mode 100644
index 6ce3daa6d3c..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/authentication/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.server.authentication;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/DefaultOrganizationEnforcer.java b/server/sonar-server/src/main/java/org/sonar/server/organization/DefaultOrganizationEnforcer.java
deleted file mode 100644
index 6c8aa140701..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/DefaultOrganizationEnforcer.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import org.picocontainer.Startable;
-
-public class DefaultOrganizationEnforcer implements Startable {
- private final DefaultOrganizationProvider defaultOrganizationProvider;
-
- public DefaultOrganizationEnforcer(DefaultOrganizationProvider defaultOrganizationProvider) {
- this.defaultOrganizationProvider = defaultOrganizationProvider;
- }
-
- @Override
- public void start() {
- // get will fail with IllegalStateException if no default organization can be found
- defaultOrganizationProvider.get();
- }
-
- @Override
- public void stop() {
- // nothing to do
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/MemberUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/organization/MemberUpdater.java
deleted file mode 100644
index 0f6c126a6a6..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/MemberUpdater.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.alm.ALM;
-import org.sonar.db.alm.OrganizationAlmBindingDto;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.organization.OrganizationMemberDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserGroupDto;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Sets.difference;
-import static com.google.common.collect.Sets.union;
-import static java.util.Collections.singletonList;
-import static java.util.stream.Collectors.toSet;
-import static org.sonar.api.CoreProperties.DEFAULT_ISSUE_ASSIGNEE;
-import static org.sonar.core.util.stream.MoreCollectors.toList;
-import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
-import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
-
-public class MemberUpdater {
-
- private final DbClient dbClient;
- private final DefaultGroupFinder defaultGroupFinder;
- private final UserIndexer userIndexer;
-
- public MemberUpdater(DbClient dbClient, DefaultGroupFinder defaultGroupFinder, UserIndexer userIndexer) {
- this.dbClient = dbClient;
- this.defaultGroupFinder = defaultGroupFinder;
- this.userIndexer = userIndexer;
- }
-
- public void addMember(DbSession dbSession, OrganizationDto organization, UserDto user) {
- addMembers(dbSession, organization, singletonList(user));
- }
-
- public void addMembers(DbSession dbSession, OrganizationDto organization, List<UserDto> users) {
- Set<Integer> currentMemberIds = new HashSet<>(dbClient.organizationMemberDao().selectUserIdsByOrganizationUuid(dbSession, organization.getUuid()));
- List<UserDto> usersToAdd = users.stream()
- .filter(UserDto::isActive)
- .filter(u -> !currentMemberIds.contains(u.getId()))
- .collect(toList());
- if (usersToAdd.isEmpty()) {
- return;
- }
- usersToAdd.forEach(u -> addMemberInDb(dbSession, organization, u));
- userIndexer.commitAndIndex(dbSession, usersToAdd);
- }
-
- private void addMemberInDb(DbSession dbSession, OrganizationDto organization, UserDto user) {
- dbClient.organizationMemberDao().insert(dbSession, new OrganizationMemberDto()
- .setOrganizationUuid(organization.getUuid())
- .setUserId(user.getId()));
- dbClient.userGroupDao().insert(dbSession,
- new UserGroupDto().setGroupId(defaultGroupFinder.findDefaultGroup(dbSession, organization.getUuid()).getId()).setUserId(user.getId()));
- }
-
- public void removeMember(DbSession dbSession, OrganizationDto organization, UserDto user) {
- removeMembers(dbSession, organization, singletonList(user));
- }
-
- public void removeMembers(DbSession dbSession, OrganizationDto organization, List<UserDto> users) {
- Set<Integer> currentMemberIds = new HashSet<>(dbClient.organizationMemberDao().selectUserIdsByOrganizationUuid(dbSession, organization.getUuid()));
- List<UserDto> usersToRemove = users.stream()
- .filter(UserDto::isActive)
- .filter(u -> currentMemberIds.contains(u.getId()))
- .collect(toList());
- if (usersToRemove.isEmpty()) {
- return;
- }
-
- Set<Integer> userIdsToRemove = usersToRemove.stream().map(UserDto::getId).collect(toSet());
- Set<Integer> adminIds = new HashSet<>(dbClient.authorizationDao().selectUserIdsWithGlobalPermission(dbSession, organization.getUuid(), ADMINISTER.getKey()));
- checkArgument(!difference(adminIds, userIdsToRemove).isEmpty(), "The last administrator member cannot be removed");
-
- usersToRemove.forEach(u -> removeMemberInDb(dbSession, organization, u));
- userIndexer.commitAndIndex(dbSession, usersToRemove);
- }
-
- /**
- * Synchronize organization membership of a user from a list of ALM organization specific ids
- * Please note that no commit will not be executed.
- */
- public void synchronizeUserOrganizationMembership(DbSession dbSession, UserDto user, ALM alm, Set<String> organizationAlmIds) {
- Set<String> userOrganizationUuids = dbClient.organizationMemberDao().selectOrganizationUuidsByUser(dbSession, user.getId());
- Set<String> userOrganizationUuidsWithMembersSyncEnabled = dbClient.organizationAlmBindingDao().selectByOrganizationUuids(dbSession, userOrganizationUuids).stream()
- .filter(OrganizationAlmBindingDto::isMembersSyncEnable)
- .map(OrganizationAlmBindingDto::getOrganizationUuid)
- .collect(toSet());
- Set<String> almOrganizationUuidsWithMembersSyncEnabled = dbClient.organizationAlmBindingDao().selectByOrganizationAlmIds(dbSession, alm, organizationAlmIds).stream()
- .filter(OrganizationAlmBindingDto::isMembersSyncEnable)
- .map(OrganizationAlmBindingDto::getOrganizationUuid)
- .collect(toSet());
-
- Set<String> organizationUuidsToBeAdded = difference(almOrganizationUuidsWithMembersSyncEnabled, userOrganizationUuidsWithMembersSyncEnabled);
- Set<String> organizationUuidsToBeRemoved = difference(userOrganizationUuidsWithMembersSyncEnabled, almOrganizationUuidsWithMembersSyncEnabled);
- Map<String, OrganizationDto> allOrganizationsByUuid = dbClient.organizationDao().selectByUuids(dbSession, union(organizationUuidsToBeAdded, organizationUuidsToBeRemoved))
- .stream()
- .collect(uniqueIndex(OrganizationDto::getUuid));
-
- allOrganizationsByUuid.entrySet().stream()
- .filter(entry -> organizationUuidsToBeAdded.contains(entry.getKey()))
- .forEach(entry -> addMemberInDb(dbSession, entry.getValue(), user));
- allOrganizationsByUuid.entrySet().stream()
- .filter(entry -> organizationUuidsToBeRemoved.contains(entry.getKey()))
- .forEach(entry -> removeMemberInDb(dbSession, entry.getValue(), user));
- }
-
- private void removeMemberInDb(DbSession dbSession, OrganizationDto organization, UserDto user) {
- int userId = user.getId();
- String organizationUuid = organization.getUuid();
- dbClient.userPermissionDao().deleteOrganizationMemberPermissions(dbSession, organizationUuid, userId);
- dbClient.permissionTemplateDao().deleteUserPermissionsByOrganization(dbSession, organizationUuid, userId);
- dbClient.qProfileEditUsersDao().deleteByOrganizationAndUser(dbSession, organization, user);
- dbClient.userGroupDao().deleteByOrganizationAndUser(dbSession, organizationUuid, userId);
- dbClient.propertiesDao().deleteByOrganizationAndUser(dbSession, organizationUuid, userId);
- dbClient.propertiesDao().deleteByOrganizationAndMatchingLogin(dbSession, organizationUuid, user.getLogin(), singletonList(DEFAULT_ISSUE_ASSIGNEE));
-
- dbClient.organizationMemberDao().delete(dbSession, organizationUuid, userId);
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/NoopDefaultOrganizationCache.java b/server/sonar-server/src/main/java/org/sonar/server/organization/NoopDefaultOrganizationCache.java
deleted file mode 100644
index cfb1cbad52b..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/NoopDefaultOrganizationCache.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-/**
- * This implementation of {@link DefaultOrganizationCache} has no effect. It is used when SQ is running in safe mode
- * (ie. when we are expecting a DB upgrade and we can't assume the tables storing default organization information are
- * available).
- */
-public class NoopDefaultOrganizationCache implements DefaultOrganizationCache {
- @Override
- public void load() {
- // do nothing
- }
-
- @Override
- public void unload() {
- // do nothing
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganisationSupport.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganisationSupport.java
deleted file mode 100644
index 0198cae2b4e..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganisationSupport.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import java.util.List;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.server.ServerSide;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.permission.GroupPermissionDto;
-import org.sonar.db.permission.template.PermissionTemplateGroupDto;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserGroupDto;
-import org.sonar.server.rule.index.RuleIndexer;
-import org.sonar.server.usergroups.DefaultGroupCreator;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static org.sonar.core.util.stream.MoreCollectors.toList;
-
-@ServerSide
-public class OrganisationSupport {
- private final DbClient dbClient;
- private final DefaultOrganizationProvider defaultOrganizationProvider;
- private final OrganizationFlags organizationFlags;
- private final DefaultGroupCreator defaultGroupCreator;
- private final DefaultGroupFinder defaultGroupFinder;
- private final RuleIndexer ruleIndexer;
-
- public OrganisationSupport(DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider,
- OrganizationFlags organizationFlags, DefaultGroupCreator defaultGroupCreator, DefaultGroupFinder defaultGroupFinder,
- RuleIndexer ruleIndexer) {
- this.dbClient = dbClient;
- this.defaultOrganizationProvider = defaultOrganizationProvider;
- this.organizationFlags = organizationFlags;
- this.defaultGroupCreator = defaultGroupCreator;
- this.defaultGroupFinder = defaultGroupFinder;
- this.ruleIndexer = ruleIndexer;
- }
-
- public void enable(String login) {
- String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid();
- try (DbSession dbSession = dbClient.openSession(false)) {
- if (!organizationFlags.isEnabled(dbSession)) {
- flagAdminUserAsRoot(dbSession, login);
- createDefaultMembersGroup(dbSession, defaultOrganizationUuid);
- List<Integer> disabledTemplateAndCustomRuleIds = disableTemplateRulesAndCustomRules(dbSession);
- enableFeature(dbSession);
- ruleIndexer.commitAndIndex(dbSession, disabledTemplateAndCustomRuleIds);
- }
- }
- }
-
- private void flagAdminUserAsRoot(DbSession dbSession, String login) {
- dbClient.userDao().setRoot(dbSession, login, true);
- }
-
- private void createDefaultMembersGroup(DbSession dbSession, String defaultOrganizationUuid) {
- GroupDto sonarUsersGroupId = defaultGroupFinder.findDefaultGroup(dbSession, defaultOrganizationUuid);
- GroupDto members = defaultGroupCreator.create(dbSession, defaultOrganizationUuid);
- copySonarUsersGroupPermissionsToMembersGroup(dbSession, defaultOrganizationUuid, sonarUsersGroupId, members);
- copySonarUsersGroupPermissionTemplatesToMembersGroup(dbSession, sonarUsersGroupId, members);
- associateMembersOfDefaultOrganizationToGroup(dbSession, defaultOrganizationUuid, members);
- }
-
- private void associateMembersOfDefaultOrganizationToGroup(DbSession dbSession, String defaultOrganizationUuid, GroupDto membersGroup) {
- List<Integer> organizationMembers = dbClient.organizationMemberDao().selectUserIdsByOrganizationUuid(dbSession, defaultOrganizationUuid);
- organizationMembers.forEach(member -> dbClient.userGroupDao().insert(dbSession, new UserGroupDto().setGroupId(membersGroup.getId()).setUserId(member)));
- }
-
- private void copySonarUsersGroupPermissionsToMembersGroup(DbSession dbSession, String defaultOrganizationUuid, GroupDto sonarUsersGroup, GroupDto membersGroup) {
- dbClient.groupPermissionDao().selectAllPermissionsByGroupId(dbSession, defaultOrganizationUuid, sonarUsersGroup.getId(),
- context -> {
- GroupPermissionDto groupPermissionDto = (GroupPermissionDto) context.getResultObject();
- dbClient.groupPermissionDao().insert(dbSession,
- new GroupPermissionDto().setOrganizationUuid(defaultOrganizationUuid).setGroupId(membersGroup.getId())
- .setRole(groupPermissionDto.getRole())
- .setResourceId(groupPermissionDto.getResourceId()));
- });
- }
-
- private void copySonarUsersGroupPermissionTemplatesToMembersGroup(DbSession dbSession, GroupDto sonarUsersGroup, GroupDto membersGroup) {
- List<PermissionTemplateGroupDto> sonarUsersPermissionTemplates = dbClient.permissionTemplateDao().selectAllGroupPermissionTemplatesByGroupId(dbSession,
- sonarUsersGroup.getId());
- sonarUsersPermissionTemplates.forEach(permissionTemplateGroup -> dbClient.permissionTemplateDao().insertGroupPermission(dbSession,
- permissionTemplateGroup.getTemplateId(), membersGroup.getId(), permissionTemplateGroup.getPermission()));
- }
-
- private List<Integer> disableTemplateRulesAndCustomRules(DbSession dbSession) {
- List<RuleDefinitionDto> rules = dbClient.ruleDao().selectAllDefinitions(dbSession).stream()
- .filter(r -> r.isTemplate() || r.isCustomRule())
- .collect(toList());
- rules.forEach(r -> {
- r.setStatus(RuleStatus.REMOVED);
- dbClient.ruleDao().update(dbSession, r);
- });
- return rules.stream().map(RuleDefinitionDto::getId).collect(toList());
- }
-
- private void enableFeature(DbSession dbSession) {
- organizationFlags.enable(dbSession);
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java
deleted file mode 100644
index 80584ff7f47..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import org.sonar.api.server.ServerSide;
-import org.sonar.db.DbSession;
-import org.sonar.db.organization.OrganizationDto;
-
-@ServerSide
-public interface OrganizationAlmBinding {
-
- void bindOrganization(DbSession dbSession, OrganizationDto organization, String installationId, boolean isNewOrganization);
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdater.java
deleted file mode 100644
index de4f15b2ee7..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdater.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import java.util.function.Consumer;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.DbSession;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.usergroups.DefaultGroupCreatorImpl;
-
-import static java.util.Objects.requireNonNull;
-
-public interface OrganizationUpdater {
- String OWNERS_GROUP_NAME = "Owners";
- String OWNERS_GROUP_DESCRIPTION = "Owners of organization";
- String PERM_TEMPLATE_NAME = "Default template";
- String PERM_TEMPLATE_DESCRIPTION_PATTERN = "Default permission template of organization %s";
-
- /**
- * Create a new organization with the specified properties and of which the specified user will assign
- * Administer Organization permission.
- * <p>
- * This method does several operations at once:
- * <ol>
- * <li>create an ungarded organization with the specified details</li>
- * <li>create a group called {@link #OWNERS_GROUP_NAME Owners} with all organization wide permissions</li>
- * <li>create a group called {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} with browse permissions</li>
- * <li>make the specified user a member of these groups</li>
- * <li>create a default template for the organization
- * <ul>
- * <li>name is {@link #PERM_TEMPLATE_NAME Default template}</li>
- * <li>description follows pattern {@link #PERM_TEMPLATE_DESCRIPTION_PATTERN} based on the organization name</li>
- * </ul>
- * </li>
- * <li>this permission template defines the specified permissions (which effectively makes projects public):
- * <ul>
- * <li>group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#ADMIN ADMIN}</li>
- * <li>group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#ISSUE_ADMIN ISSUE_ADMIN}</li>
- * <li>group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#SECURITYHOTSPOT_ADMIN SECURITYHOTSPOT_ADMIN}</li>
- * <li>group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#SCAN SCAN}</li>
- * <li>group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#USER USER}</li>
- * <li>group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#CODEVIEWER CODEVIEWER}</li>
- * </ul>
- * </li>
- * </ol>
- * </p>
- *
- * @return the created organization
- *
- * @throws KeyConflictException if an organization with the specified key already exists
- * @throws IllegalArgumentException if any field of {@code newOrganization} is invalid according to {@link OrganizationValidation}
- */
- OrganizationDto create(DbSession dbSession, UserDto userCreator, NewOrganization newOrganization, Consumer<OrganizationDto> beforeCommit) throws KeyConflictException;
-
- /**
- * Update the personal organization key of a user.
- * No update will be performed if generated key match the same key as existing one.
- *
- * @throws IllegalStateException if user has no no personal organization
- * @throws IllegalStateException if personal organization uuid does not exist
- * @throws IllegalStateException if an organization with the key generated from the login already exists
- */
- void updateOrganizationKey(DbSession dbSession, OrganizationDto organization, String newKey);
-
- final class KeyConflictException extends Exception {
- KeyConflictException(String message) {
- super(message);
- }
- }
-
- final class NewOrganization {
- private final String key;
- private final String name;
- @CheckForNull
- private final String description;
- @CheckForNull
- private final String url;
- @CheckForNull
- private final String avatar;
-
- private NewOrganization(Builder builder) {
- this.key = builder.key;
- this.name = builder.name;
- this.description = builder.description;
- this.url = builder.url;
- this.avatar = builder.avatarUrl;
- }
-
- public String getKey() {
- return key;
- }
-
- public String getName() {
- return name;
- }
-
- @CheckForNull
- public String getDescription() {
- return description;
- }
-
- @CheckForNull
- public String getUrl() {
- return url;
- }
-
- @CheckForNull
- public String getAvatar() {
- return avatar;
- }
-
- public static NewOrganization.Builder newOrganizationBuilder() {
- return new Builder();
- }
-
- public static final class Builder {
- private String key;
- private String name;
- private String description;
- private String url;
- private String avatarUrl;
-
- private Builder() {
- // use factory method
- }
-
- public Builder setKey(String key) {
- this.key = requireNonNull(key, "key can't be null");
- return this;
- }
-
- public Builder setName(String name) {
- this.name = requireNonNull(name, "name can't be null");
- return this;
- }
-
- public Builder setDescription(@Nullable String description) {
- this.description = description;
- return this;
- }
-
- public Builder setUrl(@Nullable String url) {
- this.url = url;
- return this;
- }
-
- public Builder setAvatarUrl(@Nullable String avatarUrl) {
- this.avatarUrl = avatarUrl;
- return this;
- }
-
- public NewOrganization build() {
- requireNonNull(key, "key can't be null");
- requireNonNull(name, "name can't be null");
- return new NewOrganization(this);
- }
- }
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java
deleted file mode 100644
index 38f4a3c1a17..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-import javax.annotation.Nullable;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.UuidFactory;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.organization.DefaultTemplates;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.organization.OrganizationMemberDto;
-import org.sonar.db.permission.GroupPermissionDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.permission.template.PermissionTemplateDto;
-import org.sonar.db.qualitygate.QualityGateDto;
-import org.sonar.db.qualityprofile.DefaultQProfileDto;
-import org.sonar.db.qualityprofile.OrgQProfileDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserGroupDto;
-import org.sonar.server.permission.PermissionService;
-import org.sonar.server.qualityprofile.BuiltInQProfile;
-import org.sonar.server.qualityprofile.BuiltInQProfileRepository;
-import org.sonar.server.qualityprofile.QProfileName;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.usergroups.DefaultGroupCreator;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.web.UserRole.ADMIN;
-import static org.sonar.api.web.UserRole.CODEVIEWER;
-import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
-import static org.sonar.api.web.UserRole.SECURITYHOTSPOT_ADMIN;
-import static org.sonar.api.web.UserRole.USER;
-import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
-import static org.sonar.db.organization.OrganizationDto.Subscription.FREE;
-import static org.sonar.db.permission.OrganizationPermission.SCAN;
-
-public class OrganizationUpdaterImpl implements OrganizationUpdater {
-
- private final DbClient dbClient;
- private final System2 system2;
- private final UuidFactory uuidFactory;
- private final OrganizationValidation organizationValidation;
- private final BuiltInQProfileRepository builtInQProfileRepository;
- private final DefaultGroupCreator defaultGroupCreator;
- private final UserIndexer userIndexer;
- private final PermissionService permissionService;
-
- public OrganizationUpdaterImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory,
- OrganizationValidation organizationValidation, UserIndexer userIndexer,
- BuiltInQProfileRepository builtInQProfileRepository, DefaultGroupCreator defaultGroupCreator, PermissionService permissionService) {
- this.dbClient = dbClient;
- this.system2 = system2;
- this.uuidFactory = uuidFactory;
- this.organizationValidation = organizationValidation;
- this.userIndexer = userIndexer;
- this.builtInQProfileRepository = builtInQProfileRepository;
- this.defaultGroupCreator = defaultGroupCreator;
- this.permissionService = permissionService;
- }
-
- @Override
- public OrganizationDto create(DbSession dbSession, UserDto userCreator, NewOrganization newOrganization, Consumer<OrganizationDto> beforeCommit) throws KeyConflictException {
- validate(newOrganization);
- String key = newOrganization.getKey();
- if (organizationKeyIsUsed(dbSession, key)) {
- throw new KeyConflictException(format("Organization key '%s' is already used", key));
- }
-
- QualityGateDto builtInQualityGate = dbClient.qualityGateDao().selectBuiltIn(dbSession);
- OrganizationDto organization = insertOrganization(dbSession, newOrganization, builtInQualityGate);
- beforeCommit.accept(organization);
- insertOrganizationMember(dbSession, organization, userCreator.getId());
- dbClient.qualityGateDao().associate(dbSession, uuidFactory.create(), organization, builtInQualityGate);
- GroupDto ownerGroup = insertOwnersGroup(dbSession, organization);
- GroupDto defaultGroup = defaultGroupCreator.create(dbSession, organization.getUuid());
- insertDefaultTemplateOnGroups(dbSession, organization, ownerGroup, defaultGroup);
- addCurrentUserToGroup(dbSession, ownerGroup, userCreator.getId());
- addCurrentUserToGroup(dbSession, defaultGroup, userCreator.getId());
- try (DbSession batchDbSession = dbClient.openSession(true)) {
- insertQualityProfiles(dbSession, batchDbSession, organization);
- batchDbSession.commit();
-
- // Elasticsearch is updated when DB session is committed
- userIndexer.commitAndIndex(dbSession, userCreator);
-
- return organization;
- }
- }
-
- @Override
- public void updateOrganizationKey(DbSession dbSession, OrganizationDto organization, String newKey) {
- String sanitizedKey = organizationValidation.generateKeyFrom(newKey);
- if (organization.getKey().equals(sanitizedKey)) {
- return;
- }
- checkKey(dbSession, sanitizedKey);
- dbClient.organizationDao().update(dbSession, organization.setKey(sanitizedKey));
- }
-
- private void checkKey(DbSession dbSession, String key) {
- checkState(!organizationKeyIsUsed(dbSession, key),
- "Can't create organization with key '%s' because an organization with this key already exists", key);
- }
-
- private void validate(NewOrganization newOrganization) {
- requireNonNull(newOrganization, "newOrganization can't be null");
- organizationValidation.checkName(newOrganization.getName());
- organizationValidation.checkKey(newOrganization.getKey());
- organizationValidation.checkDescription(newOrganization.getDescription());
- organizationValidation.checkUrl(newOrganization.getUrl());
- organizationValidation.checkAvatar(newOrganization.getAvatar());
- }
-
- private OrganizationDto insertOrganization(DbSession dbSession, NewOrganization newOrganization, QualityGateDto builtInQualityGate, Consumer<OrganizationDto>... extendCreation) {
- OrganizationDto res = new OrganizationDto()
- .setUuid(uuidFactory.create())
- .setName(newOrganization.getName())
- .setKey(newOrganization.getKey())
- .setDescription(newOrganization.getDescription())
- .setUrl(newOrganization.getUrl())
- .setDefaultQualityGateUuid(builtInQualityGate.getUuid())
- .setAvatarUrl(newOrganization.getAvatar())
- .setSubscription(FREE);
- Arrays.stream(extendCreation).forEach(c -> c.accept(res));
- dbClient.organizationDao().insert(dbSession, res, false);
- return res;
- }
-
- private boolean organizationKeyIsUsed(DbSession dbSession, String key) {
- return dbClient.organizationDao().selectByKey(dbSession, key).isPresent();
- }
-
- private void insertDefaultTemplateOnGroups(DbSession dbSession, OrganizationDto organizationDto, GroupDto ownerGroup, GroupDto defaultGroup) {
- Date now = new Date(system2.now());
- PermissionTemplateDto permissionTemplateDto = dbClient.permissionTemplateDao().insert(
- dbSession,
- new PermissionTemplateDto()
- .setOrganizationUuid(organizationDto.getUuid())
- .setUuid(uuidFactory.create())
- .setName(PERM_TEMPLATE_NAME)
- .setDescription(format(PERM_TEMPLATE_DESCRIPTION_PATTERN, organizationDto.getName()))
- .setCreatedAt(now)
- .setUpdatedAt(now));
-
- insertGroupPermission(dbSession, permissionTemplateDto, ADMIN, ownerGroup);
- insertGroupPermission(dbSession, permissionTemplateDto, SCAN.getKey(), ownerGroup);
- insertGroupPermission(dbSession, permissionTemplateDto, USER, defaultGroup);
- insertGroupPermission(dbSession, permissionTemplateDto, CODEVIEWER, defaultGroup);
- insertGroupPermission(dbSession, permissionTemplateDto, ISSUE_ADMIN, defaultGroup);
- insertGroupPermission(dbSession, permissionTemplateDto, SECURITYHOTSPOT_ADMIN, defaultGroup);
-
- dbClient.organizationDao().setDefaultTemplates(
- dbSession,
- organizationDto.getUuid(),
- new DefaultTemplates().setProjectUuid(permissionTemplateDto.getUuid()));
- }
-
- private void insertGroupPermission(DbSession dbSession, PermissionTemplateDto template, String permission, @Nullable GroupDto group) {
- dbClient.permissionTemplateDao().insertGroupPermission(dbSession, template.getId(), group == null ? null : group.getId(), permission);
- }
-
- private void insertQualityProfiles(DbSession dbSession, DbSession batchDbSession, OrganizationDto organization) {
- Map<QProfileName, BuiltInQProfile> builtInsPerName = builtInQProfileRepository.get().stream()
- .collect(uniqueIndex(BuiltInQProfile::getQProfileName));
-
- List<DefaultQProfileDto> defaults = new ArrayList<>();
- dbClient.qualityProfileDao().selectBuiltInRuleProfiles(dbSession).forEach(rulesProfile -> {
- OrgQProfileDto dto = new OrgQProfileDto()
- .setOrganizationUuid(organization.getUuid())
- .setRulesProfileUuid(rulesProfile.getKee())
- .setUuid(uuidFactory.create());
-
- QProfileName name = new QProfileName(rulesProfile.getLanguage(), rulesProfile.getName());
- BuiltInQProfile builtIn = builtInsPerName.get(name);
- if (builtIn == null || builtIn.isDefault()) {
- // If builtIn == null, the plugin has been removed
- // rows of table default_qprofiles must be inserted after org_qprofiles
- // in order to benefit from batch SQL inserts
- defaults.add(new DefaultQProfileDto()
- .setQProfileUuid(dto.getUuid())
- .setOrganizationUuid(organization.getUuid())
- .setLanguage(rulesProfile.getLanguage()));
- }
-
- dbClient.qualityProfileDao().insert(batchDbSession, dto);
- });
-
- defaults.forEach(defaultQProfileDto -> dbClient.defaultQProfileDao().insertOrUpdate(dbSession, defaultQProfileDto));
- }
-
- /**
- * Owners group has an hard coded name, a description based on the organization's name and has all global permissions.
- */
- private GroupDto insertOwnersGroup(DbSession dbSession, OrganizationDto organization) {
- GroupDto group = dbClient.groupDao().insert(dbSession, new GroupDto()
- .setOrganizationUuid(organization.getUuid())
- .setName(OWNERS_GROUP_NAME)
- .setDescription(OWNERS_GROUP_DESCRIPTION));
- permissionService.getAllOrganizationPermissions().forEach(p -> addPermissionToGroup(dbSession, group, p));
- return group;
- }
-
- private void addPermissionToGroup(DbSession dbSession, GroupDto group, OrganizationPermission permission) {
- dbClient.groupPermissionDao().insert(
- dbSession,
- new GroupPermissionDto()
- .setOrganizationUuid(group.getOrganizationUuid())
- .setGroupId(group.getId())
- .setRole(permission.getKey()));
- }
-
- private void addCurrentUserToGroup(DbSession dbSession, GroupDto group, int createUserId) {
- dbClient.userGroupDao().insert(
- dbSession,
- new UserGroupDto().setGroupId(group.getId()).setUserId(createUserId));
- }
-
- private void insertOrganizationMember(DbSession dbSession, OrganizationDto organizationDto, int userId) {
- dbClient.organizationMemberDao().insert(dbSession, new OrganizationMemberDto()
- .setOrganizationUuid(organizationDto.getUuid())
- .setUserId(userId));
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidation.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidation.java
deleted file mode 100644
index 37fb7eb5758..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidation.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-public interface OrganizationValidation {
- int KEY_MIN_LENGTH = 1;
- int KEY_MAX_LENGTH = 255;
- int NAME_MIN_LENGTH = 1;
- int NAME_MAX_LENGTH = 255;
- int DESCRIPTION_MAX_LENGTH = 256;
- int URL_MAX_LENGTH = 256;
-
- /**
- * Ensures the specified argument is a valid key by failing with an exception if it is not so.
- * <p>
- * A valid key is non null and its length is between {@link #KEY_MIN_LENGTH} and {@link #KEY_MAX_LENGTH}.
- * </p>
- *
- * @return the argument
- *
- * @throws NullPointerException if argument is {@code null}.
- * @throws IllegalArgumentException if argument is not a valid key.
- */
- String checkKey(String keyCandidate);
-
- /**
- * Ensures the specified argument is a valid name by failing with an exception if it is not so.
- * <p>
- * A valid name is non null and its length is between {@link #NAME_MIN_LENGTH} and {@link #NAME_MAX_LENGTH}.
- * </p>
- *
- * @return the argument
- *
- * @throws NullPointerException if argument is {@code null}.
- * @throws IllegalArgumentException if argument is not a valid name.
- */
- String checkName(String nameCandidate);
-
- /**
- * Ensures the specified argument is either {@code null}, empty or a valid description by failing with an exception
- * if it is not so.
- * <p>
- * The length of a valid url can't be more than {@link #DESCRIPTION_MAX_LENGTH 256}.
- * </p>
- *
- * @return the argument
- *
- * @throws IllegalArgumentException if argument is not a valid description.
- */
- @CheckForNull
- String checkDescription(@Nullable String descriptionCandidate);
-
- /**
- * Ensures the specified argument is either {@code null}, empty or a valid URL by failing with an exception if it is
- * not so.
- * <p>
- * The length of a valid URL can't be more than {@link #URL_MAX_LENGTH 256}.
- * </p>
- *
- * @return the argument
- *
- * @throws IllegalArgumentException if argument is not a valid url.
- */
- @CheckForNull
- String checkUrl(@Nullable String urlCandidate);
-
- /**
- * Ensures the specified argument is either {@code null}, empty or a valid avatar URL by failing with an exception if
- * it is not so.
- * <p>
- * The length of a valid avatar URL can't be more than {@link #URL_MAX_LENGTH 256}.
- * </p>
- *
- * @return the argument
- *
- * @throws IllegalArgumentException if argument is not a valid avatar url.
- */
- @CheckForNull
- String checkAvatar(@Nullable String avatarCandidate);
-
- /**
- * Transforms the specified string into a valid key.
- *
- * @see #checkKey(String)
- */
- String generateKeyFrom(String source);
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java
deleted file mode 100644
index ab6e0c4fb87..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.core.util.Slug.slugify;
-
-public class OrganizationValidationImpl implements OrganizationValidation {
-
- @Override
- public String checkKey(String keyCandidate) {
- requireNonNull(keyCandidate, "key can't be null");
- checkArgument(keyCandidate.length() >= KEY_MIN_LENGTH, "Key must not be empty");
- checkArgument(keyCandidate.length() <= KEY_MAX_LENGTH, "Key '%s' must be at most %s chars long", keyCandidate, KEY_MAX_LENGTH);
- checkArgument(slugify(keyCandidate).equals(keyCandidate), "Key '%s' contains at least one invalid char", keyCandidate);
-
- return keyCandidate;
- }
-
- @Override
- public String checkName(String nameCandidate) {
- requireNonNull(nameCandidate, "name can't be null");
-
- checkArgument(nameCandidate.length() >= NAME_MIN_LENGTH, "Name must not be empty");
- checkArgument(nameCandidate.length() <= NAME_MAX_LENGTH, "Name '%s' must be at most %s chars long", nameCandidate, NAME_MAX_LENGTH);
-
- return nameCandidate;
- }
-
- @Override
- public String checkDescription(@Nullable String descriptionCandidate) {
- checkParamMaxLength(descriptionCandidate, "Description", DESCRIPTION_MAX_LENGTH);
-
- return descriptionCandidate;
- }
-
- @Override
- public String checkUrl(@Nullable String urlCandidate) {
- checkParamMaxLength(urlCandidate, "Url", URL_MAX_LENGTH);
-
- return urlCandidate;
- }
-
- @Override
- public String checkAvatar(@Nullable String avatarCandidate) {
- checkParamMaxLength(avatarCandidate, "Avatar", URL_MAX_LENGTH);
-
- return avatarCandidate;
- }
-
- @CheckForNull
- private static void checkParamMaxLength(@Nullable String value, String label, int maxLength) {
- if (value != null) {
- checkArgument(value.length() <= maxLength, "%s '%s' must be at most %s chars long", label, value, maxLength);
- }
- }
-
- @Override
- public String generateKeyFrom(String source) {
- return slugify(source);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/organization/package-info.java
deleted file mode 100644
index 0b32d7b6139..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.server.organization;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/GroupId.java b/server/sonar-server/src/main/java/org/sonar/server/permission/GroupId.java
deleted file mode 100644
index 0faba895d4a..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/GroupId.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.permission;
-
-import javax.annotation.concurrent.Immutable;
-import org.sonar.db.user.GroupDto;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * Reference to a user group, as used internally by the backend. It does
- * not support reference to virtual groups "anyone".
- *
- * @see GroupWsRef
- * @see GroupIdOrAnyone
- */
-@Immutable
-public class GroupId {
-
- private final int id;
- private final String organizationUuid;
-
- private GroupId(String organizationUuid, int id) {
- this.id = id;
- this.organizationUuid = requireNonNull(organizationUuid);
- }
-
- public int getId() {
- return id;
- }
-
- public String getOrganizationUuid() {
- return organizationUuid;
- }
-
- public static GroupId from(GroupDto dto) {
- return new GroupId(dto.getOrganizationUuid(), dto.getId());
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/GroupIdOrAnyone.java b/server/sonar-server/src/main/java/org/sonar/server/permission/GroupIdOrAnyone.java
deleted file mode 100644
index 4a6add59eb6..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/GroupIdOrAnyone.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.permission;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.db.user.GroupDto;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * Reference to a user group, as used internally by the backend. Contrary to
- * {@link GroupId}, it supports reference to virtual groups "anyone". In these
- * cases {@link #getId()} returns {@code null}
- *
- * @see GroupId
- */
-@Immutable
-public class GroupIdOrAnyone {
-
- private final Integer id;
- private final String organizationUuid;
-
- private GroupIdOrAnyone(String organizationUuid, @Nullable Integer id) {
- this.id = id;
- this.organizationUuid = requireNonNull(organizationUuid);
- }
-
- public boolean isAnyone() {
- return id == null;
- }
-
- @CheckForNull
- public Integer getId() {
- return id;
- }
-
- public String getOrganizationUuid() {
- return organizationUuid;
- }
-
- public static GroupIdOrAnyone from(GroupDto dto) {
- return new GroupIdOrAnyone(dto.getOrganizationUuid(), dto.getId());
- }
-
- public static GroupIdOrAnyone forAnyone(String organizationUuid) {
- return new GroupIdOrAnyone(organizationUuid, null);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java b/server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java
index 5e6a0a48dd0..947310f2274 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java
@@ -21,16 +21,17 @@ package org.sonar.server.permission;
import java.util.List;
import java.util.Optional;
+import org.sonar.core.permission.GlobalPermissions;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.permission.GroupPermissionDto;
+import static java.lang.String.format;
import static org.sonar.api.web.UserRole.PUBLIC_PERMISSIONS;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
+import static org.sonar.server.exceptions.BadRequestException.checkRequest;
import static org.sonar.server.permission.PermissionChange.Operation.ADD;
import static org.sonar.server.permission.PermissionChange.Operation.REMOVE;
-import static org.sonar.server.permission.RequestValidator.validateNotAnyoneAndAdminPermission;
-import static org.sonar.server.exceptions.BadRequestException.checkRequest;
public class GroupPermissionChanger {
@@ -117,6 +118,11 @@ public class GroupPermissionChanger {
return true;
}
+ private static void validateNotAnyoneAndAdminPermission(String permission, GroupIdOrAnyone group) {
+ checkRequest(!GlobalPermissions.SYSTEM_ADMIN.equals(permission) || !group.isAnyone(),
+ format("It is not possible to add the '%s' permission to group 'Anyone'.", permission));
+ }
+
private boolean removePermission(DbSession dbSession, GroupPermissionChange change) {
if (!loadExistingPermissions(dbSession, change).contains(change.getPermission())) {
return false;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionPrivilegeChecker.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionPrivilegeChecker.java
deleted file mode 100644
index 64243e1355b..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionPrivilegeChecker.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.permission;
-
-import java.util.Optional;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.server.user.UserSession;
-
-import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
-
-public class PermissionPrivilegeChecker {
- private PermissionPrivilegeChecker() {
- // static methods only
- }
-
- public static void checkGlobalAdmin(UserSession userSession, String organizationUuid) {
- userSession
- .checkLoggedIn()
- .checkPermission(OrganizationPermission.ADMINISTER, organizationUuid);
- }
-
- /**
- * Checks that user is administrator of the specified project, or of the specified organization if project is not
- * defined.
- * @throws org.sonar.server.exceptions.ForbiddenException if user is not administrator
- */
- public static void checkProjectAdmin(UserSession userSession, String organizationUuid, Optional<ProjectId> projectId) {
- userSession.checkLoggedIn();
-
- if (userSession.hasPermission(OrganizationPermission.ADMINISTER, organizationUuid)) {
- return;
- }
-
- if (projectId.isPresent()) {
- userSession.checkComponentUuidPermission(UserRole.ADMIN, projectId.get().getUuid());
- } else {
- throw insufficientPrivilegesException();
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java
deleted file mode 100644
index fdfe77d7383..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.permission;
-
-import java.util.List;
-import org.sonar.db.permission.OrganizationPermission;
-
-public interface PermissionService {
-
- List<OrganizationPermission> getAllOrganizationPermissions();
- List<String> getAllProjectPermissions();
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionServiceImpl.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionServiceImpl.java
deleted file mode 100644
index a7278d4ed20..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionServiceImpl.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.permission;
-
-import com.google.common.collect.ImmutableList;
-import java.util.List;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.permission.OrganizationPermission;
-
-import static java.util.stream.Collectors.toList;
-
-@Immutable
-public class PermissionServiceImpl implements PermissionService {
-
- private static final List<String> ALL_PROJECT_PERMISSIONS = ImmutableList.of(
- UserRole.ADMIN, UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, UserRole.SCAN, UserRole.USER);
-
- private static final List<OrganizationPermission> ALL_GLOBAL_PERMISSIONS = ImmutableList.copyOf(OrganizationPermission.values());
-
- private final List<OrganizationPermission> globalPermissions;
- private final List<String> projectPermissions;
-
- public PermissionServiceImpl(ResourceTypes resourceTypes) {
- globalPermissions = ImmutableList.copyOf(ALL_GLOBAL_PERMISSIONS.stream()
- .filter(s -> !s.equals(OrganizationPermission.APPLICATION_CREATOR) || resourceTypes.isQualifierPresent(Qualifiers.APP))
- .filter(s -> !s.equals(OrganizationPermission.PORTFOLIO_CREATOR) || resourceTypes.isQualifierPresent(Qualifiers.VIEW))
- .collect(toList()));
- projectPermissions = ImmutableList.copyOf(ALL_PROJECT_PERMISSIONS.stream()
- .filter(s -> !s.equals(OrganizationPermission.APPLICATION_CREATOR.getKey()) || resourceTypes.isQualifierPresent(Qualifiers.APP))
- .filter(s -> !s.equals(OrganizationPermission.PORTFOLIO_CREATOR.getKey()) || resourceTypes.isQualifierPresent(Qualifiers.VIEW))
- .collect(toList()));
- }
-
- /**
- * Return an immutable Set of all organization permissions
- */
- @Override
- public List<OrganizationPermission> getAllOrganizationPermissions() {
- return globalPermissions;
- }
-
- /**
- * Return an immutable Set of all project permissions
- */
- @Override
- public List<String> getAllProjectPermissions() {
- return projectPermissions;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ProjectId.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ProjectId.java
deleted file mode 100644
index 0fb1941e3b8..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/ProjectId.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.permission;
-
-import javax.annotation.concurrent.Immutable;
-import org.sonar.db.component.ComponentDto;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * Reference to a project by its db id or uuid. The field "id" should
- * be removed as soon as backend is fully based on uuids.
- *
- */
-@Immutable
-public class ProjectId {
-
- private final long id;
- private final String uuid;
- private final boolean isPrivate;
-
- public ProjectId(ComponentDto project) {
- this.id = requireNonNull(project.getId());
- this.uuid = requireNonNull(project.uuid());
- this.isPrivate = project.isPrivate();
- }
-
- public long getId() {
- return id;
- }
-
- public String getUuid() {
- return uuid;
- }
-
- public boolean isPrivate() {
- return isPrivate;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/RequestValidator.java b/server/sonar-server/src/main/java/org/sonar/server/permission/RequestValidator.java
deleted file mode 100644
index 8fe5e6ba069..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/RequestValidator.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.permission;
-
-import com.google.common.base.Joiner;
-import java.util.Set;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-import java.util.stream.Collectors;
-import javax.annotation.Nullable;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypes;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.exceptions.BadRequestException;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static java.lang.String.format;
-import static org.sonar.server.exceptions.BadRequestException.checkRequest;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY_PATTERN;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
-
-public class RequestValidator {
- public static final String MSG_TEMPLATE_WITH_SAME_NAME = "A template with the name '%s' already exists (case insensitive).";
- private final PermissionService permissionService;
- private final String allProjectsPermissionsOnOneLine;
-
- public RequestValidator(PermissionService permissionService) {
- this.permissionService = permissionService;
- allProjectsPermissionsOnOneLine = Joiner.on(", ").join(permissionService.getAllProjectPermissions());
- }
-
- public String validateProjectPermission(String permission) {
- BadRequestException.checkRequest(permissionService.getAllProjectPermissions().contains(permission),
- String.format("The '%s' parameter for project permissions must be one of %s. '%s' was passed.", PARAM_PERMISSION,
- allProjectsPermissionsOnOneLine, permission));
- return permission;
- }
-
- public static void validateGlobalPermission(String permission) {
- checkRequest(GlobalPermissions.ALL.contains(permission),
- format("The '%s' parameter for global permissions must be one of %s. '%s' was passed.", PARAM_PERMISSION, GlobalPermissions.ALL_ON_ONE_LINE, permission));
- }
-
- public static void validateNotAnyoneAndAdminPermission(String permission, GroupIdOrAnyone group) {
- checkRequest(!GlobalPermissions.SYSTEM_ADMIN.equals(permission) || !group.isAnyone(),
- format("It is not possible to add the '%s' permission to group 'Anyone'.", permission));
- }
-
- public static void validateQualifier(@Nullable String qualifier, ResourceTypes resourceTypes) {
- if (qualifier == null) {
- return;
- }
- Set<String> rootQualifiers = resourceTypes.getRoots().stream()
- .map(ResourceType::getQualifier)
- .collect(Collectors.toSet());
- checkRequest(rootQualifiers.contains(qualifier),
- format("The '%s' parameter must be one of %s. '%s' was passed.", PARAM_QUALIFIER, rootQualifiers, qualifier));
- }
-
- public static void validateProjectPattern(@Nullable String projectPattern) {
- if (isNullOrEmpty(projectPattern)) {
- return;
- }
-
- try {
- Pattern.compile(projectPattern);
- } catch (PatternSyntaxException e) {
- throw BadRequestException.create(format("The '%s' parameter must be a valid Java regular expression. '%s' was passed", PARAM_PROJECT_KEY_PATTERN, projectPattern));
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/UserId.java b/server/sonar-server/src/main/java/org/sonar/server/permission/UserId.java
deleted file mode 100644
index 4c859a29322..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/UserId.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.permission;
-
-import javax.annotation.concurrent.Immutable;
-import org.sonar.db.user.UserDto;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * Reference a user by his technical (db) id or functional login.
- * This is temporary class as long as services and DAOs do not
- * use only technical id.
- */
-@Immutable
-public class UserId {
-
- private final int id;
- private final String login;
-
- public UserId(int userId, String login) {
- this.id = userId;
- this.login = requireNonNull(login);
- }
-
- public int getId() {
- return id;
- }
-
- public String getLogin() {
- return login;
- }
-
- public static UserId from(UserDto dto) {
- return new UserId(dto.getId(), dto.getLogin());
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
deleted file mode 100644
index 22f3e451a97..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.platform;
-
-import org.sonar.core.platform.ComponentContainer;
-
-public interface Platform {
- void doStart();
-
- Status status();
-
- ComponentContainer getContainer();
-
- enum Status {
- BOOTING, SAFEMODE, STARTING, UP
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotification.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotification.java
deleted file mode 100644
index ee7c4cb8b54..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotification.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import org.sonar.api.notifications.Notification;
-
-public class BuiltInQPChangeNotification extends Notification {
- static final String TYPE = "built-in-quality-profiles";
-
- public BuiltInQPChangeNotification() {
- super(TYPE);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationBuilder.java
deleted file mode 100644
index 4115d0641ba..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationBuilder.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.IntStream;
-import org.sonar.api.notifications.Notification;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.Integer.parseInt;
-import static java.lang.Long.parseLong;
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-
-public class BuiltInQPChangeNotificationBuilder {
-
- private static final String NUMBER_OF_PROFILES = "numberOfProfiles";
- private static final String PROFILE_NAME = ".profileName";
- private static final String LANGUAGE_KEY = ".languageKey";
- private static final String LANGUAGE_NAME = ".languageName";
- private static final String NEW_RULES = ".newRules";
- private static final String UPDATED_RULES = ".updatedRules";
- private static final String REMOVED_RULES = ".removedRules";
- private static final String START_DATE = ".startDate";
- private static final String END_DATE = ".endDate";
-
- private final List<Profile> profiles = new ArrayList<>();
-
- public BuiltInQPChangeNotificationBuilder addProfile(Profile profile) {
- profiles.add(profile);
- return this;
- }
-
- public BuiltInQPChangeNotification build() {
- BuiltInQPChangeNotification notification = new BuiltInQPChangeNotification();
- notification.setFieldValue(NUMBER_OF_PROFILES, String.valueOf(profiles.size()));
- AtomicInteger count = new AtomicInteger();
- profiles.forEach(profile -> {
- int index = count.getAndIncrement();
- notification.setFieldValue(index + PROFILE_NAME, profile.getProfileName());
- notification.setFieldValue(index + LANGUAGE_KEY, profile.getLanguageKey());
- notification.setFieldValue(index + LANGUAGE_NAME, profile.getLanguageName());
- notification.setFieldValue(index + NEW_RULES, String.valueOf(profile.getNewRules()));
- notification.setFieldValue(index + UPDATED_RULES, String.valueOf(profile.getUpdatedRules()));
- notification.setFieldValue(index + REMOVED_RULES, String.valueOf(profile.getRemovedRules()));
- notification.setFieldValue(index + START_DATE, String.valueOf(profile.getStartDate()));
- notification.setFieldValue(index + END_DATE, String.valueOf(profile.getEndDate()));
- });
- return notification;
- }
-
- public static BuiltInQPChangeNotificationBuilder parse(Notification notification) {
- checkState(BuiltInQPChangeNotification.TYPE.equals(notification.getType()),
- "Expected notification of type %s but got %s", BuiltInQPChangeNotification.TYPE, notification.getType());
- BuiltInQPChangeNotificationBuilder notif = new BuiltInQPChangeNotificationBuilder();
- String numberOfProfilesText = notification.getFieldValue(NUMBER_OF_PROFILES);
- checkState(numberOfProfilesText != null, "Could not read the built-in quality profile notification");
- Integer numberOfProfiles = Integer.valueOf(numberOfProfilesText);
- IntStream.rangeClosed(0, numberOfProfiles - 1)
- .mapToObj(index -> Profile.newBuilder()
- .setProfileName(getNonNullFieldValue(notification, index + PROFILE_NAME))
- .setLanguageKey(getNonNullFieldValue(notification, index + LANGUAGE_KEY))
- .setLanguageName(getNonNullFieldValue(notification, index + LANGUAGE_NAME))
- .setNewRules(parseInt(getNonNullFieldValue(notification, index + NEW_RULES)))
- .setUpdatedRules(parseInt(getNonNullFieldValue(notification, index + UPDATED_RULES)))
- .setRemovedRules(parseInt(getNonNullFieldValue(notification, index + REMOVED_RULES)))
- .setStartDate(parseLong(getNonNullFieldValue(notification, index + START_DATE)))
- .setEndDate(parseLong(getNonNullFieldValue(notification, index + END_DATE)))
- .build())
- .forEach(notif::addProfile);
- return notif;
- }
-
- private static String getNonNullFieldValue(Notification notification, String key) {
- String value = notification.getFieldValue(key);
- return requireNonNull(value, format("Notification field '%s' is null", key));
- }
-
- public List<Profile> getProfiles() {
- return profiles;
- }
-
- public static class Profile {
- private final String profileName;
- private final String languageKey;
- private final String languageName;
- private final int newRules;
- private final int updatedRules;
- private final int removedRules;
- private final long startDate;
- private final long endDate;
-
- public Profile(Builder builder) {
- this.profileName = builder.profileName;
- this.languageKey = builder.languageKey;
- this.languageName = builder.languageName;
- this.newRules = builder.newRules;
- this.updatedRules = builder.updatedRules;
- this.removedRules = builder.removedRules;
- this.startDate = builder.startDate;
- this.endDate = builder.endDate;
- }
-
- public String getProfileName() {
- return profileName;
- }
-
- public String getLanguageKey() {
- return languageKey;
- }
-
- public String getLanguageName() {
- return languageName;
- }
-
- public int getNewRules() {
- return newRules;
- }
-
- public int getUpdatedRules() {
- return updatedRules;
- }
-
- public int getRemovedRules() {
- return removedRules;
- }
-
- public long getStartDate() {
- return startDate;
- }
-
- public long getEndDate() {
- return endDate;
- }
-
- public static Builder newBuilder() {
- return new Builder();
- }
-
- public static class Builder {
- private String profileName;
- private String languageKey;
- private String languageName;
- private int newRules;
- private int updatedRules;
- private int removedRules;
- private long startDate;
- private long endDate;
-
- private Builder() {
- }
-
- public Builder setLanguageKey(String languageKey) {
- this.languageKey = requireNonNull(languageKey, "languageKEy should not be null");
- return this;
- }
-
- public Builder setLanguageName(String languageName) {
- this.languageName = requireNonNull(languageName, "languageName should not be null");
- return this;
- }
-
- public Builder setProfileName(String profileName) {
- this.profileName = requireNonNull(profileName, "profileName should not be null");
- return this;
- }
-
- public Builder setNewRules(int newRules) {
- checkState(newRules >= 0, "newRules should not be negative");
- this.newRules = newRules;
- return this;
- }
-
- public Builder setUpdatedRules(int updatedRules) {
- checkState(updatedRules >= 0, "updatedRules should not be negative");
- this.updatedRules = updatedRules;
- return this;
- }
-
- public Builder setRemovedRules(int removedRules) {
- checkState(removedRules >= 0, "removedRules should not be negative");
- this.removedRules = removedRules;
- return this;
- }
-
- public Builder setStartDate(long startDate) {
- this.startDate = startDate;
- return this;
- }
-
- public Builder setEndDate(long endDate) {
- this.endDate = endDate;
- return this;
- }
-
- public Profile build() {
- return new Profile(this);
- }
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationHandler.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationHandler.java
deleted file mode 100644
index 302ba14ad9b..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationHandler.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.Collection;
-import java.util.Optional;
-import java.util.Set;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.server.notification.EmailNotificationHandler;
-import org.sonar.server.notification.NotificationDispatcherMetadata;
-import org.sonar.server.notification.email.EmailNotificationChannel;
-import org.sonar.server.notification.email.EmailNotificationChannel.EmailDeliveryRequest;
-
-import static org.sonar.core.util.stream.MoreCollectors.toSet;
-
-public class BuiltInQPChangeNotificationHandler extends EmailNotificationHandler<BuiltInQPChangeNotification> {
- private final DbClient dbClient;
-
- public BuiltInQPChangeNotificationHandler(DbClient dbClient, EmailNotificationChannel emailNotificationChannel) {
- super(emailNotificationChannel);
- this.dbClient = dbClient;
- }
-
- @Override
- public Optional<NotificationDispatcherMetadata> getMetadata() {
- return Optional.empty();
- }
-
- @Override
- public Class<BuiltInQPChangeNotification> getNotificationClass() {
- return BuiltInQPChangeNotification.class;
- }
-
- @Override
- public Set<EmailDeliveryRequest> toEmailDeliveryRequests(Collection<BuiltInQPChangeNotification> notifications) {
- try (DbSession session = dbClient.openSession(false)) {
- return dbClient.authorizationDao()
- .selectQualityProfileAdministratorLogins(session)
- .stream()
- .flatMap(t -> notifications.stream().map(notification -> new EmailDeliveryRequest(t.getEmail(), notification)))
- .collect(toSet());
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTemplate.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTemplate.java
deleted file mode 100644
index ccc644b02a1..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTemplate.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.Comparator;
-import java.util.Date;
-import javax.annotation.CheckForNull;
-import org.sonar.api.notifications.Notification;
-import org.sonar.api.platform.Server;
-import org.sonar.server.issue.notification.EmailMessage;
-import org.sonar.server.issue.notification.EmailTemplate;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.sonar.api.utils.DateUtils.formatDate;
-import static org.sonar.server.qualityprofile.BuiltInQPChangeNotificationBuilder.Profile;
-import static org.sonar.server.qualityprofile.BuiltInQPChangeNotificationBuilder.parse;
-
-public class BuiltInQPChangeNotificationTemplate implements EmailTemplate {
-
- private final Server server;
-
- public BuiltInQPChangeNotificationTemplate(Server server) {
- this.server = server;
- }
-
- @Override
- @CheckForNull
- public EmailMessage format(Notification notification) {
- if (!BuiltInQPChangeNotification.TYPE.equals(notification.getType())) {
- return null;
- }
-
- BuiltInQPChangeNotificationBuilder profilesNotification = parse(notification);
- StringBuilder message = new StringBuilder("The following built-in profiles have been updated:\n\n");
- profilesNotification.getProfiles().stream()
- .sorted(Comparator.comparing(Profile::getLanguageName).thenComparing(Profile::getProfileName))
- .forEach(profile -> {
- message.append("\"")
- .append(profile.getProfileName())
- .append("\" - ")
- .append(profile.getLanguageName())
- .append(": ")
- .append(server.getPublicRootUrl()).append("/profiles/changelog?language=")
- .append(profile.getLanguageKey())
- .append("&name=")
- .append(encode(profile.getProfileName()))
- .append("&since=")
- .append(formatDate(new Date(profile.getStartDate())))
- .append("&to=")
- .append(formatDate(new Date(profile.getEndDate())))
- .append("\n");
- int newRules = profile.getNewRules();
- if (newRules > 0) {
- message.append(" ").append(newRules).append(" new rule")
- .append(plural(newRules))
- .append('\n');
- }
- int updatedRules = profile.getUpdatedRules();
- if (updatedRules > 0) {
- message.append(" ").append(updatedRules).append(" rule")
- .append(updatedRules > 1 ? "s have been updated" : " has been updated")
- .append("\n");
- }
- int removedRules = profile.getRemovedRules();
- if (removedRules > 0) {
- message.append(" ").append(removedRules).append(" rule")
- .append(plural(removedRules))
- .append(" removed\n");
- }
- message.append("\n");
- });
-
- message.append("This is a good time to review your quality profiles and update them to benefit from the latest evolutions: ");
- message.append(server.getPublicRootUrl()).append("/profiles");
-
- // And finally return the email that will be sent
- return new EmailMessage()
- .setMessageId(BuiltInQPChangeNotification.TYPE)
- .setSubject("Built-in quality profiles have been updated")
- .setPlainTextMessage(message.toString());
- }
-
- private static String plural(int count) {
- return count > 1 ? "s" : "";
- }
-
- public String encode(String text) {
- try {
- return URLEncoder.encode(text, UTF_8.name());
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException(String.format("Cannot encode %s", text), e);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfile.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfile.java
deleted file mode 100644
index 96750f5976c..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfile.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.List;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
-
-/**
- * Represent a Quality Profile as computed from {@link BuiltInQualityProfilesDefinition} provided by installed plugins.
- */
-@Immutable
-public final class BuiltInQProfile {
- private final QProfileName qProfileName;
- private final boolean isDefault;
- private final List<ActiveRule> activeRules;
-
- private BuiltInQProfile(Builder builder) {
- this.qProfileName = new QProfileName(builder.language, builder.name);
- this.isDefault = builder.declaredDefault || builder.computedDefault;
- this.activeRules = ImmutableList.copyOf(builder.activeRules);
- }
-
- public String getName() {
- return qProfileName.getName();
- }
-
- public String getLanguage() {
- return qProfileName.getLanguage();
- }
-
- public QProfileName getQProfileName() {
- return qProfileName;
- }
-
- public boolean isDefault() {
- return isDefault;
- }
-
- public List<ActiveRule> getActiveRules() {
- return activeRules;
- }
-
- static final class ActiveRule {
- private final int ruleId;
- private final BuiltInQualityProfilesDefinition.BuiltInActiveRule builtIn;
-
- ActiveRule(int ruleId, BuiltInQualityProfilesDefinition.BuiltInActiveRule builtIn) {
- this.ruleId = ruleId;
- this.builtIn = builtIn;
- }
-
- public int getRuleId() {
- return ruleId;
- }
-
- public RuleKey getRuleKey() {
- return RuleKey.of(builtIn.repoKey(), builtIn.ruleKey());
- }
-
- public BuiltInQualityProfilesDefinition.BuiltInActiveRule getBuiltIn() {
- return builtIn;
- }
- }
-
- static final class Builder {
- private String language;
- private String name;
- private boolean declaredDefault;
- private boolean computedDefault;
- private final List<ActiveRule> activeRules = new ArrayList<>();
-
- public Builder setLanguage(String language) {
- this.language = language;
- return this;
- }
-
- Builder setName(String name) {
- this.name = name;
- return this;
- }
-
- String getName() {
- return name;
- }
-
- Builder setDeclaredDefault(boolean declaredDefault) {
- this.declaredDefault = declaredDefault;
- return this;
- }
-
- boolean isDeclaredDefault() {
- return declaredDefault;
- }
-
- Builder setComputedDefault(boolean flag) {
- computedDefault = flag;
- return this;
- }
-
- Builder addRule(BuiltInQualityProfilesDefinition.BuiltInActiveRule rule, int ruleId) {
- this.activeRules.add(new ActiveRule(ruleId, rule));
- return this;
- }
-
- Builder addRule(ActiveRule activeRule) {
- this.activeRules.add(activeRule);
- return this;
- }
-
- BuiltInQProfile build() {
- return new BuiltInQProfile(this);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileDefinitionsBridge.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileDefinitionsBridge.java
deleted file mode 100644
index 58feb3b73f1..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileDefinitionsBridge.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.collect.ImmutableList;
-import java.util.List;
-import org.sonar.api.profiles.ProfileDefinition;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.rules.ActiveRuleParam;
-import org.sonar.api.rules.RulePriority;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
-import org.sonar.api.utils.ValidationMessages;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.utils.log.Profiler;
-
-import static java.lang.String.format;
-
-/**
- * Bridge between deprecated {@link ProfileDefinition} API and new {@link BuiltInQualityProfilesDefinition}
- */
-public class BuiltInQProfileDefinitionsBridge implements BuiltInQualityProfilesDefinition {
- private static final Logger LOGGER = Loggers.get(BuiltInQProfileDefinitionsBridge.class);
-
- private final List<ProfileDefinition> definitions;
-
- /**
- * Requires for pico container when no {@link ProfileDefinition} is defined at all
- */
- public BuiltInQProfileDefinitionsBridge() {
- this(new ProfileDefinition[0]);
- }
-
- public BuiltInQProfileDefinitionsBridge(ProfileDefinition... definitions) {
- this.definitions = ImmutableList.copyOf(definitions);
- }
-
- @Override
- public void define(Context context) {
- Profiler profiler = Profiler.create(Loggers.get(getClass()));
- for (ProfileDefinition definition : definitions) {
- profiler.start();
- ValidationMessages validation = ValidationMessages.create();
- RulesProfile profile = definition.createProfile(validation);
- validation.log(LOGGER);
- if (profile == null) {
- profiler.stopDebug(format("Loaded definition %s that return no profile", definition));
- } else {
- if (!validation.hasErrors()) {
- define(context, profile);
- }
- profiler.stopDebug(format("Loaded deprecated profile definition %s for language %s", profile.getName(), profile.getLanguage()));
- }
- }
- }
-
- private static void define(Context context, RulesProfile profile) {
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile(profile.getName(), profile.getLanguage())
- .setDefault(profile.getDefaultProfile().booleanValue());
-
- for (org.sonar.api.rules.ActiveRule ar : profile.getActiveRules()) {
- NewBuiltInActiveRule newActiveRule = newQp.activateRule(ar.getRepositoryKey(), ar.getRuleKey());
- RulePriority overriddenSeverity = ar.getOverriddenSeverity();
- if (overriddenSeverity != null) {
- newActiveRule.overrideSeverity(overriddenSeverity.name());
- }
- for (ActiveRuleParam param : ar.getActiveRuleParams()) {
- newActiveRule.overrideParam(param.getKey(), param.getValue());
- }
- }
- newQp.done();
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileInsert.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileInsert.java
deleted file mode 100644
index 52d52009f03..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileInsert.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import org.sonar.db.DbSession;
-
-public interface BuiltInQProfileInsert {
- /**
- * Persist a new built-in profile and associate it to all existing organizations.
- * Db sessions are committed and Elasticsearch indices are updated..
- */
- void create(DbSession session, DbSession batchSession, BuiltInQProfile builtInQProfile);
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImpl.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImpl.java
deleted file mode 100644
index fab592130f1..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImpl.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
-import org.sonar.api.server.rule.RuleParamType;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.UuidFactory;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.qualityprofile.ActiveRuleDto;
-import org.sonar.db.qualityprofile.ActiveRuleKey;
-import org.sonar.db.qualityprofile.ActiveRuleParamDto;
-import org.sonar.db.qualityprofile.DefaultQProfileDto;
-import org.sonar.db.qualityprofile.OrgQProfileDto;
-import org.sonar.db.qualityprofile.RulesProfileDto;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.rule.RuleParamDto;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
-import org.sonar.server.util.TypeValidations;
-
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static com.google.common.collect.Lists.newArrayList;
-import static java.util.Objects.requireNonNull;
-
-public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert {
- private final DbClient dbClient;
- private final System2 system2;
- private final UuidFactory uuidFactory;
- private final TypeValidations typeValidations;
- private final ActiveRuleIndexer activeRuleIndexer;
- private RuleRepository ruleRepository;
-
- public BuiltInQProfileInsertImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory, TypeValidations typeValidations, ActiveRuleIndexer activeRuleIndexer) {
- this.dbClient = dbClient;
- this.system2 = system2;
- this.uuidFactory = uuidFactory;
- this.typeValidations = typeValidations;
- this.activeRuleIndexer = activeRuleIndexer;
- }
-
- @Override
- public void create(DbSession dbSession, DbSession batchDbSession, BuiltInQProfile builtInQProfile) {
- initRuleRepository(batchDbSession);
-
- Date now = new Date(system2.now());
- RulesProfileDto ruleProfile = insertRulesProfile(dbSession, builtInQProfile, now);
-
- List<ActiveRuleChange> changes = builtInQProfile.getActiveRules()
- .stream()
- .map(activeRule -> insertActiveRule(dbSession, ruleProfile, activeRule, now.getTime()))
- .collect(MoreCollectors.toList());
-
- changes.forEach(change -> dbClient.qProfileChangeDao().insert(batchDbSession, change.toDto(null)));
-
- associateToOrganizations(dbSession, batchDbSession, builtInQProfile, ruleProfile);
-
- // TODO batch statements should be executed through dbSession
- batchDbSession.commit();
-
- activeRuleIndexer.commitAndIndex(dbSession, changes);
- }
-
- private void associateToOrganizations(DbSession dbSession, DbSession batchDbSession, BuiltInQProfile builtIn, RulesProfileDto rulesProfileDto) {
- List<String> orgUuids = dbClient.organizationDao().selectAllUuids(dbSession);
- Set<String> orgUuidsWithoutDefault = dbClient.defaultQProfileDao().selectUuidsOfOrganizationsWithoutDefaultProfile(dbSession, builtIn.getLanguage());
-
- List<DefaultQProfileDto> defaults = new ArrayList<>();
- orgUuids.forEach(orgUuid -> {
- OrgQProfileDto dto = new OrgQProfileDto()
- .setOrganizationUuid(orgUuid)
- .setRulesProfileUuid(rulesProfileDto.getKee())
- .setUuid(uuidFactory.create());
-
- if (builtIn.isDefault() && orgUuidsWithoutDefault.contains(orgUuid)) {
- // rows of table default_qprofiles must be inserted after
- // in order to benefit from batch SQL inserts
- defaults.add(new DefaultQProfileDto()
- .setQProfileUuid(dto.getUuid())
- .setOrganizationUuid(orgUuid)
- .setLanguage(builtIn.getLanguage()));
- }
-
- dbClient.qualityProfileDao().insert(batchDbSession, dto);
- });
-
- defaults.forEach(defaultQProfileDto -> dbClient.defaultQProfileDao().insertOrUpdate(dbSession, defaultQProfileDto));
- }
-
- private void initRuleRepository(DbSession dbSession) {
- if (ruleRepository == null) {
- ruleRepository = new RuleRepository(dbClient, dbSession);
- }
- }
-
- private RulesProfileDto insertRulesProfile(DbSession dbSession, BuiltInQProfile builtIn, Date now) {
- RulesProfileDto dto = new RulesProfileDto()
- .setKee(uuidFactory.create())
- .setName(builtIn.getName())
- .setLanguage(builtIn.getLanguage())
- .setIsBuiltIn(true)
- .setRulesUpdatedAtAsDate(now);
- dbClient.qualityProfileDao().insert(dbSession, dto);
- return dto;
- }
-
- private ActiveRuleChange insertActiveRule(DbSession dbSession, RulesProfileDto rulesProfileDto, BuiltInQProfile.ActiveRule activeRule, long now) {
- RuleKey ruleKey = activeRule.getRuleKey();
- RuleDefinitionDto ruleDefinitionDto = ruleRepository.getDefinition(ruleKey)
- .orElseThrow(() -> new IllegalStateException("RuleDefinition not found for key " + ruleKey));
-
- ActiveRuleDto dto = new ActiveRuleDto();
- dto.setProfileId(rulesProfileDto.getId());
- dto.setRuleId(ruleDefinitionDto.getId());
- dto.setKey(ActiveRuleKey.of(rulesProfileDto, ruleDefinitionDto.getKey()));
- dto.setSeverity(firstNonNull(activeRule.getBuiltIn().overriddenSeverity(), ruleDefinitionDto.getSeverityString()));
- dto.setUpdatedAt(now);
- dto.setCreatedAt(now);
- dbClient.activeRuleDao().insert(dbSession, dto);
-
- List<ActiveRuleParamDto> paramDtos = insertActiveRuleParams(dbSession, activeRule, dto);
-
- ActiveRuleChange change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, dto, ruleDefinitionDto);
- change.setSeverity(dto.getSeverityString());
- paramDtos.forEach(paramDto -> change.setParameter(paramDto.getKey(), paramDto.getValue()));
- return change;
- }
-
- private List<ActiveRuleParamDto> insertActiveRuleParams(DbSession session, BuiltInQProfile.ActiveRule activeRule,
- ActiveRuleDto activeRuleDto) {
- Map<String, String> valuesByParamKey = activeRule.getBuiltIn().overriddenParams()
- .stream()
- .collect(MoreCollectors.uniqueIndex(BuiltInQualityProfilesDefinition.OverriddenParam::key, BuiltInQualityProfilesDefinition.OverriddenParam::overriddenValue));
- return ruleRepository.getRuleParams(activeRule.getRuleKey())
- .stream()
- .map(param -> {
- String activeRuleValue = valuesByParamKey.get(param.getName());
- return createParamDto(param, activeRuleValue == null ? param.getDefaultValue() : activeRuleValue);
- })
- .filter(Objects::nonNull)
- .peek(paramDto -> dbClient.activeRuleDao().insertParam(session, activeRuleDto, paramDto))
- .collect(MoreCollectors.toList());
- }
-
- @CheckForNull
- private ActiveRuleParamDto createParamDto(RuleParamDto param, @Nullable String value) {
- if (value == null) {
- return null;
- }
- ActiveRuleParamDto paramDto = ActiveRuleParamDto.createFor(param);
- paramDto.setValue(validateParam(param, value));
- return paramDto;
- }
-
- @CheckForNull
- private String validateParam(RuleParamDto ruleParam, String value) {
- RuleParamType ruleParamType = RuleParamType.parse(ruleParam.getType());
- if (ruleParamType.multiple()) {
- List<String> values = newArrayList(Splitter.on(",").split(value));
- typeValidations.validate(values, ruleParamType.type(), ruleParamType.values());
- } else {
- typeValidations.validate(value, ruleParamType.type(), ruleParamType.values());
- }
- return value;
- }
-
- private static class RuleRepository {
- private final Map<RuleKey, RuleDefinitionDto> definitions;
- private final Map<RuleKey, Set<RuleParamDto>> params;
-
- private RuleRepository(DbClient dbClient, DbSession session) {
- this.definitions = dbClient.ruleDao().selectAllDefinitions(session)
- .stream()
- .collect(Collectors.toMap(RuleDefinitionDto::getKey, Function.identity()));
- Map<Integer, RuleKey> ruleIdsByKey = definitions.values()
- .stream()
- .collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getId, RuleDefinitionDto::getKey));
- this.params = new HashMap<>(ruleIdsByKey.size());
- dbClient.ruleDao().selectRuleParamsByRuleKeys(session, definitions.keySet())
- .forEach(ruleParam -> params.compute(
- ruleIdsByKey.get(ruleParam.getRuleId()),
- (key, value) -> {
- if (value == null) {
- return ImmutableSet.of(ruleParam);
- }
- return ImmutableSet.copyOf(Sets.union(value, Collections.singleton(ruleParam)));
- }));
- }
-
- private Optional<RuleDefinitionDto> getDefinition(RuleKey ruleKey) {
- return Optional.ofNullable(definitions.get(requireNonNull(ruleKey, "RuleKey can't be null")));
- }
-
- private Set<RuleParamDto> getRuleParams(RuleKey ruleKey) {
- Set<RuleParamDto> res = params.get(requireNonNull(ruleKey, "RuleKey can't be null"));
- return res == null ? Collections.emptySet() : res;
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileLoader.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileLoader.java
deleted file mode 100644
index 9134b3a464b..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileLoader.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import org.picocontainer.Startable;
-
-/**
- * Startable added to {@link org.sonar.server.platform.platformlevel.PlatformLevelStartup} responsible for initializing
- * {@link BuiltInQProfileRepository}.
- */
-public class BuiltInQProfileLoader implements Startable {
- private final BuiltInQProfileRepository builtInQProfileRepository;
-
- public BuiltInQProfileLoader(BuiltInQProfileRepository builtInQProfileRepository) {
- this.builtInQProfileRepository = builtInQProfileRepository;
- }
-
- @Override
- public void start() {
- builtInQProfileRepository.initialize();
- }
-
- @Override
- public void stop() {
- // nothing to do
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepository.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepository.java
deleted file mode 100644
index b47ff98b3be..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepository.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.List;
-
-public interface BuiltInQProfileRepository {
- /**
- * Initializes the Repository.
- *
- * This method is intended to be called from a startup task
- * (see {@link org.sonar.server.platform.platformlevel.PlatformLevelStartup}).
- *
- * @throws IllegalStateException if called more then once
- */
- void initialize();
-
- /**
- * @return an immutable list
- *
- * @throws IllegalStateException if {@link #initialize()} has not been called
- */
- List<BuiltInQProfile> get();
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImpl.java
deleted file mode 100644
index 9473d574a04..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImpl.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.collect.ImmutableList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.annotation.Nullable;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInQualityProfile;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.utils.log.Profiler;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.rule.RuleDefinitionDto;
-
-import static com.google.common.base.Preconditions.checkState;
-
-public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository {
- private static final Logger LOGGER = Loggers.get(BuiltInQProfileRepositoryImpl.class);
- private static final String DEFAULT_PROFILE_NAME = "Sonar way";
-
- private final DbClient dbClient;
- private final Languages languages;
- private final List<BuiltInQualityProfilesDefinition> definitions;
- private List<BuiltInQProfile> qProfiles;
-
- /**
- * Requires for pico container when no {@link BuiltInQualityProfilesDefinition} is defined at all
- */
- public BuiltInQProfileRepositoryImpl(DbClient dbClient, Languages languages) {
- this(dbClient, languages, new BuiltInQualityProfilesDefinition[0]);
- }
-
- public BuiltInQProfileRepositoryImpl(DbClient dbClient, Languages languages, BuiltInQualityProfilesDefinition... definitions) {
- this.dbClient = dbClient;
- this.languages = languages;
- this.definitions = ImmutableList.copyOf(definitions);
- }
-
- @Override
- public void initialize() {
- checkState(qProfiles == null, "initialize must be called only once");
-
- Profiler profiler = Profiler.create(LOGGER).startInfo("Load quality profiles");
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- for (BuiltInQualityProfilesDefinition definition : definitions) {
- definition.define(context);
- }
- Map<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguage = validateAndClean(context);
- this.qProfiles = toFlatList(rulesProfilesByLanguage);
- ensureAllLanguagesHaveAtLeastOneBuiltInQP();
- profiler.stopDebug();
- }
-
- @Override
- public List<BuiltInQProfile> get() {
- checkState(qProfiles != null, "initialize must be called first");
-
- return qProfiles;
- }
-
- private void ensureAllLanguagesHaveAtLeastOneBuiltInQP() {
- Set<String> languagesWithBuiltInQProfiles = qProfiles.stream().map(BuiltInQProfile::getLanguage).collect(Collectors.toSet());
- Set<String> languagesWithoutBuiltInQProfiles = Arrays.stream(languages.all())
- .map(Language::getKey)
- .filter(key -> !languagesWithBuiltInQProfiles.contains(key))
- .collect(Collectors.toSet());
-
- checkState(languagesWithoutBuiltInQProfiles.isEmpty(), "The following languages have no built-in quality profiles: %s",
- languagesWithoutBuiltInQProfiles.stream().collect(Collectors.joining()));
- }
-
- private Map<String, Map<String, BuiltInQualityProfile>> validateAndClean(BuiltInQualityProfilesDefinition.Context context) {
- Map<String, Map<String, BuiltInQualityProfile>> profilesByLanguageAndName = context.profilesByLanguageAndName();
- profilesByLanguageAndName.entrySet()
- .removeIf(entry -> {
- String language = entry.getKey();
- if (languages.get(language) == null) {
- LOGGER.info("Language {} is not installed, related quality profiles are ignored", language);
- return true;
- }
- return false;
- });
-
- return profilesByLanguageAndName;
- }
-
- private List<BuiltInQProfile> toFlatList(Map<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguage) {
- if (rulesProfilesByLanguage.isEmpty()) {
- return Collections.emptyList();
- }
-
- try (DbSession dbSession = dbClient.openSession(false)) {
- Map<RuleKey, RuleDefinitionDto> rulesByRuleKey = dbClient.ruleDao().selectAllDefinitions(dbSession)
- .stream()
- .collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getKey));
- Map<String, List<BuiltInQProfile.Builder>> buildersByLanguage = rulesProfilesByLanguage
- .entrySet()
- .stream()
- .collect(MoreCollectors.uniqueIndex(
- Map.Entry::getKey,
- rulesProfilesByLanguageAndName -> toQualityProfileBuilders(rulesProfilesByLanguageAndName, rulesByRuleKey)));
- return buildersByLanguage
- .entrySet()
- .stream()
- .filter(BuiltInQProfileRepositoryImpl::ensureAtMostOneDeclaredDefault)
- .map(entry -> toQualityProfiles(entry.getValue()))
- .flatMap(Collection::stream)
- .collect(MoreCollectors.toList());
- }
- }
-
- /**
- * Creates {@link BuiltInQProfile.Builder} for each unique quality profile name for a given language.
- * Builders will have the following properties populated:
- * <ul>
- * <li>{@link BuiltInQProfile.Builder#language language}: key of the method's parameter</li>
- * <li>{@link BuiltInQProfile.Builder#name name}: {@link RulesProfile#getName()}</li>
- * <li>{@link BuiltInQProfile.Builder#declaredDefault declaredDefault}: {@code true} if at least one RulesProfile
- * with a given name has {@link RulesProfile#getDefaultProfile()} is {@code true}</li>
- * <li>{@link BuiltInQProfile.Builder#activeRules activeRules}: the concatenate of the active rules of all
- * RulesProfile with a given name</li>
- * </ul>
- */
- private static List<BuiltInQProfile.Builder> toQualityProfileBuilders(Map.Entry<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguageAndName,
- Map<RuleKey, RuleDefinitionDto> rulesByRuleKey) {
- String language = rulesProfilesByLanguageAndName.getKey();
- // use a LinkedHashMap to keep order of insertion of RulesProfiles
- Map<String, BuiltInQProfile.Builder> qualityProfileBuildersByName = new LinkedHashMap<>();
- for (BuiltInQualityProfile builtInProfile : rulesProfilesByLanguageAndName.getValue().values()) {
- qualityProfileBuildersByName.compute(
- builtInProfile.name(),
- (name, existingBuilder) -> updateOrCreateBuilder(language, existingBuilder, builtInProfile, rulesByRuleKey));
- }
- return ImmutableList.copyOf(qualityProfileBuildersByName.values());
- }
-
- /**
- * Fails if more than one {@link BuiltInQProfile.Builder#declaredDefault} is {@code true}, otherwise returns {@code true}.
- */
- private static boolean ensureAtMostOneDeclaredDefault(Map.Entry<String, List<BuiltInQProfile.Builder>> entry) {
- Set<String> declaredDefaultProfileNames = entry.getValue().stream()
- .filter(BuiltInQProfile.Builder::isDeclaredDefault)
- .map(BuiltInQProfile.Builder::getName)
- .collect(MoreCollectors.toSet());
- checkState(declaredDefaultProfileNames.size() <= 1, "Several Quality profiles are flagged as default for the language %s: %s", entry.getKey(), declaredDefaultProfileNames);
- return true;
- }
-
- private static BuiltInQProfile.Builder updateOrCreateBuilder(String language, @Nullable BuiltInQProfile.Builder existingBuilder, BuiltInQualityProfile builtInProfile,
- Map<RuleKey, RuleDefinitionDto> rulesByRuleKey) {
- BuiltInQProfile.Builder builder = createOrReuseBuilder(existingBuilder, language, builtInProfile);
- builder.setDeclaredDefault(builtInProfile.isDefault());
- builtInProfile.rules().forEach(builtInActiveRule -> {
- RuleKey ruleKey = RuleKey.of(builtInActiveRule.repoKey(), builtInActiveRule.ruleKey());
- RuleDefinitionDto ruleDefinition = rulesByRuleKey.get(ruleKey);
- checkState(ruleDefinition != null, "Rule with key '%s' not found", ruleKey);
- builder.addRule(builtInActiveRule, ruleDefinition.getId());
- });
- return builder;
- }
-
- private static BuiltInQProfile.Builder createOrReuseBuilder(@Nullable BuiltInQProfile.Builder existingBuilder, String language, BuiltInQualityProfile builtInProfile) {
- if (existingBuilder == null) {
- return new BuiltInQProfile.Builder()
- .setLanguage(language)
- .setName(builtInProfile.name());
- }
- return existingBuilder;
- }
-
- private static List<BuiltInQProfile> toQualityProfiles(List<BuiltInQProfile.Builder> builders) {
- if (builders.stream().noneMatch(BuiltInQProfile.Builder::isDeclaredDefault)) {
- Optional<BuiltInQProfile.Builder> sonarWayProfile = builders.stream().filter(builder -> builder.getName().equals(DEFAULT_PROFILE_NAME)).findFirst();
- if (sonarWayProfile.isPresent()) {
- sonarWayProfile.get().setComputedDefault(true);
- } else {
- builders.iterator().next().setComputedDefault(true);
- }
- }
- return builders.stream()
- .map(BuiltInQProfile.Builder::build)
- .collect(MoreCollectors.toList(builders.size()));
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdate.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdate.java
deleted file mode 100644
index 4992402a0d9..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdate.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.List;
-import org.sonar.db.DbSession;
-import org.sonar.db.qualityprofile.RulesProfileDto;
-
-public interface BuiltInQProfileUpdate {
- /**
- * Persist an existing built-in profile and associate it to all existing organizations.
- * Db session is committed and Elasticsearch indices are updated.
- */
- List<ActiveRuleChange> update(DbSession dbSession, BuiltInQProfile builtInQProfile, RulesProfileDto ruleProfile);
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImpl.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImpl.java
deleted file mode 100644
index b711c69c15b..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImpl.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Stream;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.qualityprofile.ActiveRuleDto;
-import org.sonar.db.qualityprofile.RulesProfileDto;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
-
-import static org.sonar.core.util.stream.MoreCollectors.toSet;
-
-public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate {
-
- private final DbClient dbClient;
- private final RuleActivator ruleActivator;
- private final ActiveRuleIndexer activeRuleIndexer;
-
- public BuiltInQProfileUpdateImpl(DbClient dbClient, RuleActivator ruleActivator, ActiveRuleIndexer activeRuleIndexer) {
- this.dbClient = dbClient;
- this.ruleActivator = ruleActivator;
- this.activeRuleIndexer = activeRuleIndexer;
- }
-
- public List<ActiveRuleChange> update(DbSession dbSession, BuiltInQProfile builtInDefinition, RulesProfileDto initialRuleProfile) {
- // Keep reference to all the activated rules before update
- Set<Integer> deactivatedRuleIds = dbClient.activeRuleDao().selectByRuleProfile(dbSession, initialRuleProfile)
- .stream()
- .map(ActiveRuleDto::getRuleId)
- .collect(MoreCollectors.toHashSet());
-
- // all rules, including those which are removed from built-in profile
- Set<Integer> ruleIds = Stream.concat(
- deactivatedRuleIds.stream(),
- builtInDefinition.getActiveRules().stream().map(BuiltInQProfile.ActiveRule::getRuleId))
- .collect(toSet());
-
- Collection<RuleActivation> activations = new ArrayList<>();
- for (BuiltInQProfile.ActiveRule ar : builtInDefinition.getActiveRules()) {
- RuleActivation activation = convert(ar);
- activations.add(activation);
- deactivatedRuleIds.remove(activation.getRuleId());
- }
-
- RuleActivationContext context = ruleActivator.createContextForBuiltInProfile(dbSession, initialRuleProfile, ruleIds);
- List<ActiveRuleChange> changes = new ArrayList<>();
- for (RuleActivation activation : activations) {
- changes.addAll(ruleActivator.activate(dbSession, activation, context));
- }
-
- // these rules are no longer part of the built-in profile
- deactivatedRuleIds.forEach(ruleKey -> changes.addAll(ruleActivator.deactivate(dbSession, context, ruleKey, false)));
-
- activeRuleIndexer.commitAndIndex(dbSession, changes);
- return changes;
- }
-
- private static RuleActivation convert(BuiltInQProfile.ActiveRule ar) {
- Map<String, String> params = ar.getBuiltIn().overriddenParams().stream()
- .collect(MoreCollectors.uniqueIndex(BuiltInQualityProfilesDefinition.OverriddenParam::key, BuiltInQualityProfilesDefinition.OverriddenParam::overriddenValue));
- return RuleActivation.create(ar.getRuleId(), ar.getBuiltIn().overriddenSeverity(), params);
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesUpdateListener.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesUpdateListener.java
deleted file mode 100644
index e37e84297db..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesUpdateListener.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.collect.Multimap;
-import java.util.Collection;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.server.notification.NotificationManager;
-import org.sonar.server.qualityprofile.BuiltInQPChangeNotificationBuilder.Profile;
-
-import static org.sonar.core.config.CorePropertyDefinitions.DISABLE_NOTIFICATION_ON_BUILT_IN_QPROFILES;
-import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
-import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
-import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.UPDATED;
-
-public class BuiltInQualityProfilesUpdateListener {
-
- private final NotificationManager notificationManager;
- private final Languages languages;
- private final Configuration config;
-
- public BuiltInQualityProfilesUpdateListener(NotificationManager notificationManager, Languages languages, Configuration config) {
- this.notificationManager = notificationManager;
- this.languages = languages;
- this.config = config;
- }
-
- void onChange(Multimap<QProfileName, ActiveRuleChange> changedProfiles, long startDate, long endDate) {
- if (config.getBoolean(DISABLE_NOTIFICATION_ON_BUILT_IN_QPROFILES).orElse(false)) {
- return;
- }
-
- BuiltInQPChangeNotificationBuilder builder = new BuiltInQPChangeNotificationBuilder();
- changedProfiles.keySet().stream()
- .map(changedProfile -> {
- String profileName = changedProfile.getName();
- Language language = languages.get(changedProfile.getLanguage());
- Collection<ActiveRuleChange> activeRuleChanges = changedProfiles.get(changedProfile);
- int newRules = (int) activeRuleChanges.stream().map(ActiveRuleChange::getType).filter(ACTIVATED::equals).count();
- int updatedRules = (int) activeRuleChanges.stream().map(ActiveRuleChange::getType).filter(UPDATED::equals).count();
- int removedRules = (int) activeRuleChanges.stream().map(ActiveRuleChange::getType).filter(DEACTIVATED::equals).count();
- return Profile.newBuilder()
- .setProfileName(profileName)
- .setLanguageKey(language.getKey())
- .setLanguageName(language.getName())
- .setNewRules(newRules)
- .setUpdatedRules(updatedRules)
- .setRemovedRules(removedRules)
- .setStartDate(startDate)
- .setEndDate(endDate)
- .build();
- })
- .forEach(builder::addProfile);
-
- notificationManager.scheduleForSending(builder.build());
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/DescendantProfilesSupplier.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/DescendantProfilesSupplier.java
deleted file mode 100644
index ef073340e7a..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/DescendantProfilesSupplier.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.Collection;
-import org.sonar.db.qualityprofile.ActiveRuleDto;
-import org.sonar.db.qualityprofile.ActiveRuleParamDto;
-import org.sonar.db.qualityprofile.QProfileDto;
-
-@FunctionalInterface
-public interface DescendantProfilesSupplier {
-
- Result get(Collection<QProfileDto> profiles, Collection<Integer> ruleIds);
-
- final class Result {
- private final Collection<QProfileDto> profiles;
- private final Collection<ActiveRuleDto> activeRules;
- private final Collection<ActiveRuleParamDto> activeRuleParams;
-
- public Result(Collection<QProfileDto> profiles, Collection<ActiveRuleDto> activeRules, Collection<ActiveRuleParamDto> activeRuleParams) {
- this.profiles = profiles;
- this.activeRules = activeRules;
- this.activeRuleParams = activeRuleParams;
- }
-
- public Collection<QProfileDto> getProfiles() {
- return profiles;
- }
-
- public Collection<ActiveRuleDto> getActiveRules() {
- return activeRules;
- }
-
- public Collection<ActiveRuleParamDto> getActiveRuleParams() {
- return activeRuleParams;
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileName.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileName.java
deleted file mode 100644
index 8b134c00ece..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileName.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import javax.annotation.Nullable;
-
-public class QProfileName {
- private final String lang;
- private final String name;
-
- public QProfileName(String lang, String name) {
- this.lang = lang;
- this.name = name;
- }
-
- public String getLanguage() {
- return lang;
- }
-
- public String getName() {
- return name;
- }
-
- public static QProfileName createFor(String lang, String name){
- return new QProfileName(lang, name);
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- QProfileName that = (QProfileName) o;
- if (!lang.equals(that.lang)) {
- return false;
- }
- return name.equals(that.name);
- }
-
- @Override
- public int hashCode() {
- int result = lang.hashCode();
- result = 31 * result + name.hashCode();
- return result;
- }
-
- @Override
- public String toString() {
- return String.format("%s/%s", lang, name);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java
deleted file mode 100644
index 106fd158b26..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.base.Strings;
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.rule.Severity;
-
-/**
- * The request for activation.
- */
-@Immutable
-public class RuleActivation {
-
- private final int ruleId;
- private final boolean reset;
- private final String severity;
- private final Map<String, String> parameters = new HashMap<>();
-
- private RuleActivation(int ruleId, boolean reset, @Nullable String severity, @Nullable Map<String, String> parameters) {
- this.ruleId = ruleId;
- this.reset = reset;
- this.severity = severity;
- if (severity != null && !Severity.ALL.contains(severity)) {
- throw new IllegalArgumentException("Unknown severity: " + severity);
- }
- if (parameters != null) {
- for (Map.Entry<String, String> entry : parameters.entrySet()) {
- this.parameters.put(entry.getKey(), Strings.emptyToNull(entry.getValue()));
- }
- }
- }
-
- public static RuleActivation createReset(int ruleId) {
- return new RuleActivation(ruleId, true, null, null);
- }
-
- public static RuleActivation create(int ruleId, @Nullable String severity, @Nullable Map<String, String> parameters) {
- return new RuleActivation(ruleId, false, severity, parameters);
- }
-
- public static RuleActivation create(int ruleId) {
- return create(ruleId, null, null);
- }
-
- /**
- * Optional severity. Use the parent severity or default rule severity if null.
- */
- @CheckForNull
- public String getSeverity() {
- return severity;
- }
-
- public int getRuleId() {
- return ruleId;
- }
-
- @CheckForNull
- public String getParameter(String key) {
- return parameters.get(key);
- }
-
- public boolean hasParameter(String key) {
- return parameters.containsKey(key);
- }
-
- public boolean isReset() {
- return reset;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivationContext.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivationContext.java
deleted file mode 100644
index 28a55cdb37f..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivationContext.java
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ListMultimap;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-import javax.annotation.CheckForNull;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.db.qualityprofile.ActiveRuleDto;
-import org.sonar.db.qualityprofile.ActiveRuleKey;
-import org.sonar.db.qualityprofile.ActiveRuleParamDto;
-import org.sonar.db.qualityprofile.QProfileDto;
-import org.sonar.db.qualityprofile.RulesProfileDto;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.rule.RuleParamDto;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.core.util.stream.MoreCollectors.index;
-import static org.sonar.core.util.stream.MoreCollectors.toArrayList;
-import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
-import static org.sonar.server.exceptions.BadRequestException.checkRequest;
-
-/**
- * Cache of the data required to activate/deactivate
- * multiple rules on a Quality profile, including
- * the rule definitions, the rule parameters, the tree
- * of profiles hierarchy and its related active rules.
- */
-class RuleActivationContext {
-
- private final long date;
-
- // The profile that is initially targeted by the operation
- private final RulesProfileDto baseRulesProfile;
-
- private final Map<String, QProfileDto> profilesByUuid = new HashMap<>();
- private final ListMultimap<String, QProfileDto> profilesByParentUuid = ArrayListMultimap.create();
-
- // The rules/active rules involved in the group of activations/de-activations
- private final Map<Integer, RuleWrapper> rulesById = new HashMap<>();
- private final Map<ActiveRuleKey, ActiveRuleWrapper> activeRulesByKey = new HashMap<>();
-
- // Cursors used to move in the rules and in the tree of profiles.
-
- private RulesProfileDto currentRulesProfile;
- // Cardinality is zero-to-many when cursor is on a built-in rules profile,
- // otherwise it's always one, and only one (cursor on descendants or on non-built-in base profile).
- private Collection<QProfileDto> currentProfiles;
- private RuleWrapper currentRule;
- private ActiveRuleWrapper currentActiveRule;
- private ActiveRuleWrapper currentParentActiveRule;
-
- private boolean descendantsLoaded = false;
- private final DescendantProfilesSupplier descendantProfilesSupplier;
-
- private RuleActivationContext(Builder builder) {
- this.date = builder.date;
- this.descendantProfilesSupplier = builder.descendantProfilesSupplier;
-
- ListMultimap<Integer, RuleParamDto> paramsByRuleId = builder.ruleParams.stream().collect(index(RuleParamDto::getRuleId));
- for (RuleDefinitionDto rule : builder.rules) {
- RuleWrapper wrapper = new RuleWrapper(rule, paramsByRuleId.get(rule.getId()));
- rulesById.put(rule.getId(), wrapper);
- }
-
- this.baseRulesProfile = builder.baseRulesProfile;
- register(builder.profiles);
- register(builder.activeRules, builder.activeRuleParams);
- }
-
- private void register(Collection<QProfileDto> profiles) {
- for (QProfileDto profile : profiles) {
- profilesByUuid.put(profile.getKee(), profile);
- if (profile.getParentKee() != null) {
- profilesByParentUuid.put(profile.getParentKee(), profile);
- }
- }
- }
-
- private void register(Collection<ActiveRuleDto> activeRules, Collection<ActiveRuleParamDto> activeRuleParams) {
- ListMultimap<Integer, ActiveRuleParamDto> paramsByActiveRuleId = activeRuleParams.stream().collect(index(ActiveRuleParamDto::getActiveRuleId));
- for (ActiveRuleDto activeRule : activeRules) {
- ActiveRuleWrapper wrapper = new ActiveRuleWrapper(activeRule, paramsByActiveRuleId.get(activeRule.getId()));
- this.activeRulesByKey.put(activeRule.getKey(), wrapper);
- }
- }
-
- long getDate() {
- return date;
- }
-
- /**
- * The rule currently selected.
- */
- RuleWrapper getRule() {
- checkState(currentRule != null, "Rule has not been set yet");
- return currentRule;
- }
-
- @CheckForNull
- String getRequestedParamValue(RuleActivation request, String key) {
- if (currentRule.rule.isCustomRule()) {
- return null;
- }
- return request.getParameter(key);
- }
-
- boolean hasRequestedParamValue(RuleActivation request, String key) {
- return request.hasParameter(key);
- }
-
- /**
- * The rules profile being selected.
- */
- RulesProfileDto getRulesProfile() {
- checkState(currentRulesProfile != null, "Rule profile has not been set yet");
- return currentRulesProfile;
- }
-
- /**
- * The active rule related to the selected profile and rule.
- * @return null if the selected rule is not activated on the selected profile.
- * @see #getRulesProfile()
- * @see #getRule()
- */
- @CheckForNull
- ActiveRuleWrapper getActiveRule() {
- return currentActiveRule;
- }
-
- /**
- * The active rule related to the rule and the parent of the selected profile.
- * @return null if the selected rule is not activated on the parent profile.
- * @see #getRule()
- */
- @CheckForNull
- ActiveRuleWrapper getParentActiveRule() {
- return currentParentActiveRule;
- }
-
- /**
- * Whether the profile cursor is on the base profile or not.
- */
- boolean isCascading() {
- return currentRulesProfile != null && !currentRulesProfile.getKee().equals(baseRulesProfile.getKee());
- }
-
- /**
- * The profiles being selected. Can be zero or many if {@link #getRulesProfile()} is built-in.
- * Else the collection always contains a single profile.
- */
- Collection<QProfileDto> getProfiles() {
- checkState(currentProfiles != null, "Profiles have not been set yet");
- return currentProfiles;
- }
-
- /**
- * The children of {@link #getProfiles()}
- */
- Collection<QProfileDto> getChildProfiles() {
- loadDescendants();
- return getProfiles().stream()
- .flatMap(p -> profilesByParentUuid.get(p.getKee()).stream())
- .collect(Collectors.toList());
- }
-
- private void loadDescendants() {
- if (descendantsLoaded) {
- return;
- }
- Collection<QProfileDto> baseProfiles = profilesByUuid.values().stream()
- .filter(p -> p.getRulesProfileUuid().equals(baseRulesProfile.getKee()))
- .collect(toArrayList(profilesByUuid.size()));
- DescendantProfilesSupplier.Result result = descendantProfilesSupplier.get(baseProfiles, rulesById.keySet());
- register(result.getProfiles());
- register(result.getActiveRules(), result.getActiveRuleParams());
- descendantsLoaded = true;
- }
-
- /**
- * Move the cursor to the given rule and back to the base profile.
- */
- public void reset(int ruleId) {
- doSwitch(this.baseRulesProfile, ruleId);
- }
-
- /**
- * Moves cursor to a child profile
- */
- void selectChild(QProfileDto to) {
- checkState(!to.isBuiltIn());
- QProfileDto qp = requireNonNull(this.profilesByUuid.get(to.getKee()), () -> "No profile with uuid " + to.getKee());
-
- RulesProfileDto ruleProfile = RulesProfileDto.from(qp);
- doSwitch(ruleProfile, getRule().get().getId());
- }
-
- private void doSwitch(RulesProfileDto ruleProfile, int ruleId) {
- this.currentRule = rulesById.get(ruleId);
- checkRequest(this.currentRule != null, "Rule with ID %s not found", ruleId);
- RuleKey ruleKey = currentRule.get().getKey();
-
- checkRequest(ruleProfile.getLanguage().equals(currentRule.get().getLanguage()),
- "%s rule %s cannot be activated on %s profile %s", currentRule.get().getLanguage(), ruleKey, ruleProfile.getLanguage(), ruleProfile.getName());
- this.currentRulesProfile = ruleProfile;
- this.currentProfiles = profilesByUuid.values().stream()
- .filter(p -> p.getRulesProfileUuid().equals(ruleProfile.getKee()))
- .collect(Collectors.toList());
- this.currentActiveRule = this.activeRulesByKey.get(ActiveRuleKey.of(ruleProfile, ruleKey));
- this.currentParentActiveRule = this.currentProfiles.stream()
- .map(QProfileDto::getParentKee)
- .filter(Objects::nonNull)
- .map(profilesByUuid::get)
- .filter(Objects::nonNull)
- .findFirst()
- .map(profile -> activeRulesByKey.get(ActiveRuleKey.of(profile, ruleKey)))
- .orElse(null);
- }
-
- static final class Builder {
- private long date = System.currentTimeMillis();
- private RulesProfileDto baseRulesProfile;
- private Collection<RuleDefinitionDto> rules;
- private Collection<RuleParamDto> ruleParams;
- private Collection<QProfileDto> profiles;
- private Collection<ActiveRuleDto> activeRules;
- private Collection<ActiveRuleParamDto> activeRuleParams;
- private DescendantProfilesSupplier descendantProfilesSupplier;
-
- Builder setDate(long l) {
- this.date = l;
- return this;
- }
-
- Builder setBaseProfile(RulesProfileDto p) {
- this.baseRulesProfile = p;
- return this;
- }
-
- Builder setRules(Collection<RuleDefinitionDto> rules) {
- this.rules = rules;
- return this;
- }
-
- Builder setRuleParams(Collection<RuleParamDto> ruleParams) {
- this.ruleParams = ruleParams;
- return this;
- }
-
- /**
- * All the profiles involved in the activation workflow, including the
- * parent profile, even if it's not updated.
- */
- Builder setProfiles(Collection<QProfileDto> profiles) {
- this.profiles = profiles;
- return this;
- }
-
- Builder setActiveRules(Collection<ActiveRuleDto> activeRules) {
- this.activeRules = activeRules;
- return this;
- }
-
- Builder setActiveRuleParams(Collection<ActiveRuleParamDto> activeRuleParams) {
- this.activeRuleParams = activeRuleParams;
- return this;
- }
-
- Builder setDescendantProfilesSupplier(DescendantProfilesSupplier d) {
- this.descendantProfilesSupplier = d;
- return this;
- }
-
- RuleActivationContext build() {
- checkArgument(date > 0, "date is not set");
- requireNonNull(baseRulesProfile, "baseRulesProfile is null");
- requireNonNull(rules, "rules is null");
- requireNonNull(ruleParams, "ruleParams is null");
- requireNonNull(profiles, "profiles is null");
- requireNonNull(activeRules, "activeRules is null");
- requireNonNull(activeRuleParams, "activeRuleParams is null");
- requireNonNull(descendantProfilesSupplier, "descendantProfilesSupplier is null");
- return new RuleActivationContext(this);
- }
- }
-
- static final class RuleWrapper {
- private final RuleDefinitionDto rule;
- private final Map<String, RuleParamDto> paramsByKey;
-
- private RuleWrapper(RuleDefinitionDto rule, Collection<RuleParamDto> params) {
- this.rule = rule;
- this.paramsByKey = params.stream().collect(uniqueIndex(RuleParamDto::getName));
- }
-
- RuleDefinitionDto get() {
- return rule;
- }
-
- Collection<RuleParamDto> getParams() {
- return paramsByKey.values();
- }
-
- @CheckForNull
- RuleParamDto getParam(String key) {
- return paramsByKey.get(key);
- }
-
- @CheckForNull
- String getParamDefaultValue(String key) {
- RuleParamDto param = getParam(key);
- return param != null ? param.getDefaultValue() : null;
- }
- }
-
- static final class ActiveRuleWrapper {
- private final ActiveRuleDto activeRule;
- private final Map<String, ActiveRuleParamDto> paramsByKey;
-
- private ActiveRuleWrapper(ActiveRuleDto activeRule, Collection<ActiveRuleParamDto> params) {
- this.activeRule = activeRule;
- this.paramsByKey = params.stream().collect(uniqueIndex(ActiveRuleParamDto::getKey));
- }
-
- ActiveRuleDto get() {
- return activeRule;
- }
-
- Collection<ActiveRuleParamDto> getParams() {
- return paramsByKey.values();
- }
-
- @CheckForNull
- ActiveRuleParamDto getParam(String key) {
- return paramsByKey.get(key);
- }
-
- @CheckForNull
- String getParamValue(String key) {
- ActiveRuleParamDto param = paramsByKey.get(key);
- return param != null ? param.getValue() : null;
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
deleted file mode 100644
index 2b5a2f8e19f..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.base.Splitter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Stream;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.server.rule.RuleParamType;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.qualityprofile.ActiveRuleDao;
-import org.sonar.db.qualityprofile.ActiveRuleDto;
-import org.sonar.db.qualityprofile.ActiveRuleKey;
-import org.sonar.db.qualityprofile.ActiveRuleParamDto;
-import org.sonar.db.qualityprofile.OrgQProfileDto;
-import org.sonar.db.qualityprofile.QProfileDto;
-import org.sonar.db.qualityprofile.RulesProfileDto;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.rule.RuleParamDto;
-import org.sonar.server.qualityprofile.RuleActivationContext.ActiveRuleWrapper;
-import org.sonar.server.qualityprofile.RuleActivationContext.RuleWrapper;
-import org.sonar.server.user.UserSession;
-import org.sonar.server.util.TypeValidations;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.sonar.server.exceptions.BadRequestException.checkRequest;
-
-/**
- * Activation and deactivation of rules in Quality profiles
- */
-@ServerSide
-public class RuleActivator {
-
- private final System2 system2;
- private final DbClient db;
- private final TypeValidations typeValidations;
- private final UserSession userSession;
-
- public RuleActivator(System2 system2, DbClient db, TypeValidations typeValidations, UserSession userSession) {
- this.system2 = system2;
- this.db = db;
- this.typeValidations = typeValidations;
- this.userSession = userSession;
- }
-
- public List<ActiveRuleChange> activate(DbSession dbSession, RuleActivation activation, RuleActivationContext context) {
- context.reset(activation.getRuleId());
- return doActivate(dbSession, activation, context);
- }
-
- private List<ActiveRuleChange> doActivate(DbSession dbSession, RuleActivation activation, RuleActivationContext context) {
- RuleDefinitionDto rule = context.getRule().get();
- checkRequest(RuleStatus.REMOVED != rule.getStatus(), "Rule was removed: %s", rule.getKey());
- checkRequest(!rule.isTemplate(), "Rule template can't be activated on a Quality profile: %s", rule.getKey());
-
- List<ActiveRuleChange> changes = new ArrayList<>();
- ActiveRuleChange change;
- boolean stopCascading = false;
-
- ActiveRuleWrapper activeRule = context.getActiveRule();
- ActiveRuleKey activeRuleKey = ActiveRuleKey.of(context.getRulesProfile(), rule.getKey());
- if (activeRule == null) {
- if (activation.isReset()) {
- // ignore reset when rule is not activated
- return changes;
- }
- // new activation
- change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, activeRuleKey, rule);
- applySeverityAndParamToChange(activation, context, change);
- if (context.isCascading() || isSameAsParent(change, context)) {
- change.setInheritance(ActiveRuleInheritance.INHERITED);
- }
- } else {
- // already activated
- if (context.isCascading() && activeRule.get().doesOverride()) {
- // propagating to descendants, but child profile already overrides rule -> stop propagation
- return changes;
- }
- change = new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRuleKey, rule);
- if (context.isCascading() && activeRule.get().getInheritance() == null) {
- // activate on child, then on parent -> mark child as overriding parent
- change.setInheritance(ActiveRuleInheritance.OVERRIDES);
- change.setSeverity(activeRule.get().getSeverityString());
- for (ActiveRuleParamDto activeParam : activeRule.getParams()) {
- change.setParameter(activeParam.getKey(), activeParam.getValue());
- }
- stopCascading = true;
- } else {
- applySeverityAndParamToChange(activation, context, change);
- if (!context.isCascading() && context.getParentActiveRule() != null) {
- // override rule which is already declared on parents
- change.setInheritance(isSameAsParent(change, context) ? ActiveRuleInheritance.INHERITED : ActiveRuleInheritance.OVERRIDES);
- }
- }
- if (isSame(change, activeRule)) {
- change = null;
- stopCascading = true;
- }
- }
-
- if (change != null) {
- changes.add(change);
- persist(change, context, dbSession);
- }
-
- if (!changes.isEmpty()) {
- updateProfileDates(dbSession, context);
- }
-
- if (!stopCascading) {
- changes.addAll(propagateActivationToDescendants(dbSession, activation, context));
- }
-
- return changes;
- }
-
- private void updateProfileDates(DbSession dbSession, RuleActivationContext context) {
- RulesProfileDto ruleProfile = context.getRulesProfile();
- ruleProfile.setRulesUpdatedAtAsDate(new Date(context.getDate()));
- db.qualityProfileDao().update(dbSession, ruleProfile);
-
- if (userSession.isLoggedIn()) {
- context.getProfiles().forEach(p -> db.qualityProfileDao().update(dbSession, OrgQProfileDto.from(p).setUserUpdatedAt(context.getDate())));
- }
- }
-
- /**
- * Update severity and params
- */
- private void applySeverityAndParamToChange(RuleActivation request, RuleActivationContext context, ActiveRuleChange change) {
- RuleWrapper rule = context.getRule();
- ActiveRuleWrapper activeRule = context.getActiveRule();
- ActiveRuleWrapper parentActiveRule = context.getParentActiveRule();
-
- // First apply severity
- String severity;
- if (request.isReset()) {
- // load severity from parent profile, else from default values
- severity = firstNonNull(
- parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null,
- rule.get().getSeverityString());
- } else if (context.getRulesProfile().isBuiltIn()) {
- // for builtin quality profiles, the severity from profile, when null use the default severity of the rule
- severity = firstNonNull(request.getSeverity(), rule.get().getSeverityString());
- } else {
- // load severity from request, else keep existing one (if already activated), else from parent, else from default
- severity = firstNonNull(
- request.getSeverity(),
- activeRule == null ? null : activeRule.get().getSeverityString(),
- parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null,
- rule.get().getSeverityString());
- }
- change.setSeverity(severity);
-
- // Apply param values
- for (RuleParamDto ruleParamDto : rule.getParams()) {
- String paramKey = ruleParamDto.getName();
- String paramValue;
- if (request.isReset()) {
- // load params from parent profile, else from default values
- paramValue = firstNonNull(
- parentActiveRule != null ? parentActiveRule.getParamValue(paramKey) : null,
- rule.getParamDefaultValue(paramKey));
- } else if (context.getRulesProfile().isBuiltIn()) {
- // use the value defined in the profile definition, else the rule default value
- paramValue = firstNonNull(
- context.getRequestedParamValue(request, paramKey),
- rule.getParamDefaultValue(paramKey));
- } else {
- String parentValue = parentActiveRule != null ? parentActiveRule.getParamValue(paramKey) : null;
- String activeRuleValue = activeRule == null ? null : activeRule.getParamValue(paramKey);
- paramValue = context.hasRequestedParamValue(request, paramKey) ?
- // If the request contains the parameter then we're using either value from request, or parent value, or default value
- firstNonNull(
- context.getRequestedParamValue(request, paramKey),
- parentValue,
- rule.getParamDefaultValue(paramKey))
- // If the request doesn't contain the parameter, then we're using either value in DB, or parent value, or default value
- : firstNonNull(
- activeRuleValue,
- parentValue,
- rule.getParamDefaultValue(paramKey));
- }
-
- change.setParameter(paramKey, validateParam(ruleParamDto, paramValue));
- }
- }
-
- private List<ActiveRuleChange> propagateActivationToDescendants(DbSession dbSession, RuleActivation activation, RuleActivationContext context) {
- List<ActiveRuleChange> changes = new ArrayList<>();
-
- // get all inherited profiles
- context.getChildProfiles().forEach(child -> {
- context.selectChild(child);
- changes.addAll(doActivate(dbSession, activation, context));
- });
- return changes;
- }
-
- private void persist(ActiveRuleChange change, RuleActivationContext context, DbSession dbSession) {
- ActiveRuleDto activeRule = null;
- if (change.getType() == ActiveRuleChange.Type.ACTIVATED) {
- activeRule = doInsert(change, context, dbSession);
- } else if (change.getType() == ActiveRuleChange.Type.DEACTIVATED) {
- ActiveRuleDao dao = db.activeRuleDao();
- activeRule = dao.delete(dbSession, change.getKey()).orElse(null);
-
- } else if (change.getType() == ActiveRuleChange.Type.UPDATED) {
- activeRule = doUpdate(change, context, dbSession);
- }
- change.setActiveRule(activeRule);
- db.qProfileChangeDao().insert(dbSession, change.toDto(userSession.getUuid()));
- }
-
- private ActiveRuleDto doInsert(ActiveRuleChange change, RuleActivationContext context, DbSession dbSession) {
- ActiveRuleDao dao = db.activeRuleDao();
- RuleWrapper rule = context.getRule();
-
- ActiveRuleDto activeRule = new ActiveRuleDto();
- activeRule.setProfileId(context.getRulesProfile().getId());
- activeRule.setRuleId(rule.get().getId());
- activeRule.setKey(ActiveRuleKey.of(context.getRulesProfile(), rule.get().getKey()));
- String severity = change.getSeverity();
- if (severity != null) {
- activeRule.setSeverity(severity);
- }
- ActiveRuleInheritance inheritance = change.getInheritance();
- if (inheritance != null) {
- activeRule.setInheritance(inheritance.name());
- }
- activeRule.setUpdatedAt(system2.now());
- activeRule.setCreatedAt(system2.now());
- dao.insert(dbSession, activeRule);
- for (Map.Entry<String, String> param : change.getParameters().entrySet()) {
- if (param.getValue() != null) {
- ActiveRuleParamDto paramDto = ActiveRuleParamDto.createFor(rule.getParam(param.getKey()));
- paramDto.setValue(param.getValue());
- dao.insertParam(dbSession, activeRule, paramDto);
- }
- }
- return activeRule;
- }
-
- private ActiveRuleDto doUpdate(ActiveRuleChange change, RuleActivationContext context, DbSession dbSession) {
- ActiveRuleWrapper activeRule = context.getActiveRule();
- if (activeRule == null) {
- return null;
- }
- ActiveRuleDao dao = db.activeRuleDao();
- String severity = change.getSeverity();
- if (severity != null) {
- activeRule.get().setSeverity(severity);
- }
- ActiveRuleInheritance inheritance = change.getInheritance();
- if (inheritance != null) {
- activeRule.get().setInheritance(inheritance.name());
- }
- activeRule.get().setUpdatedAt(system2.now());
- dao.update(dbSession, activeRule.get());
-
- for (Map.Entry<String, String> param : change.getParameters().entrySet()) {
- ActiveRuleParamDto activeRuleParamDto = activeRule.getParam(param.getKey());
- if (activeRuleParamDto == null) {
- // did not exist
- if (param.getValue() != null) {
- activeRuleParamDto = ActiveRuleParamDto.createFor(context.getRule().getParam(param.getKey()));
- activeRuleParamDto.setValue(param.getValue());
- dao.insertParam(dbSession, activeRule.get(), activeRuleParamDto);
- }
- } else {
- if (param.getValue() != null) {
- activeRuleParamDto.setValue(param.getValue());
- dao.updateParam(dbSession, activeRuleParamDto);
- } else {
- dao.deleteParam(dbSession, activeRuleParamDto);
- }
- }
- }
- return activeRule.get();
- }
-
- public List<ActiveRuleChange> deactivate(DbSession dbSession, RuleActivationContext context, int ruleId, boolean force) {
- context.reset(ruleId);
- return doDeactivate(dbSession, context, force);
- }
-
- private List<ActiveRuleChange> doDeactivate(DbSession dbSession, RuleActivationContext context, boolean force) {
- List<ActiveRuleChange> changes = new ArrayList<>();
- ActiveRuleWrapper activeRule = context.getActiveRule();
- if (activeRule == null) {
- return changes;
- }
-
- ActiveRuleChange change;
- checkRequest(force || context.isCascading() || activeRule.get().getInheritance() == null, "Cannot deactivate inherited rule '%s'", context.getRule().get().getKey());
- change = new ActiveRuleChange(ActiveRuleChange.Type.DEACTIVATED, activeRule.get(), context.getRule().get());
- changes.add(change);
- persist(change, context, dbSession);
-
- // get all inherited profiles (they are not built-in by design)
- context.getChildProfiles().forEach(child -> {
- context.selectChild(child);
- changes.addAll(doDeactivate(dbSession, context, force));
- });
-
- if (!changes.isEmpty()) {
- updateProfileDates(dbSession, context);
- }
-
- return changes;
- }
-
- @CheckForNull
- private String validateParam(RuleParamDto ruleParam, @Nullable String value) {
- if (value != null) {
- RuleParamType ruleParamType = RuleParamType.parse(ruleParam.getType());
- if (ruleParamType.multiple()) {
- List<String> values = Splitter.on(",").splitToList(value);
- typeValidations.validate(values, ruleParamType.type(), ruleParamType.values());
- } else {
- typeValidations.validate(value, ruleParamType.type(), ruleParamType.values());
- }
- }
- return value;
- }
-
- public RuleActivationContext createContextForBuiltInProfile(DbSession dbSession, RulesProfileDto builtInProfile, Collection<Integer> ruleIds) {
- checkArgument(builtInProfile.isBuiltIn(), "Rules profile with UUID %s is not built-in", builtInProfile.getKee());
-
- RuleActivationContext.Builder builder = new RuleActivationContext.Builder();
- builder.setDescendantProfilesSupplier(createDescendantProfilesSupplier(dbSession));
-
- // load rules
- completeWithRules(dbSession, builder, ruleIds);
-
- // load org profiles. Their parents are null by nature.
- List<QProfileDto> profiles = db.qualityProfileDao().selectQProfilesByRuleProfile(dbSession, builtInProfile);
- builder.setProfiles(profiles);
- builder.setBaseProfile(builtInProfile);
-
- // load active rules
- Collection<String> ruleProfileUuids = Stream
- .concat(Stream.of(builtInProfile.getKee()), profiles.stream().map(QProfileDto::getRulesProfileUuid))
- .collect(MoreCollectors.toHashSet(profiles.size() + 1));
- completeWithActiveRules(dbSession, builder, ruleIds, ruleProfileUuids);
- return builder.build();
- }
-
- public RuleActivationContext createContextForUserProfile(DbSession dbSession, QProfileDto profile, Collection<Integer> ruleIds) {
- checkArgument(!profile.isBuiltIn(), "Profile with UUID %s is built-in", profile.getKee());
- RuleActivationContext.Builder builder = new RuleActivationContext.Builder();
- builder.setDescendantProfilesSupplier(createDescendantProfilesSupplier(dbSession));
-
- // load rules
- completeWithRules(dbSession, builder, ruleIds);
-
- // load profiles
- List<QProfileDto> profiles = new ArrayList<>();
- profiles.add(profile);
- if (profile.getParentKee() != null) {
- profiles.add(db.qualityProfileDao().selectByUuid(dbSession, profile.getParentKee()));
- }
- builder.setProfiles(profiles);
- builder.setBaseProfile(RulesProfileDto.from(profile));
-
- // load active rules
- Collection<String> ruleProfileUuids = profiles.stream()
- .map(QProfileDto::getRulesProfileUuid)
- .collect(MoreCollectors.toHashSet(profiles.size()));
- completeWithActiveRules(dbSession, builder, ruleIds, ruleProfileUuids);
-
- return builder.build();
- }
-
- DescendantProfilesSupplier createDescendantProfilesSupplier(DbSession dbSession) {
- return (parents, ruleIds) -> {
- Collection<QProfileDto> profiles = db.qualityProfileDao().selectDescendants(dbSession, parents);
- Set<String> ruleProfileUuids = profiles.stream()
- .map(QProfileDto::getRulesProfileUuid)
- .collect(MoreCollectors.toHashSet());
- Collection<ActiveRuleDto> activeRules = db.activeRuleDao().selectByRulesAndRuleProfileUuids(dbSession, ruleIds, ruleProfileUuids);
- List<Integer> activeRuleIds = activeRules.stream().map(ActiveRuleDto::getId).collect(MoreCollectors.toArrayList(activeRules.size()));
- List<ActiveRuleParamDto> activeRuleParams = db.activeRuleDao().selectParamsByActiveRuleIds(dbSession, activeRuleIds);
- return new DescendantProfilesSupplier.Result(profiles, activeRules, activeRuleParams);
- };
- }
-
- private void completeWithRules(DbSession dbSession, RuleActivationContext.Builder builder, Collection<Integer> ruleIds) {
- List<RuleDefinitionDto> rules = db.ruleDao().selectDefinitionByIds(dbSession, ruleIds);
- builder.setRules(rules);
- builder.setRuleParams(db.ruleDao().selectRuleParamsByRuleIds(dbSession, ruleIds));
- }
-
- private void completeWithActiveRules(DbSession dbSession, RuleActivationContext.Builder builder, Collection<Integer> ruleIds, Collection<String> ruleProfileUuids) {
- Collection<ActiveRuleDto> activeRules = db.activeRuleDao().selectByRulesAndRuleProfileUuids(dbSession, ruleIds, ruleProfileUuids);
- builder.setActiveRules(activeRules);
- List<Integer> activeRuleIds = activeRules.stream().map(ActiveRuleDto::getId).collect(MoreCollectors.toArrayList(activeRules.size()));
- builder.setActiveRuleParams(db.activeRuleDao().selectParamsByActiveRuleIds(dbSession, activeRuleIds));
- }
-
- private static boolean isSame(ActiveRuleChange change, ActiveRuleWrapper activeRule) {
- ActiveRuleInheritance inheritance = change.getInheritance();
- if (inheritance != null && !inheritance.name().equals(activeRule.get().getInheritance())) {
- return false;
- }
- String severity = change.getSeverity();
- if (severity != null && !severity.equals(activeRule.get().getSeverityString())) {
- return false;
- }
- for (Map.Entry<String, String> changeParam : change.getParameters().entrySet()) {
- String activeParamValue = activeRule.getParamValue(changeParam.getKey());
- if (changeParam.getValue() == null && activeParamValue != null) {
- return false;
- }
- if (changeParam.getValue() != null && (activeParamValue == null || !StringUtils.equals(changeParam.getValue(), activeParamValue))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * True if trying to override an inherited rule but with exactly the same values
- */
- private static boolean isSameAsParent(ActiveRuleChange change, RuleActivationContext context) {
- ActiveRuleWrapper parentActiveRule = context.getParentActiveRule();
- if (parentActiveRule == null) {
- return false;
- }
- if (!StringUtils.equals(change.getSeverity(), parentActiveRule.get().getSeverityString())) {
- return false;
- }
- for (Map.Entry<String, String> entry : change.getParameters().entrySet()) {
- if (entry.getValue() != null && !entry.getValue().equals(parentActiveRule.getParamValue(entry.getKey()))) {
- return false;
- }
- }
- return true;
- }
-
- @CheckForNull
- private static String firstNonNull(String... strings) {
- for (String s : strings) {
- if (s != null) {
- return s;
- }
- }
- return null;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/AbstractUserSession.java b/server/sonar-server/src/main/java/org/sonar/server/user/AbstractUserSession.java
deleted file mode 100644
index bba45afcf16..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/AbstractUserSession.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import com.google.common.collect.ImmutableSet;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.UnauthorizedException;
-
-import static java.lang.String.format;
-import static org.apache.commons.lang.StringUtils.defaultString;
-import static org.sonar.server.user.UserSession.IdentityProvider.SONARQUBE;
-
-public abstract class AbstractUserSession implements UserSession {
- private static final Set<String> PUBLIC_PERMISSIONS = ImmutableSet.of(UserRole.USER, UserRole.CODEVIEWER);
- private static final String INSUFFICIENT_PRIVILEGES_MESSAGE = "Insufficient privileges";
- private static final String AUTHENTICATION_IS_REQUIRED_MESSAGE = "Authentication is required";
-
- protected static Identity computeIdentity(UserDto userDto) {
- IdentityProvider identityProvider = IdentityProvider.getFromKey(userDto.getExternalIdentityProvider());
- ExternalIdentity externalIdentity = identityProvider == SONARQUBE ? null : externalIdentityOf(userDto);
- return new Identity(identityProvider, externalIdentity);
- }
-
- private static ExternalIdentity externalIdentityOf(UserDto userDto) {
- String externalId = userDto.getExternalId();
- String externalLogin = userDto.getExternalLogin();
- return new ExternalIdentity(externalId, externalLogin);
- }
-
- protected static final class Identity {
- private final IdentityProvider identityProvider;
- private final ExternalIdentity externalIdentity;
-
- private Identity(IdentityProvider identityProvider, @Nullable ExternalIdentity externalIdentity) {
- this.identityProvider = identityProvider;
- this.externalIdentity = externalIdentity;
- }
-
- public IdentityProvider getIdentityProvider() {
- return identityProvider;
- }
-
- @CheckForNull
- public ExternalIdentity getExternalIdentity() {
- return externalIdentity;
- }
- }
-
- @Override
- public final boolean hasPermission(OrganizationPermission permission, OrganizationDto organization) {
- return hasPermission(permission, organization.getUuid());
- }
-
- @Override
- public final boolean hasPermission(OrganizationPermission permission, String organizationUuid) {
- return isRoot() || hasPermissionImpl(permission, organizationUuid);
- }
-
- protected abstract boolean hasPermissionImpl(OrganizationPermission permission, String organizationUuid);
-
- @Override
- public final boolean hasComponentPermission(String permission, ComponentDto component) {
- if (isRoot()) {
- return true;
- }
- String projectUuid = defaultString(component.getMainBranchProjectUuid(), component.projectUuid());
- return hasProjectUuidPermission(permission, projectUuid);
- }
-
- @Override
- public final boolean hasComponentUuidPermission(String permission, String componentUuid) {
- if (isRoot()) {
- return true;
- }
- Optional<String> projectUuid = componentUuidToProjectUuid(componentUuid);
- return projectUuid
- .map(s -> hasProjectUuidPermission(permission, s))
- .orElse(false);
- }
-
- protected abstract Optional<String> componentUuidToProjectUuid(String componentUuid);
-
- protected abstract boolean hasProjectUuidPermission(String permission, String projectUuid);
-
- @Override
- public final boolean hasMembership(OrganizationDto organizationDto) {
- return isRoot() || hasMembershipImpl(organizationDto);
- }
-
- protected abstract boolean hasMembershipImpl(OrganizationDto organizationDto);
-
- @Override
- public final List<ComponentDto> keepAuthorizedComponents(String permission, Collection<ComponentDto> components) {
- if (isRoot()) {
- return new ArrayList<>(components);
- }
- return doKeepAuthorizedComponents(permission, components);
- }
-
- /**
- * Naive implementation, to be overridden if needed
- */
- protected List<ComponentDto> doKeepAuthorizedComponents(String permission, Collection<ComponentDto> components) {
- boolean allowPublicComponent = PUBLIC_PERMISSIONS.contains(permission);
- return components.stream()
- .filter(c -> (allowPublicComponent && !c.isPrivate()) || hasComponentPermission(permission, c))
- .collect(MoreCollectors.toList());
- }
-
- @Override
- public UserSession checkIsRoot() {
- if (!isRoot()) {
- throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE);
- }
- return this;
- }
-
- @Override
- public final UserSession checkLoggedIn() {
- if (!isLoggedIn()) {
- throw new UnauthorizedException(AUTHENTICATION_IS_REQUIRED_MESSAGE);
- }
- return this;
- }
-
- @Override
- public final UserSession checkPermission(OrganizationPermission permission, OrganizationDto organization) {
- return checkPermission(permission, organization.getUuid());
- }
-
- @Override
- public final UserSession checkPermission(OrganizationPermission permission, String organizationUuid) {
- if (!hasPermission(permission, organizationUuid)) {
- throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE);
- }
- return this;
- }
-
- @Override
- public final UserSession checkComponentPermission(String projectPermission, ComponentDto component) {
- if (!hasComponentPermission(projectPermission, component)) {
- throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE);
- }
- return this;
- }
-
- @Override
- public final UserSession checkComponentUuidPermission(String permission, String componentUuid) {
- if (!hasComponentUuidPermission(permission, componentUuid)) {
- throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE);
- }
- return this;
- }
-
- public static ForbiddenException insufficientPrivilegesException() {
- return new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE);
- }
-
- @Override
- public final UserSession checkIsSystemAdministrator() {
- if (!isSystemAdministrator()) {
- throw insufficientPrivilegesException();
- }
- return this;
- }
-
- @Override
- public UserSession checkMembership(OrganizationDto organization) {
- if (!hasMembership(organization)) {
- throw new ForbiddenException(format("You're not member of organization '%s'", organization.getKey()));
- }
- return this;
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/CompatibilityRealm.java b/server/sonar-server/src/main/java/org/sonar/server/user/CompatibilityRealm.java
deleted file mode 100644
index 2f2aa1df59e..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/CompatibilityRealm.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.sonar.api.security.LoginPasswordAuthenticator;
-import org.sonar.api.security.SecurityRealm;
-
-/**
- * Provides backward compatibility for {@link org.sonar.api.CoreProperties#CORE_AUTHENTICATOR_CLASS}.
- *
- * @since 2.14
- */
-class CompatibilityRealm extends SecurityRealm {
- private final LoginPasswordAuthenticator authenticator;
-
- public CompatibilityRealm(LoginPasswordAuthenticator authenticator) {
- this.authenticator = authenticator;
- }
-
- @Override
- public void init() {
- authenticator.init();
- }
-
- @Override
- public String getName() {
- return "CompatibilityRealm[" + authenticator.getClass().getName() + "]";
- }
-
- @Override
- public LoginPasswordAuthenticator getLoginPasswordAuthenticator() {
- return authenticator;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/DoPrivileged.java b/server/sonar-server/src/main/java/org/sonar/server/user/DoPrivileged.java
deleted file mode 100644
index 4f695b25f8d..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/DoPrivileged.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Optional;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.user.GroupDto;
-
-/**
- * Allow code to be executed with the highest privileges possible, as if executed by a {@link OrganizationPermission#ADMINISTER} account.
- * @since 4.3
- */
-public final class DoPrivileged {
-
- private DoPrivileged() {
- // Only static stuff
- }
-
- /**
- * Executes the task's <code>{@link Task#doPrivileged() doPrivileged}</code> method in a privileged environment.
- * @param task
- */
- public static void execute(Task task) {
- try {
- task.start();
- task.doPrivileged();
- } finally {
- task.stop();
- }
- }
-
- /**
- * Define a task that will be executed using the highest privileges available. The privileged section is restricted
- * to the execution of the {@link #doPrivileged()} method.
- */
- public abstract static class Task {
- private final ThreadLocalUserSession threadLocalUserSession;
- private UserSession oldUserSession;
-
- protected Task(ThreadLocalUserSession threadLocalUserSession) {
- this.threadLocalUserSession = threadLocalUserSession;
- }
-
- /**
- * Code placed in this method will be executed in a privileged environment.
- */
- protected abstract void doPrivileged();
-
- private static class PrivilegedUserSession extends AbstractUserSession {
- @Override
- public String getLogin() {
- return null;
- }
-
- @Override
- public String getUuid() {
- return null;
- }
-
- @Override
- public String getName() {
- return null;
- }
-
- @Override
- public Integer getUserId() {
- return null;
- }
-
- @Override
- public Collection<GroupDto> getGroups() {
- return Collections.emptyList();
- }
-
- @Override
- public boolean isLoggedIn() {
- return false;
- }
-
- @Override
- public boolean isRoot() {
- return true;
- }
-
- @Override
- public Optional<IdentityProvider> getIdentityProvider() {
- return Optional.empty();
- }
-
- @Override
- public Optional<ExternalIdentity> getExternalIdentity() {
- return Optional.empty();
- }
-
- @Override
- protected boolean hasPermissionImpl(OrganizationPermission permission, String organizationUuid) {
- return true;
- }
-
- @Override
- protected Optional<String> componentUuidToProjectUuid(String componentUuid) {
- // always root so unused
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected boolean hasProjectUuidPermission(String permission, String projectUuid) {
- return true;
- }
-
- @Override
- public boolean isSystemAdministrator() {
- return true;
- }
-
- @Override
- public boolean hasMembershipImpl(OrganizationDto organizationDto) {
- return true;
- }
- }
-
- private void start() {
- oldUserSession = threadLocalUserSession.hasSession() ? threadLocalUserSession.get() : null;
- threadLocalUserSession.set(new PrivilegedUserSession());
- }
-
- private void stop() {
- threadLocalUserSession.unload();
- if (oldUserSession != null) {
- threadLocalUserSession.set(oldUserSession);
- }
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ExternalIdentity.java b/server/sonar-server/src/main/java/org/sonar/server/user/ExternalIdentity.java
deleted file mode 100644
index 483f4590ca2..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/ExternalIdentity.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import javax.annotation.Nullable;
-
-import static java.util.Objects.requireNonNull;
-
-public class ExternalIdentity {
-
- public static final String SQ_AUTHORITY = "sonarqube";
-
- private String provider;
- private String login;
- private String id;
-
- public ExternalIdentity(String provider, String login, @Nullable String id) {
- this.provider = requireNonNull(provider, "Identity provider cannot be null");
- this.login = requireNonNull(login, "Identity login cannot be null");
- this.id = id == null ? login : id;
- }
-
- public String getProvider() {
- return provider;
- }
-
- public String getLogin() {
- return login;
- }
-
- public String getId() {
- return id;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/NewUser.java b/server/sonar-server/src/main/java/org/sonar/server/user/NewUser.java
deleted file mode 100644
index cd7b51116ee..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/NewUser.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import static com.google.common.base.Preconditions.checkState;
-
-public class NewUser {
-
- private String login;
- private String password;
- private String name;
- private String email;
- private List<String> scmAccounts;
- private ExternalIdentity externalIdentity;
-
- private NewUser(Builder builder) {
- this.login = builder.login;
- this.password = builder.password;
- this.name = builder.name;
- this.email = builder.email;
- this.scmAccounts = builder.scmAccounts;
- this.externalIdentity = builder.externalIdentity;
- }
-
- @CheckForNull
- public String login() {
- return login;
- }
-
- public String name() {
- return name;
- }
-
- @CheckForNull
- public String email() {
- return email;
- }
-
- public NewUser setEmail(@Nullable String email) {
- this.email = email;
- return this;
- }
-
- public List<String> scmAccounts() {
- return scmAccounts;
- }
-
- public NewUser setScmAccounts(List<String> scmAccounts) {
- this.scmAccounts = scmAccounts;
- return this;
- }
-
- @Nullable
- public String password() {
- return password;
- }
-
- public NewUser setPassword(@Nullable String password) {
- this.password = password;
- return this;
- }
-
- @Nullable
- public ExternalIdentity externalIdentity() {
- return externalIdentity;
- }
-
- public NewUser setExternalIdentity(@Nullable ExternalIdentity externalIdentity) {
- this.externalIdentity = externalIdentity;
- return this;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static class Builder {
- private String login;
- private String name;
- private String email;
- private List<String> scmAccounts = new ArrayList<>();
- private String password;
- private ExternalIdentity externalIdentity;
-
- public Builder setLogin(@Nullable String login) {
- this.login = login;
- return this;
- }
-
- public Builder setName(String name) {
- this.name = name;
- return this;
- }
-
- public Builder setEmail(@Nullable String email) {
- this.email = email;
- return this;
- }
-
- public Builder setScmAccounts(List<String> scmAccounts) {
- this.scmAccounts = scmAccounts;
- return this;
- }
-
- public Builder setPassword(@Nullable String password) {
- this.password = password;
- return this;
- }
-
- public Builder setExternalIdentity(@Nullable ExternalIdentity externalIdentity) {
- this.externalIdentity = externalIdentity;
- return this;
- }
-
- public NewUser build() {
- checkState(externalIdentity == null || password == null, "Password should not be set with an external identity");
- return new NewUser(this);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/NewUserNotifier.java b/server/sonar-server/src/main/java/org/sonar/server/user/NewUserNotifier.java
deleted file mode 100644
index e5dc562bd70..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/NewUserNotifier.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.platform.NewUserHandler;
-import org.sonar.api.utils.log.Loggers;
-
-/**
- * @since 3.2
- */
-@ServerSide
-public class NewUserNotifier {
-
- private NewUserHandler[] handlers;
-
- public NewUserNotifier(NewUserHandler[] handlers) {
- this.handlers = handlers;
- }
-
- public NewUserNotifier() {
- this(new NewUserHandler[0]);
- }
-
- public void onNewUser(NewUserHandler.Context context) {
- Loggers.get(NewUserNotifier.class).debug("User created: " + context.getLogin() + ". Notifying " + NewUserHandler.class.getSimpleName() + " handlers...");
- for (NewUserHandler handler : handlers) {
- handler.doOnNewUser(context);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/SecurityRealmFactory.java b/server/sonar-server/src/main/java/org/sonar/server/user/SecurityRealmFactory.java
deleted file mode 100644
index f98f6ac58ac..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/SecurityRealmFactory.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-import org.picocontainer.Startable;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.security.LoginPasswordAuthenticator;
-import org.sonar.api.security.SecurityRealm;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.SonarException;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-import static org.sonar.process.ProcessProperties.Property.SONAR_AUTHENTICATOR_IGNORE_STARTUP_FAILURE;
-import static org.sonar.process.ProcessProperties.Property.SONAR_SECURITY_REALM;
-
-/**
- * @since 2.14
- */
-@ServerSide
-public class SecurityRealmFactory implements Startable {
-
- private final boolean ignoreStartupFailure;
- private final SecurityRealm realm;
-
- public SecurityRealmFactory(Configuration config, SecurityRealm[] realms, LoginPasswordAuthenticator[] authenticators) {
- ignoreStartupFailure = config.getBoolean(SONAR_AUTHENTICATOR_IGNORE_STARTUP_FAILURE.getKey()).orElse(false);
- String realmName = config.get(SONAR_SECURITY_REALM.getKey()).orElse(null);
- String className = config.get(CoreProperties.CORE_AUTHENTICATOR_CLASS).orElse(null);
- SecurityRealm selectedRealm = null;
- if (!StringUtils.isEmpty(realmName)) {
- selectedRealm = selectRealm(realms, realmName);
- if (selectedRealm == null) {
- throw new SonarException(String.format(
- "Realm '%s' not found. Please check the property '%s' in conf/sonar.properties", realmName, SONAR_SECURITY_REALM.getKey()));
- }
- }
- if (selectedRealm == null && !StringUtils.isEmpty(className)) {
- LoginPasswordAuthenticator authenticator = selectAuthenticator(authenticators, className);
- if (authenticator == null) {
- throw new SonarException(String.format(
- "Authenticator '%s' not found. Please check the property '%s' in conf/sonar.properties", className, CoreProperties.CORE_AUTHENTICATOR_CLASS));
- }
- selectedRealm = new CompatibilityRealm(authenticator);
- }
- realm = selectedRealm;
- }
-
- public SecurityRealmFactory(Configuration config, LoginPasswordAuthenticator[] authenticators) {
- this(config, new SecurityRealm[0], authenticators);
- }
-
- public SecurityRealmFactory(Configuration config, SecurityRealm[] realms) {
- this(config, realms, new LoginPasswordAuthenticator[0]);
- }
-
- public SecurityRealmFactory(Configuration config) {
- this(config, new SecurityRealm[0], new LoginPasswordAuthenticator[0]);
- }
-
- @Override
- public void start() {
- if (realm != null) {
- Logger logger = Loggers.get("org.sonar.INFO");
- try {
- logger.info("Security realm: " + realm.getName());
- realm.init();
- logger.info("Security realm started");
- } catch (RuntimeException e) {
- if (ignoreStartupFailure) {
- logger.error("IGNORED - Security realm fails to start: " + e.getMessage());
- } else {
- throw new SonarException("Security realm fails to start: " + e.getMessage(), e);
- }
- }
- }
- }
-
- @Override
- public void stop() {
- // nothing
- }
-
- @Nullable
- public SecurityRealm getRealm() {
- return realm;
- }
-
- public boolean hasExternalAuthentication() {
- return getRealm() != null;
- }
-
- private static SecurityRealm selectRealm(SecurityRealm[] realms, String realmName) {
- for (SecurityRealm realm : realms) {
- if (StringUtils.equals(realmName, realm.getName())) {
- return realm;
- }
- }
- return null;
- }
-
- private static LoginPasswordAuthenticator selectAuthenticator(LoginPasswordAuthenticator[] authenticators, String className) {
- for (LoginPasswordAuthenticator lpa : authenticators) {
- if (lpa.getClass().getName().equals(className)) {
- return lpa;
- }
- }
- return null;
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ServerUserSession.java b/server/sonar-server/src/main/java/org/sonar/server/user/ServerUserSession.java
deleted file mode 100644
index 1485eca1891..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/ServerUserSession.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.collect.ImmutableSet;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.organization.OrganizationMemberDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.organization.OrganizationFlags;
-
-import static java.util.Objects.requireNonNull;
-import static java.util.Optional.of;
-import static java.util.Optional.ofNullable;
-import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
-import static org.sonar.api.web.UserRole.PUBLIC_PERMISSIONS;
-
-/**
- * Implementation of {@link UserSession} used in web server
- */
-public class ServerUserSession extends AbstractUserSession {
- @CheckForNull
- private final UserDto userDto;
- private final DbClient dbClient;
- private final OrganizationFlags organizationFlags;
- private final DefaultOrganizationProvider defaultOrganizationProvider;
- private final Supplier<Collection<GroupDto>> groups = Suppliers.memoize(this::loadGroups);
- private final Supplier<Boolean> isSystemAdministratorSupplier = Suppliers.memoize(this::loadIsSystemAdministrator);
- private final Map<String, String> projectUuidByComponentUuid = new HashMap<>();
- private Map<String, Set<OrganizationPermission>> permissionsByOrganizationUuid;
- private Map<String, Set<String>> permissionsByProjectUuid;
- private Set<String> organizationMembership = new HashSet<>();
-
- ServerUserSession(DbClient dbClient, OrganizationFlags organizationFlags,
- DefaultOrganizationProvider defaultOrganizationProvider, @Nullable UserDto userDto) {
- this.dbClient = dbClient;
- this.organizationFlags = organizationFlags;
- this.defaultOrganizationProvider = defaultOrganizationProvider;
- this.userDto = userDto;
- }
-
- private Collection<GroupDto> loadGroups() {
- if (this.userDto == null) {
- return Collections.emptyList();
- }
- try (DbSession dbSession = dbClient.openSession(false)) {
- return dbClient.groupDao().selectByUserLogin(dbSession, userDto.getLogin());
- }
- }
-
- @Override
- @CheckForNull
- public String getLogin() {
- return userDto == null ? null : userDto.getLogin();
- }
-
- @Override
- @CheckForNull
- public String getUuid() {
- return userDto == null ? null : userDto.getUuid();
- }
-
- @Override
- @CheckForNull
- public String getName() {
- return userDto == null ? null : userDto.getName();
- }
-
- @Override
- @CheckForNull
- public Integer getUserId() {
- return userDto == null ? null : userDto.getId();
- }
-
- @Override
- public Collection<GroupDto> getGroups() {
- return groups.get();
- }
-
- @Override
- public boolean isLoggedIn() {
- return userDto != null;
- }
-
- @Override
- public boolean isRoot() {
- return userDto != null && userDto.isRoot();
- }
-
- @Override
- public Optional<IdentityProvider> getIdentityProvider() {
- return ofNullable(userDto).map(d -> computeIdentity(d).getIdentityProvider());
- }
-
- @Override
- public Optional<ExternalIdentity> getExternalIdentity() {
- return ofNullable(userDto).map(d -> computeIdentity(d).getExternalIdentity());
- }
-
- @Override
- protected boolean hasPermissionImpl(OrganizationPermission permission, String organizationUuid) {
- if (permissionsByOrganizationUuid == null) {
- permissionsByOrganizationUuid = new HashMap<>();
- }
- Set<OrganizationPermission> permissions = permissionsByOrganizationUuid.computeIfAbsent(organizationUuid, this::loadOrganizationPermissions);
- return permissions.contains(permission);
- }
-
- private Set<OrganizationPermission> loadOrganizationPermissions(String organizationUuid) {
- Set<String> permissionKeys;
- try (DbSession dbSession = dbClient.openSession(false)) {
- if (userDto != null && userDto.getId() != null) {
- permissionKeys = dbClient.authorizationDao().selectOrganizationPermissions(dbSession, organizationUuid, userDto.getId());
- } else {
- permissionKeys = dbClient.authorizationDao().selectOrganizationPermissionsOfAnonymous(dbSession, organizationUuid);
- }
- }
- return permissionKeys.stream()
- .map(OrganizationPermission::fromKey)
- .collect(MoreCollectors.toSet(permissionKeys.size()));
- }
-
- @Override
- protected Optional<String> componentUuidToProjectUuid(String componentUuid) {
- String projectUuid = projectUuidByComponentUuid.get(componentUuid);
- if (projectUuid != null) {
- return of(projectUuid);
- }
- try (DbSession dbSession = dbClient.openSession(false)) {
- Optional<ComponentDto> component = dbClient.componentDao().selectByUuid(dbSession, componentUuid);
- if (!component.isPresent()) {
- return Optional.empty();
- }
- // if component is part of a branch, then permissions must be
- // checked on the project (represented by its main branch)
- projectUuid = defaultIfEmpty(component.get().getMainBranchProjectUuid(), component.get().projectUuid());
- projectUuidByComponentUuid.put(componentUuid, projectUuid);
- return of(projectUuid);
- }
- }
-
- @Override
- protected boolean hasProjectUuidPermission(String permission, String projectUuid) {
- if (permissionsByProjectUuid == null) {
- permissionsByProjectUuid = new HashMap<>();
- }
- Set<String> permissions = permissionsByProjectUuid.computeIfAbsent(projectUuid, this::loadProjectPermissions);
- return permissions.contains(permission);
- }
-
- private Set<String> loadProjectPermissions(String projectUuid) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- Optional<ComponentDto> component = dbClient.componentDao().selectByUuid(dbSession, projectUuid);
- if (!component.isPresent()) {
- return Collections.emptySet();
- }
- if (component.get().isPrivate()) {
- return loadDbPermissions(dbSession, projectUuid);
- }
- ImmutableSet.Builder<String> builder = ImmutableSet.builder();
- builder.addAll(PUBLIC_PERMISSIONS);
- builder.addAll(loadDbPermissions(dbSession, projectUuid));
- return builder.build();
- }
- }
-
- private Set<String> loadDbPermissions(DbSession dbSession, String projectUuid) {
- if (userDto != null && userDto.getId() != null) {
- return dbClient.authorizationDao().selectProjectPermissions(dbSession, projectUuid, userDto.getId());
- }
- return dbClient.authorizationDao().selectProjectPermissionsOfAnonymous(dbSession, projectUuid);
- }
-
- @Override
- protected List<ComponentDto> doKeepAuthorizedComponents(String permission, Collection<ComponentDto> components) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- Set<String> projectUuids = components.stream()
- .map(c -> defaultIfEmpty(c.getMainBranchProjectUuid(), c.projectUuid()))
- .collect(MoreCollectors.toSet(components.size()));
- Set<String> authorizedProjectUuids = dbClient.authorizationDao().keepAuthorizedProjectUuids(dbSession, projectUuids, getUserId(), permission);
-
- return components.stream()
- .filter(c -> authorizedProjectUuids.contains(c.projectUuid()) || authorizedProjectUuids.contains(c.getMainBranchProjectUuid()))
- .collect(MoreCollectors.toList(components.size()));
- }
- }
-
- @Override
- public boolean isSystemAdministrator() {
- return isSystemAdministratorSupplier.get();
- }
-
- private boolean loadIsSystemAdministrator() {
- if (isRoot()) {
- return true;
- }
- try (DbSession dbSession = dbClient.openSession(false)) {
- if (!organizationFlags.isEnabled(dbSession)) {
- String uuidOfDefaultOrg = defaultOrganizationProvider.get().getUuid();
- return hasPermission(OrganizationPermission.ADMINISTER, uuidOfDefaultOrg);
- }
- // organization feature is enabled -> requires to be root
- return false;
- }
- }
-
- @Override
- public boolean hasMembershipImpl(OrganizationDto organizationDto) {
- return isMember(organizationDto.getUuid());
- }
-
- private boolean isMember(String organizationUuid) {
- if (!isLoggedIn()) {
- return false;
- }
- if (isRoot()) {
- return true;
- }
-
- if (organizationMembership.contains(organizationUuid)) {
- return true;
- }
- try (DbSession dbSession = dbClient.openSession(false)) {
- Optional<OrganizationMemberDto> organizationMemberDto = dbClient.organizationMemberDao().select(dbSession, organizationUuid, requireNonNull(getUserId()));
- if (organizationMemberDto.isPresent()) {
- organizationMembership.add(organizationUuid);
- }
- return organizationMembership.contains(organizationUuid);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/SystemPasscode.java b/server/sonar-server/src/main/java/org/sonar/server/user/SystemPasscode.java
deleted file mode 100644
index 238f3088325..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/SystemPasscode.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.sonar.api.server.ws.Request;
-
-/**
- * Passcode for accessing some web services, usually for connecting
- * monitoring tools without using the credentials
- * of a system administrator.
- *
- * Important - the web services accepting passcode must be listed in
- * {@link org.sonar.server.authentication.UserSessionInitializer#URL_USING_PASSCODE}.
- */
-public interface SystemPasscode {
-
- /**
- * Whether the system passcode is provided by the HTTP request or not.
- * Returns {@code false} if passcode is not configured.
- */
- boolean isValid(Request request);
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/SystemPasscodeImpl.java b/server/sonar-server/src/main/java/org/sonar/server/user/SystemPasscodeImpl.java
deleted file mode 100644
index 1f68993e59b..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/SystemPasscodeImpl.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import java.util.Optional;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.Startable;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.utils.log.Loggers;
-
-@ServerSide
-public class SystemPasscodeImpl implements SystemPasscode, Startable {
-
- public static final String PASSCODE_HTTP_HEADER = "X-Sonar-Passcode";
- public static final String PASSCODE_CONF_PROPERTY = "sonar.web.systemPasscode";
-
- private final Configuration configuration;
- private String configuredPasscode;
-
- public SystemPasscodeImpl(Configuration configuration) {
- this.configuration = configuration;
- }
-
- @Override
- public boolean isValid(Request request) {
- if (configuredPasscode == null) {
- return false;
- }
- return request.header(PASSCODE_HTTP_HEADER)
- .map(s -> configuredPasscode.equals(s))
- .orElse(false);
- }
-
- @Override
- public void start() {
- Optional<String> passcodeOpt = configuration.get(PASSCODE_CONF_PROPERTY)
- // if present, result is never empty string
- .map(StringUtils::trimToNull);
-
- if (passcodeOpt.isPresent()) {
- logState("enabled");
- configuredPasscode = passcodeOpt.get();
- } else {
- logState("disabled");
- configuredPasscode = null;
- }
- }
-
- private void logState(String state) {
- Loggers.get(getClass()).info("System authentication by passcode is {}", state);
- }
-
- @Override
- public void stop() {
- // nothing to do
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java b/server/sonar-server/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java
deleted file mode 100644
index 3e5712bc5fa..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
-import javax.annotation.CheckForNull;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.user.GroupDto;
-import org.sonar.server.exceptions.UnauthorizedException;
-
-/**
- * Part of the current HTTP session
- */
-public class ThreadLocalUserSession implements UserSession {
-
- private static final ThreadLocal<UserSession> DELEGATE = new ThreadLocal<>();
-
- public UserSession get() {
- UserSession session = DELEGATE.get();
- if (session != null) {
- return session;
- }
- throw new UnauthorizedException("User is not authenticated");
- }
-
- public void set(UserSession session) {
- DELEGATE.set(session);
- }
-
- public void unload() {
- DELEGATE.remove();
- }
-
- public boolean hasSession() {
- return DELEGATE.get() != null;
- }
-
- @Override
- @CheckForNull
- public String getLogin() {
- return get().getLogin();
- }
-
- @Override
- @CheckForNull
- public String getUuid() {
- return get().getUuid();
- }
-
- @Override
- @CheckForNull
- public String getName() {
- return get().getName();
- }
-
- @Override
- @CheckForNull
- public Integer getUserId() {
- return get().getUserId();
- }
-
- @Override
- public Collection<GroupDto> getGroups() {
- return get().getGroups();
- }
-
- @Override
- public Optional<IdentityProvider> getIdentityProvider() {
- return get().getIdentityProvider();
- }
-
- @Override
- public Optional<ExternalIdentity> getExternalIdentity() {
- return get().getExternalIdentity();
- }
-
- @Override
- public boolean isLoggedIn() {
- return get().isLoggedIn();
- }
-
- @Override
- public UserSession checkIsRoot() {
- return get().checkIsRoot();
- }
-
- @Override
- public boolean isRoot() {
- return get().isRoot();
- }
-
- @Override
- public UserSession checkLoggedIn() {
- get().checkLoggedIn();
- return this;
- }
-
- @Override
- public boolean hasPermission(OrganizationPermission permission, String organizationUuid) {
- return get().hasPermission(permission, organizationUuid);
- }
-
- @Override
- public UserSession checkPermission(OrganizationPermission permission, String organizationUuid) {
- get().checkPermission(permission, organizationUuid);
- return this;
- }
-
- @Override
- public UserSession checkComponentPermission(String projectPermission, ComponentDto component) {
- get().checkComponentPermission(projectPermission, component);
- return this;
- }
-
- @Override
- public UserSession checkComponentUuidPermission(String permission, String componentUuid) {
- get().checkComponentUuidPermission(permission, componentUuid);
- return this;
- }
-
- @Override
- public boolean isSystemAdministrator() {
- return get().isSystemAdministrator();
- }
-
- @Override
- public UserSession checkIsSystemAdministrator() {
- get().checkIsSystemAdministrator();
- return this;
- }
-
- @Override
- public boolean hasComponentPermission(String permission, ComponentDto component) {
- return get().hasComponentPermission(permission, component);
- }
-
- @Override
- public boolean hasComponentUuidPermission(String permission, String componentUuid) {
- return get().hasComponentUuidPermission(permission, componentUuid);
- }
-
- @Override
- public UserSession checkPermission(OrganizationPermission permission, OrganizationDto organization) {
- get().checkPermission(permission, organization);
- return this;
- }
-
- @Override
- public boolean hasPermission(OrganizationPermission permission, OrganizationDto organization) {
- return get().hasPermission(permission, organization);
- }
-
- @Override
- public List<ComponentDto> keepAuthorizedComponents(String permission, Collection<ComponentDto> components) {
- return get().keepAuthorizedComponents(permission, components);
- }
-
- @Override
- public boolean hasMembership(OrganizationDto organizationDto) {
- return get().hasMembership(organizationDto);
- }
-
- @Override
- public UserSession checkMembership(OrganizationDto organization) {
- get().checkMembership(organization);
- return this;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/UpdateUser.java b/server/sonar-server/src/main/java/org/sonar/server/user/UpdateUser.java
deleted file mode 100644
index 746867d8285..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/UpdateUser.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import java.util.List;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-public class UpdateUser {
-
- private String login;
- private String name;
- private String email;
- private List<String> scmAccounts;
- private String password;
- private ExternalIdentity externalIdentity;
-
- private boolean loginChanged;
- private boolean nameChanged;
- private boolean emailChanged;
- private boolean scmAccountsChanged;
- private boolean passwordChanged;
- private boolean externalIdentityChanged;
-
- @CheckForNull
- public String login() {
- return login;
- }
-
- public UpdateUser setLogin(@Nullable String login) {
- this.login = login;
- loginChanged = true;
- return this;
- }
-
- @CheckForNull
- public String name() {
- return name;
- }
-
- public UpdateUser setName(@Nullable String name) {
- this.name = name;
- nameChanged = true;
- return this;
- }
-
- @CheckForNull
- public String email() {
- return email;
- }
-
- public UpdateUser setEmail(@Nullable String email) {
- this.email = email;
- emailChanged = true;
- return this;
- }
-
- @CheckForNull
- public List<String> scmAccounts() {
- return scmAccounts;
- }
-
- public UpdateUser setScmAccounts(@Nullable List<String> scmAccounts) {
- this.scmAccounts = scmAccounts;
- scmAccountsChanged = true;
- return this;
- }
-
- @CheckForNull
- public String password() {
- return password;
- }
-
- public UpdateUser setPassword(@Nullable String password) {
- this.password = password;
- passwordChanged = true;
- return this;
- }
-
- @CheckForNull
- public ExternalIdentity externalIdentity() {
- return externalIdentity;
- }
-
- /**
- * This method should only be used when updating a none local user
- */
- public UpdateUser setExternalIdentity(@Nullable ExternalIdentity externalIdentity) {
- this.externalIdentity = externalIdentity;
- externalIdentityChanged = true;
- return this;
- }
-
- public boolean isLoginChanged() {
- return loginChanged;
- }
-
- public boolean isNameChanged() {
- return nameChanged;
- }
-
- public boolean isEmailChanged() {
- return emailChanged;
- }
-
- public boolean isScmAccountsChanged() {
- return scmAccountsChanged;
- }
-
- public boolean isPasswordChanged() {
- return passwordChanged;
- }
-
- public boolean isExternalIdentityChanged() {
- return externalIdentityChanged;
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java b/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java
deleted file mode 100644
index 3399e36cdcc..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import javax.annotation.CheckForNull;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.user.GroupDto;
-
-import static java.util.Objects.requireNonNull;
-
-public interface UserSession {
-
- /**
- * Login of the authenticated user. Returns {@code null}
- * if {@link #isLoggedIn()} is {@code false}.
- */
- @CheckForNull
- String getLogin();
-
- /**
- * Uuid of the authenticated user. Returns {@code null}
- * if {@link #isLoggedIn()} is {@code false}.
- */
- @CheckForNull
- String getUuid();
-
- /**
- * Name of the authenticated user. Returns {@code null}
- * if {@link #isLoggedIn()} is {@code false}.
- */
- @CheckForNull
- String getName();
-
- /**
- * Database ID of the authenticated user. Returns {@code null}
- * if {@link #isLoggedIn()} is {@code false}.
- */
- @CheckForNull
- Integer getUserId();
-
- /**
- * The groups that the logged-in user is member of. An empty
- * collection is returned if {@link #isLoggedIn()} is {@code false}.
- */
- Collection<GroupDto> getGroups();
-
- /**
- * This enum supports by name only the few providers for which specific code exists.
- */
- enum IdentityProvider {
- SONARQUBE("sonarqube"), GITHUB("github"), BITBUCKETCLOUD("bitbucket"), OTHER("other");
-
- String key;
-
- IdentityProvider(String key) {
- this.key = key;
- }
-
- public String getKey() {
- return key;
- }
-
- public static IdentityProvider getFromKey(String key) {
- return Arrays.stream(IdentityProvider.values())
- .filter(i -> i.getKey().equals(key))
- .findAny()
- .orElse(OTHER);
- }
- }
-
- /**
- * @return empty if user is anonymous
- */
- Optional<IdentityProvider> getIdentityProvider();
-
- @Immutable
- final class ExternalIdentity {
- private final String id;
- private final String login;
-
- public ExternalIdentity(String id, String login) {
- this.id = requireNonNull(id, "id can't be null");
- this.login = requireNonNull(login, "login can't be null");
- }
-
- public String getId() {
- return id;
- }
-
- public String getLogin() {
- return login;
- }
-
- @Override
- public String toString() {
- return "ExternalIdentity{" +
- "id='" + id + '\'' +
- ", login='" + login + '\'' +
- '}';
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- ExternalIdentity that = (ExternalIdentity) o;
- return Objects.equals(id, that.id) &&
- Objects.equals(login, that.login);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(id, login);
- }
- }
-
- /**
- * @return empty if {@link #getIdentityProvider()} returns empty or {@link IdentityProvider#SONARQUBE}
- */
- Optional<ExternalIdentity> getExternalIdentity();
-
- /**
- * Whether the user is logged-in or anonymous.
- */
- boolean isLoggedIn();
-
- /**
- * Whether the user has root privileges. If {@code true}, then user automatically
- * benefits from all the permissions on all organizations and projects.
- */
- boolean isRoot();
-
- /**
- * Ensures that {@link #isRoot()} returns {@code true} otherwise throws a
- * {@link org.sonar.server.exceptions.ForbiddenException}.
- */
- UserSession checkIsRoot();
-
- /**
- * Ensures that user is logged in otherwise throws {@link org.sonar.server.exceptions.UnauthorizedException}.
- */
- UserSession checkLoggedIn();
-
- /**
- * Returns {@code true} if the permission is granted on the organization, otherwise {@code false}.
- *
- * If the organization does not exist, then returns {@code false}.
- *
- * Always returns {@code true} if {@link #isRoot()} is {@code true}, even if
- * organization does not exist.
- */
- boolean hasPermission(OrganizationPermission permission, OrganizationDto organization);
-
- boolean hasPermission(OrganizationPermission permission, String organizationUuid);
-
- /**
- * Ensures that {@link #hasPermission(OrganizationPermission, OrganizationDto)} is {@code true},
- * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}.
- */
- UserSession checkPermission(OrganizationPermission permission, OrganizationDto organization);
-
- UserSession checkPermission(OrganizationPermission permission, String organizationUuid);
-
- /**
- * Returns {@code true} if the permission is granted to user on the component,
- * otherwise {@code false}.
- *
- * If the component does not exist, then returns {@code false}.
- *
- * Always returns {@code true} if {@link #isRoot()} is {@code true}, even if
- * component does not exist.
- *
- * If the permission is not granted, then the organization permission is _not_ checked.
- *
- * @param component non-null component.
- * @param permission project permission as defined by {@link org.sonar.server.permission.PermissionService}
- */
- boolean hasComponentPermission(String permission, ComponentDto component);
-
- /**
- * Using {@link #hasComponentPermission(String, ComponentDto)} is recommended
- * because it does not have to load project if the referenced component
- * is not a project.
- *
- * @deprecated use {@link #hasComponentPermission(String, ComponentDto)} instead
- */
- @Deprecated
- boolean hasComponentUuidPermission(String permission, String componentUuid);
-
- /**
- * Return the subset of specified components which the user has granted permission.
- * An empty list is returned if input is empty or if no components are allowed to be
- * accessed.
- * If the input is ordered, then the returned components are in the same order.
- * The duplicated components are returned duplicated too.
- */
- List<ComponentDto> keepAuthorizedComponents(String permission, Collection<ComponentDto> components);
-
- /**
- * Ensures that {@link #hasComponentPermission(String, ComponentDto)} is {@code true},
- * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}.
- */
- UserSession checkComponentPermission(String projectPermission, ComponentDto component);
-
- /**
- * Ensures that {@link #hasComponentUuidPermission(String, String)} is {@code true},
- * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}.
- *
- * @deprecated use {@link #checkComponentPermission(String, ComponentDto)} instead
- */
- @Deprecated
- UserSession checkComponentUuidPermission(String permission, String componentUuid);
-
- /**
- * Whether user can administrate system, for example for using cross-organizations services
- * like update center, system info or management of users.
- *
- * Returns {@code true} if:
- * <ul>
- * <li>{@link #isRoot()} is {@code true}</li>
- * <li>organization feature is disabled and user is administrator of the (single) default organization</li>
- * </ul>
- */
- boolean isSystemAdministrator();
-
- /**
- * Ensures that {@link #isSystemAdministrator()} is {@code true},
- * otherwise throws {@link org.sonar.server.exceptions.ForbiddenException}.
- */
- UserSession checkIsSystemAdministrator();
-
- /**
- * Returns {@code true} if the user is member of the organization, otherwise {@code false}.
- *
- * If the organization does not exist, then returns {@code false}.
- *
- * Always returns {@code true} if {@link #isRoot()} is {@code true}, even if
- * organization does not exist.
- */
- boolean hasMembership(OrganizationDto organization);
-
- /**
- * Ensures that {@link #hasMembership(OrganizationDto)} is {@code true},
- * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}.
- */
- UserSession checkMembership(OrganizationDto organization);
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/UserSessionFactory.java b/server/sonar-server/src/main/java/org/sonar/server/user/UserSessionFactory.java
deleted file mode 100644
index 6c9500a4769..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/UserSessionFactory.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.sonar.api.server.ServerSide;
-import org.sonar.db.user.UserDto;
-
-@ServerSide
-public interface UserSessionFactory {
-
- UserSession create(UserDto user);
-
- UserSession createAnonymous();
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/UserSessionFactoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/user/UserSessionFactoryImpl.java
deleted file mode 100644
index 5574be514e8..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/UserSessionFactoryImpl.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.sonar.api.server.ServerSide;
-import org.sonar.db.DbClient;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.UserLastConnectionDatesUpdater;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.organization.OrganizationFlags;
-
-import static java.util.Objects.requireNonNull;
-
-@ServerSide
-public class UserSessionFactoryImpl implements UserSessionFactory {
-
- private final DbClient dbClient;
- private final DefaultOrganizationProvider defaultOrganizationProvider;
- private final OrganizationFlags organizationFlags;
- private final UserLastConnectionDatesUpdater userLastConnectionDatesUpdater;
-
- public UserSessionFactoryImpl(DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider,
- OrganizationFlags organizationFlags, UserLastConnectionDatesUpdater userLastConnectionDatesUpdater) {
- this.dbClient = dbClient;
- this.defaultOrganizationProvider = defaultOrganizationProvider;
- this.organizationFlags = organizationFlags;
- this.userLastConnectionDatesUpdater = userLastConnectionDatesUpdater;
- }
-
- @Override
- public ServerUserSession create(UserDto user) {
- requireNonNull(user, "UserDto must not be null");
- userLastConnectionDatesUpdater.updateLastConnectionDateIfNeeded(user);
- return new ServerUserSession(dbClient, organizationFlags, defaultOrganizationProvider, user);
- }
-
- @Override
- public ServerUserSession createAnonymous() {
- return new ServerUserSession(dbClient, organizationFlags, defaultOrganizationProvider, null);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/UserUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/user/UserUpdater.java
deleted file mode 100644
index 4c41bbd9ff7..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/UserUpdater.java
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Strings;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.math.RandomUtils;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.platform.NewUserHandler;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.organization.OrganizationMemberDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserGroupDto;
-import org.sonar.db.user.UserPropertyDto;
-import org.sonar.server.authentication.CredentialsLocalAuthentication;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.organization.OrganizationFlags;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-import org.sonar.server.util.Validation;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static com.google.common.collect.Lists.newArrayList;
-import static java.lang.String.format;
-import static java.util.Arrays.stream;
-import static java.util.stream.Stream.concat;
-import static org.sonar.api.CoreProperties.DEFAULT_ISSUE_ASSIGNEE;
-import static org.sonar.core.util.Slug.slugify;
-import static org.sonar.core.util.stream.MoreCollectors.toList;
-import static org.sonar.process.ProcessProperties.Property.ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS;
-import static org.sonar.server.exceptions.BadRequestException.checkRequest;
-
-@ServerSide
-public class UserUpdater {
-
- public static final String NOTIFICATIONS_READ_DATE = "notifications.readDate";
-
- private static final String SQ_AUTHORITY = "sonarqube";
-
- private static final String LOGIN_PARAM = "Login";
- private static final String PASSWORD_PARAM = "Password";
- private static final String NAME_PARAM = "Name";
- private static final String EMAIL_PARAM = "Email";
-
- public static final int LOGIN_MIN_LENGTH = 2;
- public static final int LOGIN_MAX_LENGTH = 255;
- public static final int EMAIL_MAX_LENGTH = 100;
- public static final int NAME_MAX_LENGTH = 200;
-
- private final NewUserNotifier newUserNotifier;
- private final DbClient dbClient;
- private final UserIndexer userIndexer;
- private final DefaultOrganizationProvider defaultOrganizationProvider;
- private final OrganizationFlags organizationFlags;
- private final DefaultGroupFinder defaultGroupFinder;
- private final Configuration config;
- private final CredentialsLocalAuthentication localAuthentication;
- private final System2 system2;
-
- public UserUpdater(System2 system2, NewUserNotifier newUserNotifier, DbClient dbClient, UserIndexer userIndexer, OrganizationFlags organizationFlags,
- DefaultOrganizationProvider defaultOrganizationProvider, DefaultGroupFinder defaultGroupFinder, Configuration config,
- CredentialsLocalAuthentication localAuthentication) {
- this.system2 = system2;
- this.newUserNotifier = newUserNotifier;
- this.dbClient = dbClient;
- this.userIndexer = userIndexer;
- this.organizationFlags = organizationFlags;
- this.defaultOrganizationProvider = defaultOrganizationProvider;
- this.defaultGroupFinder = defaultGroupFinder;
- this.config = config;
- this.localAuthentication = localAuthentication;
- }
-
- public UserDto createAndCommit(DbSession dbSession, NewUser newUser, Consumer<UserDto> beforeCommit, UserDto... otherUsersToIndex) {
- UserDto userDto = saveUser(dbSession, createDto(dbSession, newUser));
- return commitUser(dbSession, userDto, beforeCommit, otherUsersToIndex);
- }
-
- public UserDto reactivateAndCommit(DbSession dbSession, UserDto disabledUser, NewUser newUser, Consumer<UserDto> beforeCommit, UserDto... otherUsersToIndex) {
- checkArgument(!disabledUser.isActive(), "An active user with login '%s' already exists", disabledUser.getLogin());
- reactivateUser(dbSession, disabledUser, newUser);
- return commitUser(dbSession, disabledUser, beforeCommit, otherUsersToIndex);
- }
-
- private void reactivateUser(DbSession dbSession, UserDto reactivatedUser, NewUser newUser) {
- UpdateUser updateUser = new UpdateUser()
- .setName(newUser.name())
- .setEmail(newUser.email())
- .setScmAccounts(newUser.scmAccounts())
- .setExternalIdentity(newUser.externalIdentity());
- String login = newUser.login();
- if (login != null) {
- updateUser.setLogin(login);
- }
- String password = newUser.password();
- if (password != null) {
- updateUser.setPassword(password);
- }
- setOnboarded(reactivatedUser);
- updateDto(dbSession, updateUser, reactivatedUser);
- updateUser(dbSession, reactivatedUser);
- boolean isOrganizationEnabled = organizationFlags.isEnabled(dbSession);
- if (isOrganizationEnabled) {
- setNotificationsReadDate(dbSession, reactivatedUser);
- } else {
- addUserToDefaultOrganizationAndDefaultGroup(dbSession, reactivatedUser);
- }
- }
-
- public void updateAndCommit(DbSession dbSession, UserDto dto, UpdateUser updateUser, Consumer<UserDto> beforeCommit, UserDto... otherUsersToIndex) {
- boolean isUserUpdated = updateDto(dbSession, updateUser, dto);
- if (isUserUpdated) {
- // at least one change. Database must be updated and Elasticsearch re-indexed
- updateUser(dbSession, dto);
- commitUser(dbSession, dto, beforeCommit, otherUsersToIndex);
- } else {
- // no changes but still execute the consumer
- beforeCommit.accept(dto);
- dbSession.commit();
- }
- }
-
- private UserDto commitUser(DbSession dbSession, UserDto userDto, Consumer<UserDto> beforeCommit, UserDto... otherUsersToIndex) {
- beforeCommit.accept(userDto);
- userIndexer.commitAndIndex(dbSession, concat(Stream.of(userDto), stream(otherUsersToIndex)).collect(toList()));
- notifyNewUser(userDto.getLogin(), userDto.getName(), userDto.getEmail());
- return userDto;
- }
-
- private UserDto createDto(DbSession dbSession, NewUser newUser) {
- UserDto userDto = new UserDto();
- List<String> messages = new ArrayList<>();
-
- String login = newUser.login();
- if (isNullOrEmpty(login)) {
- userDto.setLogin(generateUniqueLogin(dbSession, newUser.name()));
- } else if (validateLoginFormat(login, messages)) {
- checkLoginUniqueness(dbSession, login);
- userDto.setLogin(login);
- }
-
- String name = newUser.name();
- if (validateNameFormat(name, messages)) {
- userDto.setName(name);
- }
-
- String email = newUser.email();
- if (email != null && validateEmailFormat(email, messages)) {
- userDto.setEmail(email);
- }
-
- String password = newUser.password();
- if (password != null && validatePasswords(password, messages)) {
- localAuthentication.storeHashPassword(userDto, password);
- }
-
- List<String> scmAccounts = sanitizeScmAccounts(newUser.scmAccounts());
- if (scmAccounts != null && !scmAccounts.isEmpty() && validateScmAccounts(dbSession, scmAccounts, login, email, null, messages)) {
- userDto.setScmAccounts(scmAccounts);
- }
-
- setExternalIdentity(dbSession, userDto, newUser.externalIdentity());
- setOnboarded(userDto);
-
- checkRequest(messages.isEmpty(), messages);
- return userDto;
- }
-
- private String generateUniqueLogin(DbSession dbSession, String userName) {
- String slugName = slugify(userName);
- for (int i = 0; i < 10; i++) {
- String login = slugName + RandomUtils.nextInt(100_000);
- UserDto existingUser = dbClient.userDao().selectByLogin(dbSession, login);
- if (existingUser == null) {
- return login;
- }
- }
- throw new IllegalStateException("Cannot create unique login for user name " + userName);
- }
-
- private boolean updateDto(DbSession dbSession, UpdateUser update, UserDto dto) {
- List<String> messages = newArrayList();
- boolean changed = updateLogin(dbSession, update, dto, messages);
- changed |= updateName(update, dto, messages);
- changed |= updateEmail(update, dto, messages);
- changed |= updateExternalIdentity(dbSession, update, dto);
- changed |= updatePassword(update, dto, messages);
- changed |= updateScmAccounts(dbSession, update, dto, messages);
- checkRequest(messages.isEmpty(), messages);
- return changed;
- }
-
- private boolean updateLogin(DbSession dbSession, UpdateUser updateUser, UserDto userDto, List<String> messages) {
- String newLogin = updateUser.login();
- if (!updateUser.isLoginChanged() || !validateLoginFormat(newLogin, messages) || Objects.equals(userDto.getLogin(), newLogin)) {
- return false;
- }
- checkLoginUniqueness(dbSession, newLogin);
- dbClient.propertiesDao().selectByKeyAndMatchingValue(dbSession, DEFAULT_ISSUE_ASSIGNEE, userDto.getLogin())
- .forEach(p -> dbClient.propertiesDao().saveProperty(p.setValue(newLogin)));
- userDto.setLogin(newLogin);
- if (userDto.isLocal()) {
- userDto.setExternalLogin(newLogin);
- userDto.setExternalId(newLogin);
- }
- return true;
- }
-
- private static boolean updateName(UpdateUser updateUser, UserDto userDto, List<String> messages) {
- String name = updateUser.name();
- if (updateUser.isNameChanged() && validateNameFormat(name, messages) && !Objects.equals(userDto.getName(), name)) {
- userDto.setName(name);
- return true;
- }
- return false;
- }
-
- private static boolean updateEmail(UpdateUser updateUser, UserDto userDto, List<String> messages) {
- String email = updateUser.email();
- if (updateUser.isEmailChanged() && validateEmailFormat(email, messages) && !Objects.equals(userDto.getEmail(), email)) {
- userDto.setEmail(email);
- return true;
- }
- return false;
- }
-
- private boolean updateExternalIdentity(DbSession dbSession, UpdateUser updateUser, UserDto userDto) {
- ExternalIdentity externalIdentity = updateUser.externalIdentity();
- if (updateUser.isExternalIdentityChanged() && !isSameExternalIdentity(userDto, externalIdentity)) {
- setExternalIdentity(dbSession, userDto, externalIdentity);
- return true;
- }
- return false;
- }
-
- private boolean updatePassword(UpdateUser updateUser, UserDto userDto, List<String> messages) {
- String password = updateUser.password();
- if (updateUser.isPasswordChanged() && validatePasswords(password, messages) && checkPasswordChangeAllowed(userDto, messages)) {
- localAuthentication.storeHashPassword(userDto, password);
- return true;
- }
- return false;
- }
-
- private boolean updateScmAccounts(DbSession dbSession, UpdateUser updateUser, UserDto userDto, List<String> messages) {
- String email = updateUser.email();
- List<String> scmAccounts = sanitizeScmAccounts(updateUser.scmAccounts());
- List<String> existingScmAccounts = userDto.getScmAccountsAsList();
- if (updateUser.isScmAccountsChanged() && !(existingScmAccounts.containsAll(scmAccounts) && scmAccounts.containsAll(existingScmAccounts))) {
- if (!scmAccounts.isEmpty()) {
- String newOrOldEmail = email != null ? email : userDto.getEmail();
- if (validateScmAccounts(dbSession, scmAccounts, userDto.getLogin(), newOrOldEmail, userDto, messages)) {
- userDto.setScmAccounts(scmAccounts);
- }
- } else {
- userDto.setScmAccounts((String) null);
- }
- return true;
- }
- return false;
- }
-
- private static boolean isSameExternalIdentity(UserDto dto, @Nullable ExternalIdentity externalIdentity) {
- return externalIdentity != null
- && !dto.isLocal()
- && Objects.equals(dto.getExternalId(), externalIdentity.getId())
- && Objects.equals(dto.getExternalLogin(), externalIdentity.getLogin())
- && Objects.equals(dto.getExternalIdentityProvider(), externalIdentity.getProvider());
- }
-
- private void setExternalIdentity(DbSession dbSession, UserDto dto, @Nullable ExternalIdentity externalIdentity) {
- if (externalIdentity == null) {
- dto.setExternalLogin(dto.getLogin());
- dto.setExternalIdentityProvider(SQ_AUTHORITY);
- dto.setExternalId(dto.getLogin());
- dto.setLocal(true);
- } else {
- dto.setExternalLogin(externalIdentity.getLogin());
- dto.setExternalIdentityProvider(externalIdentity.getProvider());
- dto.setExternalId(externalIdentity.getId());
- dto.setLocal(false);
- dto.setSalt(null);
- dto.setCryptedPassword(null);
- }
- UserDto existingUser = dbClient.userDao().selectByExternalIdAndIdentityProvider(dbSession, dto.getExternalId(), dto.getExternalIdentityProvider());
- checkArgument(existingUser == null || Objects.equals(dto.getUuid(), existingUser.getUuid()),
- "A user with provider id '%s' and identity provider '%s' already exists", dto.getExternalId(), dto.getExternalIdentityProvider());
- }
-
- private void setOnboarded(UserDto userDto) {
- boolean showOnboarding = config.getBoolean(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey()).orElse(false);
- userDto.setOnboarded(!showOnboarding);
- }
-
- private static boolean checkNotEmptyParam(@Nullable String value, String param, List<String> messages) {
- if (isNullOrEmpty(value)) {
- messages.add(format(Validation.CANT_BE_EMPTY_MESSAGE, param));
- return false;
- }
- return true;
- }
-
- private static boolean validateLoginFormat(@Nullable String login, List<String> messages) {
- boolean isValid = checkNotEmptyParam(login, LOGIN_PARAM, messages);
- if (!isNullOrEmpty(login)) {
- if (login.length() < LOGIN_MIN_LENGTH) {
- messages.add(format(Validation.IS_TOO_SHORT_MESSAGE, LOGIN_PARAM, LOGIN_MIN_LENGTH));
- return false;
- } else if (login.length() > LOGIN_MAX_LENGTH) {
- messages.add(format(Validation.IS_TOO_LONG_MESSAGE, LOGIN_PARAM, LOGIN_MAX_LENGTH));
- return false;
- } else if (!login.matches("\\A\\w[\\w\\.\\-_@]+\\z")) {
- messages.add("Use only letters, numbers, and .-_@ please.");
- return false;
- }
- }
- return isValid;
- }
-
- private static boolean validateNameFormat(@Nullable String name, List<String> messages) {
- boolean isValid = checkNotEmptyParam(name, NAME_PARAM, messages);
- if (name != null && name.length() > NAME_MAX_LENGTH) {
- messages.add(format(Validation.IS_TOO_LONG_MESSAGE, NAME_PARAM, 200));
- return false;
- }
- return isValid;
- }
-
- private static boolean validateEmailFormat(@Nullable String email, List<String> messages) {
- if (email != null && email.length() > EMAIL_MAX_LENGTH) {
- messages.add(format(Validation.IS_TOO_LONG_MESSAGE, EMAIL_PARAM, 100));
- return false;
- }
- return true;
- }
-
- private static boolean checkPasswordChangeAllowed(UserDto userDto, List<String> messages) {
- if (!userDto.isLocal()) {
- messages.add("Password cannot be changed when external authentication is used");
- return false;
- }
- return true;
- }
-
- private static boolean validatePasswords(@Nullable String password, List<String> messages) {
- if (password == null || password.length() == 0) {
- messages.add(format(Validation.CANT_BE_EMPTY_MESSAGE, PASSWORD_PARAM));
- return false;
- }
- return true;
- }
-
- private boolean validateScmAccounts(DbSession dbSession, List<String> scmAccounts, @Nullable String login, @Nullable String email, @Nullable UserDto existingUser,
- List<String> messages) {
- boolean isValid = true;
- for (String scmAccount : scmAccounts) {
- if (scmAccount.equals(login) || scmAccount.equals(email)) {
- messages.add("Login and email are automatically considered as SCM accounts");
- isValid = false;
- } else {
- List<UserDto> matchingUsers = dbClient.userDao().selectByScmAccountOrLoginOrEmail(dbSession, scmAccount);
- List<String> matchingUsersWithoutExistingUser = newArrayList();
- for (UserDto matchingUser : matchingUsers) {
- if (existingUser != null && matchingUser.getId().equals(existingUser.getId())) {
- continue;
- }
- matchingUsersWithoutExistingUser.add(getNameOrLogin(matchingUser) + " (" + matchingUser.getLogin() + ")");
- }
- if (!matchingUsersWithoutExistingUser.isEmpty()) {
- messages.add(format("The scm account '%s' is already used by user(s) : '%s'", scmAccount, Joiner.on(", ").join(matchingUsersWithoutExistingUser)));
- isValid = false;
- }
- }
- }
- return isValid;
- }
-
- private static String getNameOrLogin(UserDto user) {
- String name = user.getName();
- return name != null ? name : user.getLogin();
- }
-
- private static List<String> sanitizeScmAccounts(@Nullable List<String> scmAccounts) {
- if (scmAccounts != null) {
- return new HashSet<>(scmAccounts).stream()
- .map(Strings::emptyToNull)
- .filter(Objects::nonNull)
- .sorted(String::compareToIgnoreCase)
- .collect(toList(scmAccounts.size()));
- }
- return Collections.emptyList();
- }
-
- private void checkLoginUniqueness(DbSession dbSession, String login) {
- UserDto existingUser = dbClient.userDao().selectByLogin(dbSession, login);
- checkArgument(existingUser == null, "A user with login '%s' already exists", login);
- }
-
- private UserDto saveUser(DbSession dbSession, UserDto userDto) {
- userDto.setActive(true);
- UserDto res = dbClient.userDao().insert(dbSession, userDto);
- boolean isOrganizationEnabled = organizationFlags.isEnabled(dbSession);
- if (isOrganizationEnabled) {
- setNotificationsReadDate(dbSession, userDto);
- } else {
- addUserToDefaultOrganizationAndDefaultGroup(dbSession, userDto);
- }
-
- return res;
- }
-
- private void updateUser(DbSession dbSession, UserDto dto) {
- dto.setActive(true);
- dbClient.userDao().update(dbSession, dto);
- }
-
- private void notifyNewUser(String login, String name, @Nullable String email) {
- newUserNotifier.onNewUser(NewUserHandler.Context.builder()
- .setLogin(login)
- .setName(name)
- .setEmail(email)
- .build());
- }
-
- private static boolean isUserAlreadyMemberOfDefaultGroup(GroupDto defaultGroup, List<GroupDto> userGroups) {
- return userGroups.stream().anyMatch(group -> defaultGroup.getId().equals(group.getId()));
- }
-
- private void addUserToDefaultOrganizationAndDefaultGroup(DbSession dbSession, UserDto userDto) {
- addUserToDefaultOrganization(dbSession, userDto);
- addDefaultGroup(dbSession, userDto);
- }
-
- private void addUserToDefaultOrganization(DbSession dbSession, UserDto userDto) {
- String defOrgUuid = defaultOrganizationProvider.get().getUuid();
- dbClient.organizationMemberDao().insert(dbSession, new OrganizationMemberDto().setOrganizationUuid(defOrgUuid).setUserId(userDto.getId()));
- }
-
- private void addDefaultGroup(DbSession dbSession, UserDto userDto) {
- String defOrgUuid = defaultOrganizationProvider.get().getUuid();
- List<GroupDto> userGroups = dbClient.groupDao().selectByUserLogin(dbSession, userDto.getLogin());
- GroupDto defaultGroup = defaultGroupFinder.findDefaultGroup(dbSession, defOrgUuid);
- if (isUserAlreadyMemberOfDefaultGroup(defaultGroup, userGroups)) {
- return;
- }
- dbClient.userGroupDao().insert(dbSession, new UserGroupDto().setUserId(userDto.getId()).setGroupId(defaultGroup.getId()));
- }
-
- private void setNotificationsReadDate(DbSession dbSession, UserDto user) {
- dbClient.userPropertiesDao().insertOrUpdate(dbSession, new UserPropertyDto()
- .setUserUuid(user.getUuid())
- .setKey(NOTIFICATIONS_READ_DATE)
- .setValue(Long.toString(system2.now())));
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/user/package-info.java
deleted file mode 100644
index 15949569de4..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/user/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.server.user;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupCreator.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupCreator.java
deleted file mode 100644
index b6fa36c1225..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupCreator.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usergroups;
-
-import org.sonar.db.DbSession;
-import org.sonar.db.user.GroupDto;
-
-public interface DefaultGroupCreator {
-
- /**
- * Create the default group on the given organization
- */
- GroupDto create(DbSession dbSession, String organizationUuid);
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupCreatorImpl.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupCreatorImpl.java
deleted file mode 100644
index 4d7e1836a11..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupCreatorImpl.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usergroups;
-
-import java.util.Optional;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.user.GroupDto;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-public class DefaultGroupCreatorImpl implements DefaultGroupCreator {
-
- static final String DEFAULT_GROUP_NAME = "Members";
- private final DbClient dbClient;
-
- public DefaultGroupCreatorImpl(DbClient dbClient) {
- this.dbClient = dbClient;
- }
-
- public GroupDto create(DbSession dbSession, String organizationUuid) {
- Optional<GroupDto> existingMembersGroup = dbClient.groupDao().selectByName(dbSession, organizationUuid, DEFAULT_GROUP_NAME);
- checkArgument(!existingMembersGroup.isPresent(), "The group '%s' already exist on organization '%s'", DEFAULT_GROUP_NAME, organizationUuid);
-
- GroupDto defaultGroup = new GroupDto()
- .setName(DEFAULT_GROUP_NAME)
- .setDescription("All members of the organization")
- .setOrganizationUuid(organizationUuid);
- dbClient.groupDao().insert(dbSession, defaultGroup);
- dbClient.organizationDao().setDefaultGroupId(dbSession, organizationUuid, defaultGroup);
- return defaultGroup;
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupFinder.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupFinder.java
deleted file mode 100644
index ec4fc062633..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/DefaultGroupFinder.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usergroups;
-
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.user.GroupDto;
-
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-
-public class DefaultGroupFinder {
-
- private final DbClient dbClient;
-
- public DefaultGroupFinder(DbClient dbClient) {
- this.dbClient = dbClient;
- }
-
- public GroupDto findDefaultGroup(DbSession dbSession, String organizationUuid) {
- int defaultGroupId = dbClient.organizationDao().getDefaultGroupId(dbSession, organizationUuid)
- .orElseThrow(() -> new IllegalStateException(format("Default group cannot be found on organization '%s'", organizationUuid)));
- return requireNonNull(dbClient.groupDao().selectById(dbSession, defaultGroupId), format("Group '%s' cannot be found", defaultGroupId));
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/package-info.java
deleted file mode 100644
index 7d41d8701a5..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.server.usergroups;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/usertoken/TokenGenerator.java b/server/sonar-server/src/main/java/org/sonar/server/usertoken/TokenGenerator.java
deleted file mode 100644
index 41f9d5f7665..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/usertoken/TokenGenerator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usertoken;
-
-public interface TokenGenerator {
- /**
- * Generate a token. It must be unique and non deterministic.<br />
- * Underlying algorithm, format and max length are
- * subject to change in subsequent SonarQube versions.
- * <br/>
- * Length does not exceed 40 characters (arbitrary value).
- * Token is composed of hexadecimal characters only (0-9, a-f)
- * <br/>
- * The token is sent through the userid field (login) of HTTP Basic authentication,
- *
- * Basic authentication is used to authenticate users from tokens, so the
- * constraints of userid field (login) must be respected. Basically the token
- * must not contain colon character ":".
- *
- */
- String generate();
-
- /**
- * Hash a token.<br/>
- * Underlying algorithm, format and max length are
- * subject to change in subsequent SonarQube versions.
- * <br />
- * Length must not exceed 255 characters.
- * Hash is composed of hexadecimal characters only (0-9, a-f)
- */
- String hash(String token);
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/usertoken/TokenGeneratorImpl.java b/server/sonar-server/src/main/java/org/sonar/server/usertoken/TokenGeneratorImpl.java
deleted file mode 100644
index 16ccabb009d..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/usertoken/TokenGeneratorImpl.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usertoken;
-
-import java.security.SecureRandom;
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.codec.digest.DigestUtils;
-
-public class TokenGeneratorImpl implements TokenGenerator {
- @Override
- public String generate() {
- SecureRandom random = new SecureRandom();
- byte[] bytes = new byte[20];
- random.nextBytes(bytes);
- return Hex.encodeHexString(bytes);
- }
-
- @Override
- public String hash(String token) {
- return DigestUtils.sha384Hex(token);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/usertoken/UserTokenAuthentication.java b/server/sonar-server/src/main/java/org/sonar/server/usertoken/UserTokenAuthentication.java
deleted file mode 100644
index f3fdb952c94..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/usertoken/UserTokenAuthentication.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usertoken;
-
-import java.util.Optional;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.user.UserTokenDto;
-import org.sonar.server.authentication.UserLastConnectionDatesUpdater;
-
-import static java.util.Optional.empty;
-import static java.util.Optional.of;
-
-public class UserTokenAuthentication {
- private final TokenGenerator tokenGenerator;
- private final DbClient dbClient;
- private final UserLastConnectionDatesUpdater userLastConnectionDatesUpdater;
-
- public UserTokenAuthentication(TokenGenerator tokenGenerator, DbClient dbClient, UserLastConnectionDatesUpdater userLastConnectionDatesUpdater) {
- this.tokenGenerator = tokenGenerator;
- this.dbClient = dbClient;
- this.userLastConnectionDatesUpdater = userLastConnectionDatesUpdater;
- }
-
- /**
- * Returns the user uuid if the token hash is found, else {@code Optional.absent()}.
- * The returned uuid is not validated. If database is corrupted (table USER_TOKENS badly purged
- * for instance), then the uuid may not relate to a valid user.
- */
- public Optional<String> authenticate(String token) {
- String tokenHash = tokenGenerator.hash(token);
- try (DbSession dbSession = dbClient.openSession(false)) {
- UserTokenDto userToken = dbClient.userTokenDao().selectByTokenHash(dbSession, tokenHash);
- if (userToken == null) {
- return empty();
- }
- userLastConnectionDatesUpdater.updateLastConnectionDateIfNeeded(userToken);
- return of(userToken.getUserUuid());
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/usertoken/UserTokenModule.java b/server/sonar-server/src/main/java/org/sonar/server/usertoken/UserTokenModule.java
deleted file mode 100644
index 7f3bd962a68..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/usertoken/UserTokenModule.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usertoken;
-
-import org.sonar.core.platform.Module;
-
-public class UserTokenModule extends Module {
- @Override
- protected void configureModule() {
- add(
- UserTokenAuthentication.class,
- TokenGeneratorImpl.class);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/usertoken/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/usertoken/package-info.java
deleted file mode 100644
index 449f4017a05..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/usertoken/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.server.usertoken;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/BooleanTypeValidation.java b/server/sonar-server/src/main/java/org/sonar/server/util/BooleanTypeValidation.java
deleted file mode 100644
index 1b3ade32e60..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/BooleanTypeValidation.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import java.util.List;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.PropertyType;
-
-import static org.sonar.server.exceptions.BadRequestException.checkRequest;
-
-public class BooleanTypeValidation implements TypeValidation {
-
- @Override
- public String key() {
- return PropertyType.BOOLEAN.name();
- }
-
- @Override
- public void validate(String value, @Nullable List<String> options) {
- checkRequest(StringUtils.equalsIgnoreCase(value, "true") || StringUtils.equalsIgnoreCase(value, "false"),
- "Value '%s' must be one of \"true\" or \"false\".", value);
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/FloatTypeValidation.java b/server/sonar-server/src/main/java/org/sonar/server/util/FloatTypeValidation.java
deleted file mode 100644
index fd221dced55..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/FloatTypeValidation.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import java.util.List;
-import javax.annotation.Nullable;
-import org.sonar.api.PropertyType;
-import org.sonar.server.exceptions.BadRequestException;
-
-import static java.lang.String.format;
-
-public class FloatTypeValidation implements TypeValidation {
-
- @Override
- public String key() {
- return PropertyType.FLOAT.name();
- }
-
- @Override
- public void validate(String value, @Nullable List<String> options) {
- try {
- Double.parseDouble(value);
- } catch (NumberFormatException e) {
- throw BadRequestException.create(format("Value '%s' must be an floating point number.", value));
- }
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/IntegerTypeValidation.java b/server/sonar-server/src/main/java/org/sonar/server/util/IntegerTypeValidation.java
deleted file mode 100644
index 84502df47f7..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/IntegerTypeValidation.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import java.util.List;
-import javax.annotation.Nullable;
-import org.sonar.api.PropertyType;
-import org.sonar.server.exceptions.BadRequestException;
-
-import static java.lang.String.format;
-
-public class IntegerTypeValidation implements TypeValidation {
-
- @Override
- public String key() {
- return PropertyType.INTEGER.name();
- }
-
- @Override
- public void validate(String value, @Nullable List<String> options) {
- try {
- Integer.parseInt(value);
- } catch (NumberFormatException e) {
- throw BadRequestException.create(format("Value '%s' must be an integer.", value));
- }
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/LongTypeValidation.java b/server/sonar-server/src/main/java/org/sonar/server/util/LongTypeValidation.java
deleted file mode 100644
index 9ca540a1d1d..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/LongTypeValidation.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import java.util.List;
-import javax.annotation.Nullable;
-import org.sonar.api.PropertyType;
-import org.sonar.server.exceptions.BadRequestException;
-
-import static java.lang.String.format;
-
-public class LongTypeValidation implements TypeValidation {
- @Override
- public String key() {
- return PropertyType.LONG.name();
- }
-
- @Override
- public void validate(String value, @Nullable List<String> options) {
- try {
- Long.parseLong(value);
- } catch (NumberFormatException e) {
- throw BadRequestException.create(format("Value '%s' must be a long.", value));
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/MetricKeyValidator.java b/server/sonar-server/src/main/java/org/sonar/server/util/MetricKeyValidator.java
deleted file mode 100644
index 275341cf1cf..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/MetricKeyValidator.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-public class MetricKeyValidator {
- /*
- * Allowed characters are alphanumeric, '-', '_', with at least one non-digit
- */
- private static final String VALID_METRIC_KEY_REGEXP = "[\\p{Alnum}\\-_]*[\\p{Alpha}\\-_]+[\\p{Alnum}\\-_]*";
-
- private MetricKeyValidator() {
- // static stuff only
- }
-
- /**
- * <p>Test if given parameter is valid for a project/module. Valid format is:</p>
- * <ul>
- * <li>Allowed characters:
- * <ul>
- * <li>Uppercase ASCII letters A-Z</li>
- * <li>Lowercase ASCII letters a-z</li>
- * <li>ASCII digits 0-9</li>
- * <li>Punctuation signs dash '-', underscore '_'</li>
- * </ul>
- * </li>
- * <li>At least one non-digit</li>
- * </ul>
- * @param candidateKey
- * @return <code>true</code> if <code>candidateKey</code> can be used for a metric
- */
- public static boolean isMetricKeyValid(String candidateKey) {
- return candidateKey.matches(VALID_METRIC_KEY_REGEXP);
- }
-
- public static String checkMetricKeyFormat(String candidateKey) {
- if (!isMetricKeyValid(candidateKey)) {
- throw new IllegalArgumentException(String.format("Malformed metric key '%s'. Allowed characters are alphanumeric, '-', '_', with at least one non-digit.",
- candidateKey));
- }
-
- return candidateKey;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java b/server/sonar-server/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java
deleted file mode 100644
index ba8598a7786..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import java.util.List;
-import javax.annotation.Nullable;
-import org.sonar.api.PropertyType;
-import org.sonar.api.measures.Metric;
-import org.sonar.server.exceptions.BadRequestException;
-
-import static java.lang.String.format;
-
-public class MetricLevelTypeValidation implements TypeValidation {
- @Override
- public String key() {
- return PropertyType.METRIC_LEVEL.name();
- }
-
- @Override
- public void validate(String value, @Nullable List<String> options) {
- try {
- Metric.Level.valueOf(value);
- } catch (IllegalArgumentException e) {
- throw BadRequestException.create(format("Value '%s' must be one of \"OK\", \"ERROR\".", value));
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/StringListTypeValidation.java b/server/sonar-server/src/main/java/org/sonar/server/util/StringListTypeValidation.java
deleted file mode 100644
index acb1c7dca8f..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/StringListTypeValidation.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import java.util.List;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.PropertyType;
-
-import static org.sonar.server.exceptions.BadRequestException.checkRequest;
-
-public class StringListTypeValidation implements TypeValidation {
-
- @Override
- public String key() {
- return PropertyType.SINGLE_SELECT_LIST.name();
- }
-
- @Override
- public void validate(String value, @Nullable List<String> options) {
- checkRequest(options == null || options.contains(value), "Value '%s' must be one of : %s.", value, StringUtils.join(options, ", "));
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/StringTypeValidation.java b/server/sonar-server/src/main/java/org/sonar/server/util/StringTypeValidation.java
deleted file mode 100644
index 3851ede0e81..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/StringTypeValidation.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import org.sonar.api.PropertyType;
-
-import javax.annotation.Nullable;
-
-import java.util.List;
-
-public class StringTypeValidation implements TypeValidation {
-
- @Override
- public String key() {
- return PropertyType.STRING.name();
- }
-
- @Override
- public void validate(String value, @Nullable List<String> options) {
- // Nothing to do
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/TextTypeValidation.java b/server/sonar-server/src/main/java/org/sonar/server/util/TextTypeValidation.java
deleted file mode 100644
index c26ad125162..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/TextTypeValidation.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import org.sonar.api.PropertyType;
-
-import javax.annotation.Nullable;
-
-import java.util.List;
-
-public class TextTypeValidation implements TypeValidation {
-
- @Override
- public String key() {
- return PropertyType.TEXT.name();
- }
-
- @Override
- public void validate(String value, @Nullable List<String> options) {
- // Nothing to do
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/TypeValidation.java b/server/sonar-server/src/main/java/org/sonar/server/util/TypeValidation.java
deleted file mode 100644
index 797a3438d8f..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/TypeValidation.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import org.sonar.api.server.ServerSide;
-
-import javax.annotation.Nullable;
-
-import java.util.List;
-
-@ServerSide
-public interface TypeValidation {
-
- String key();
-
- void validate(String value, @Nullable List<String> options);
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/TypeValidationModule.java b/server/sonar-server/src/main/java/org/sonar/server/util/TypeValidationModule.java
deleted file mode 100644
index 3cc4f038e5e..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/TypeValidationModule.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import org.sonar.core.platform.Module;
-
-public class TypeValidationModule extends Module {
- @Override
- protected void configureModule() {
- add(
- TypeValidations.class,
- IntegerTypeValidation.class,
- FloatTypeValidation.class,
- BooleanTypeValidation.class,
- TextTypeValidation.class,
- StringTypeValidation.class,
- StringListTypeValidation.class,
- LongTypeValidation.class,
- MetricLevelTypeValidation.class
- );
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/TypeValidations.java b/server/sonar-server/src/main/java/org/sonar/server/util/TypeValidations.java
deleted file mode 100644
index 2c8883b77eb..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/TypeValidations.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import java.util.List;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.sonar.api.server.ServerSide;
-
-import static org.sonar.server.exceptions.BadRequestException.checkRequest;
-
-@ServerSide
-public class TypeValidations {
-
- private final List<TypeValidation> typeValidationList;
-
- public TypeValidations(List<TypeValidation> typeValidationList) {
- this.typeValidationList = typeValidationList;
- }
-
- public void validate(List<String> values, String type, List<String> options) {
- TypeValidation typeValidation = findByKey(type);
- for (String value : values) {
- typeValidation.validate(value, options);
- }
- }
-
- public void validate(String value, String type, @Nullable List<String> options) {
- TypeValidation typeValidation = findByKey(type);
- typeValidation.validate(value, options);
- }
-
- private TypeValidation findByKey(String key) {
- TypeValidation typeValidation = Iterables.find(typeValidationList, new TypeValidationMatchKey(key), null);
- checkRequest(typeValidation != null, "Type '%s' is not valid.", key);
- return typeValidation;
- }
-
- private static class TypeValidationMatchKey implements Predicate<TypeValidation> {
- private final String key;
-
- public TypeValidationMatchKey(String key) {
- this.key = key;
- }
-
- @Override
- public boolean apply(@Nonnull TypeValidation input) {
- return input.key().equals(key);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/Validation.java b/server/sonar-server/src/main/java/org/sonar/server/util/Validation.java
deleted file mode 100644
index 99d28d0bc96..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/util/Validation.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-public class Validation {
-
- public static final String CANT_BE_EMPTY_MESSAGE = "%s can't be empty";
- public static final String IS_TOO_SHORT_MESSAGE = "%s is too short (minimum is %s characters)";
- public static final String IS_TOO_LONG_MESSAGE = "%s is too long (maximum is %s characters)";
- public static final String IS_ALREADY_USED_MESSAGE = "%s has already been taken";
-
- private Validation() {
- // only static methods
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/AuthenticationModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/AuthenticationModuleTest.java
deleted file mode 100644
index 8d281d4cb01..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/AuthenticationModuleTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
-
-public class AuthenticationModuleTest {
-
- @Test
- public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
- new AuthenticationModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 20);
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/BaseContextFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/BaseContextFactoryTest.java
deleted file mode 100644
index de51e18f546..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/BaseContextFactoryTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.platform.Server;
-import org.sonar.api.server.authentication.BaseIdentityProvider;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.user.TestUserSessionFactory;
-import org.sonar.server.user.ThreadLocalUserSession;
-import org.sonar.server.user.UserSession;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class BaseContextFactoryTest {
-
- private static final String PUBLIC_ROOT_URL = "https://mydomain.com";
-
- private static final UserIdentity USER_IDENTITY = UserIdentity.builder()
- .setProviderId("ABCD")
- .setProviderLogin("johndoo")
- .setLogin("id:johndoo")
- .setName("John")
- .setEmail("john@email.com")
- .build();
-
- private ThreadLocalUserSession threadLocalUserSession = mock(ThreadLocalUserSession.class);
-
- private TestUserRegistrar userIdentityAuthenticator = new TestUserRegistrar();
- private Server server = mock(Server.class);
-
- private HttpServletRequest request = mock(HttpServletRequest.class);
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private BaseIdentityProvider identityProvider = mock(BaseIdentityProvider.class);
- private JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class);
- private TestUserSessionFactory userSessionFactory = TestUserSessionFactory.standalone();
-
- private BaseContextFactory underTest = new BaseContextFactory(userIdentityAuthenticator, server, jwtHttpHandler, threadLocalUserSession, userSessionFactory);
-
- @Before
- public void setUp() throws Exception {
- when(server.getPublicRootUrl()).thenReturn(PUBLIC_ROOT_URL);
- when(identityProvider.getName()).thenReturn("GitHub");
- when(identityProvider.getKey()).thenReturn("github");
- when(request.getSession()).thenReturn(mock(HttpSession.class));
- }
-
- @Test
- public void create_context() {
- BaseIdentityProvider.Context context = underTest.newContext(request, response, identityProvider);
-
- assertThat(context.getRequest()).isEqualTo(request);
- assertThat(context.getResponse()).isEqualTo(response);
- assertThat(context.getServerBaseURL()).isEqualTo(PUBLIC_ROOT_URL);
- }
-
- @Test
- public void authenticate() {
- BaseIdentityProvider.Context context = underTest.newContext(request, response, identityProvider);
- ArgumentCaptor<UserDto> userArgumentCaptor = ArgumentCaptor.forClass(UserDto.class);
-
- context.authenticate(USER_IDENTITY);
-
- assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- verify(threadLocalUserSession).set(any(UserSession.class));
- verify(jwtHttpHandler).generateToken(userArgumentCaptor.capture(), eq(request), eq(response));
- assertThat(userArgumentCaptor.getValue().getLogin()).isEqualTo(USER_IDENTITY.getLogin());
- assertThat(userArgumentCaptor.getValue().getExternalId()).isEqualTo(USER_IDENTITY.getProviderId());
- assertThat(userArgumentCaptor.getValue().getExternalLogin()).isEqualTo(USER_IDENTITY.getProviderLogin());
- assertThat(userArgumentCaptor.getValue().getExternalIdentityProvider()).isEqualTo("github");
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/BasicAuthenticationTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/BasicAuthenticationTest.java
deleted file mode 100644
index 493f44d964e..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/BasicAuthenticationTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Base64;
-import java.util.Optional;
-import javax.servlet.http.HttpServletRequest;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTesting;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.usertoken.UserTokenAuthentication;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.rules.ExpectedException.none;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC_TOKEN;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException;
-
-public class BasicAuthenticationTest {
-
- private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder();
-
- private static final String A_LOGIN = "login";
- private static final String A_PASSWORD = "password";
- private static final String CREDENTIALS_IN_BASE64 = toBase64(A_LOGIN + ":" + A_PASSWORD);
-
- private static final UserDto USER = UserTesting.newUserDto().setLogin(A_LOGIN);
-
- @Rule
- public ExpectedException expectedException = none();
-
- @Rule
- public DbTester db = DbTester.create(System2.INSTANCE);
-
- private DbClient dbClient = db.getDbClient();
-
- private CredentialsAuthentication credentialsAuthentication = mock(CredentialsAuthentication.class);
- private UserTokenAuthentication userTokenAuthentication = mock(UserTokenAuthentication.class);
-
- private HttpServletRequest request = mock(HttpServletRequest.class);
-
- private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
-
- private BasicAuthentication underTest = new BasicAuthentication(dbClient, credentialsAuthentication, userTokenAuthentication, authenticationEvent);
-
- @Test
- public void authenticate_from_basic_http_header() {
- when(request.getHeader("Authorization")).thenReturn("Basic " + CREDENTIALS_IN_BASE64);
- Credentials credentials = new Credentials(A_LOGIN, A_PASSWORD);
- when(credentialsAuthentication.authenticate(credentials, request, BASIC)).thenReturn(USER);
-
- underTest.authenticate(request);
-
- verify(credentialsAuthentication).authenticate(credentials, request, BASIC);
- verifyNoMoreInteractions(authenticationEvent);
- }
-
- @Test
- public void authenticate_from_basic_http_header_with_password_containing_semi_colon() {
- String password = "!ascii-only:-)@";
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64(A_LOGIN + ":" + password));
- when(credentialsAuthentication.authenticate(new Credentials(A_LOGIN, password), request, BASIC)).thenReturn(USER);
-
- underTest.authenticate(request);
-
- verify(credentialsAuthentication).authenticate(new Credentials(A_LOGIN, password), request, BASIC);
- verifyNoMoreInteractions(authenticationEvent);
- }
-
- @Test
- public void does_not_authenticate_when_no_authorization_header() {
- underTest.authenticate(request);
-
- verifyZeroInteractions(credentialsAuthentication, authenticationEvent);
- }
-
- @Test
- public void does_not_authenticate_when_authorization_header_is_not_BASIC() {
- when(request.getHeader("Authorization")).thenReturn("OTHER " + CREDENTIALS_IN_BASE64);
-
- underTest.authenticate(request);
-
- verifyZeroInteractions(credentialsAuthentication, authenticationEvent);
- }
-
- @Test
- public void fail_to_authenticate_when_no_login() {
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64(":" + A_PASSWORD));
-
- expectedException.expect(authenticationException().from(Source.local(BASIC)).withoutLogin().andNoPublicMessage());
- try {
- underTest.authenticate(request);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- @Test
- public void fail_to_authenticate_when_invalid_header() {
- when(request.getHeader("Authorization")).thenReturn("Basic Invàlid");
-
- expectedException.expect(authenticationException().from(Source.local(BASIC)).withoutLogin().andNoPublicMessage());
- expectedException.expectMessage("Invalid basic header");
- underTest.authenticate(request);
- }
-
- @Test
- public void authenticate_from_user_token() {
- UserDto user = db.users().insertUser();
- when(userTokenAuthentication.authenticate("token")).thenReturn(Optional.of(user.getUuid()));
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64("token:"));
-
- Optional<UserDto> userAuthenticated = underTest.authenticate(request);
-
- assertThat(userAuthenticated.isPresent()).isTrue();
- assertThat(userAuthenticated.get().getLogin()).isEqualTo(user.getLogin());
- verify(authenticationEvent).loginSuccess(request, user.getLogin(), Source.local(BASIC_TOKEN));
- }
-
- @Test
- public void does_not_authenticate_from_user_token_when_token_is_invalid() {
- when(userTokenAuthentication.authenticate("token")).thenReturn(Optional.empty());
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64("token:"));
-
- expectedException.expect(authenticationException().from(Source.local(BASIC_TOKEN)).withoutLogin().andNoPublicMessage());
- try {
- underTest.authenticate(request);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- @Test
- public void does_not_authenticate_from_user_token_when_token_does_not_match_existing_user() {
- when(userTokenAuthentication.authenticate("token")).thenReturn(Optional.of("Unknown user"));
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64("token:"));
-
- expectedException.expect(authenticationException().from(Source.local(Method.BASIC_TOKEN)).withoutLogin().andNoPublicMessage());
- try {
- underTest.authenticate(request);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- @Test
- public void does_not_authenticate_from_user_token_when_token_does_not_match_active_user() {
- UserDto user = db.users().insertDisabledUser();
- when(userTokenAuthentication.authenticate("token")).thenReturn(Optional.of(user.getUuid()));
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64("token:"));
-
- expectedException.expect(authenticationException().from(Source.local(Method.BASIC_TOKEN)).withoutLogin().andNoPublicMessage());
- try {
- underTest.authenticate(request);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- private static String toBase64(String text) {
- return new String(BASE64_ENCODER.encode(text.getBytes(UTF_8)));
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/CookiesTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/CookiesTest.java
deleted file mode 100644
index d7b47679da6..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/CookiesTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.authentication.Cookies.findCookie;
-import static org.sonar.server.authentication.Cookies.newCookieBuilder;
-
-public class CookiesTest {
-
- private static final String HTTPS_HEADER = "X-Forwarded-Proto";
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- private HttpServletRequest request = mock(HttpServletRequest.class);
-
- @Test
- public void create_cookie() {
- Cookie cookie = newCookieBuilder(request).setName("name").setValue("value").setHttpOnly(true).setExpiry(10).build();
- assertThat(cookie.getName()).isEqualTo("name");
- assertThat(cookie.getValue()).isEqualTo("value");
- assertThat(cookie.isHttpOnly()).isTrue();
- assertThat(cookie.getMaxAge()).isEqualTo(10);
- assertThat(cookie.getSecure()).isFalse();
- assertThat(cookie.getPath()).isEqualTo("/");
- }
-
- @Test
- public void create_cookie_without_value() {
- Cookie cookie = newCookieBuilder(request).setName("name").build();
- assertThat(cookie.getName()).isEqualTo("name");
- assertThat(cookie.getValue()).isNull();
- }
-
- @Test
- public void create_cookie_when_web_context() {
- when(request.getContextPath()).thenReturn("/sonarqube");
- Cookie cookie = newCookieBuilder(request).setName("name").setValue("value").setHttpOnly(true).setExpiry(10).build();
- assertThat(cookie.getName()).isEqualTo("name");
- assertThat(cookie.getValue()).isEqualTo("value");
- assertThat(cookie.isHttpOnly()).isTrue();
- assertThat(cookie.getMaxAge()).isEqualTo(10);
- assertThat(cookie.getSecure()).isFalse();
- assertThat(cookie.getPath()).isEqualTo("/sonarqube");
- }
-
- @Test
- public void create_not_secured_cookie_when_header_is_not_http() {
- when(request.getHeader(HTTPS_HEADER)).thenReturn("http");
- Cookie cookie = newCookieBuilder(request).setName("name").setValue("value").setHttpOnly(true).setExpiry(10).build();
- assertThat(cookie.getSecure()).isFalse();
- }
-
- @Test
- public void create_secured_cookie_when_X_Forwarded_Proto_header_is_https() {
- when(request.getHeader(HTTPS_HEADER)).thenReturn("https");
- Cookie cookie = newCookieBuilder(request).setName("name").setValue("value").setHttpOnly(true).setExpiry(10).build();
- assertThat(cookie.getSecure()).isTrue();
- }
-
- @Test
- public void create_secured_cookie_when_X_Forwarded_Proto_header_is_HTTPS() {
- when(request.getHeader(HTTPS_HEADER)).thenReturn("HTTPS");
- Cookie cookie = newCookieBuilder(request).setName("name").setValue("value").setHttpOnly(true).setExpiry(10).build();
- assertThat(cookie.getSecure()).isTrue();
- }
-
- @Test
- public void find_cookie() {
- Cookie cookie = newCookieBuilder(request).setName("name").setValue("value").build();
- when(request.getCookies()).thenReturn(new Cookie[] {cookie});
-
- assertThat(findCookie("name", request)).isPresent();
- assertThat(findCookie("NAME", request)).isEmpty();
- assertThat(findCookie("unknown", request)).isEmpty();
- }
-
- @Test
- public void does_not_fail_to_find_cookie_when_no_cookie() {
- assertThat(findCookie("unknown", request)).isEmpty();
- }
-
- @Test
- public void fail_with_NPE_when_cookie_name_is_null() {
- expectedException.expect(NullPointerException.class);
- newCookieBuilder(request).setName(null);
- }
-
- @Test
- public void fail_with_NPE_when_cookie_has_no_name() {
- expectedException.expect(NullPointerException.class);
- newCookieBuilder(request).setName(null);
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsAuthenticationTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsAuthenticationTest.java
deleted file mode 100644
index 315d5e83f1d..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsAuthenticationTest.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Optional;
-import javax.servlet.http.HttpServletRequest;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.rules.ExpectedException.none;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC_TOKEN;
-import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException;
-
-public class CredentialsAuthenticationTest {
-
- private static final String LOGIN = "LOGIN";
- private static final String PASSWORD = "PASSWORD";
- private static final String SALT = "0242b0b4c0a93ddfe09dd886de50bc25ba000b51";
- private static final String ENCRYPTED_PASSWORD = "540e4fc4be4e047db995bc76d18374a5b5db08cc";
-
- @Rule
- public ExpectedException expectedException = none();
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
- private DbClient dbClient = dbTester.getDbClient();
- private DbSession dbSession = dbTester.getSession();
- private HttpServletRequest request = mock(HttpServletRequest.class);
- private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
- private CredentialsExternalAuthentication externalAuthentication = mock(CredentialsExternalAuthentication.class);
- private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(dbClient);
- private CredentialsAuthentication underTest = new CredentialsAuthentication(dbClient, authenticationEvent, externalAuthentication, localAuthentication);
-
- @Test
- public void authenticate_local_user() {
- insertUser(newUserDto()
- .setLogin(LOGIN)
- .setCryptedPassword(ENCRYPTED_PASSWORD)
- .setHashMethod(CredentialsLocalAuthentication.HashMethod.SHA1.name())
- .setSalt(SALT)
- .setLocal(true));
-
- UserDto userDto = executeAuthenticate(BASIC);
- assertThat(userDto.getLogin()).isEqualTo(LOGIN);
- verify(authenticationEvent).loginSuccess(request, LOGIN, Source.local(BASIC));
- }
-
- @Test
- public void fail_to_authenticate_local_user_when_password_is_wrong() {
- insertUser(newUserDto()
- .setLogin(LOGIN)
- .setCryptedPassword("Wrong password")
- .setSalt("Wrong salt")
- .setHashMethod(CredentialsLocalAuthentication.HashMethod.SHA1.name())
- .setLocal(true));
-
- expectedException.expect(authenticationException().from(Source.local(BASIC)).withLogin(LOGIN).andNoPublicMessage());
- expectedException.expectMessage("wrong password");
- try {
- executeAuthenticate(BASIC);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- @Test
- public void authenticate_external_user() {
- when(externalAuthentication.authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC)).thenReturn(Optional.of(newUserDto()));
- insertUser(newUserDto()
- .setLogin(LOGIN)
- .setLocal(false));
-
- executeAuthenticate(BASIC);
-
- verify(externalAuthentication).authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC);
- verifyZeroInteractions(authenticationEvent);
- }
-
- @Test
- public void fail_to_authenticate_authenticate_external_user_when_no_external_authentication() {
- when(externalAuthentication.authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC_TOKEN)).thenReturn(Optional.empty());
- insertUser(newUserDto()
- .setLogin(LOGIN)
- .setLocal(false));
-
- expectedException.expect(authenticationException().from(Source.local(BASIC_TOKEN)).withLogin(LOGIN).andNoPublicMessage());
- expectedException.expectMessage("User is not local");
- try {
- executeAuthenticate(BASIC_TOKEN);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- @Test
- public void fail_to_authenticate_local_user_that_have_no_password() {
- insertUser(newUserDto()
- .setLogin(LOGIN)
- .setCryptedPassword(null)
- .setSalt(SALT)
- .setHashMethod(CredentialsLocalAuthentication.HashMethod.SHA1.name())
- .setLocal(true));
-
- expectedException.expect(authenticationException().from(Source.local(BASIC)).withLogin(LOGIN).andNoPublicMessage());
- expectedException.expectMessage("null password in DB");
- try {
- executeAuthenticate(BASIC);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- @Test
- public void fail_to_authenticate_local_user_that_have_no_salt() {
- insertUser(newUserDto()
- .setLogin(LOGIN)
- .setCryptedPassword(ENCRYPTED_PASSWORD)
- .setSalt(null)
- .setHashMethod(CredentialsLocalAuthentication.HashMethod.SHA1.name())
- .setLocal(true));
-
- expectedException.expect(authenticationException().from(Source.local(BASIC_TOKEN)).withLogin(LOGIN).andNoPublicMessage());
- expectedException.expectMessage("null salt");
- try {
- executeAuthenticate(BASIC_TOKEN);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- private UserDto executeAuthenticate(AuthenticationEvent.Method method) {
- return underTest.authenticate(new Credentials(LOGIN, PASSWORD), request, method);
- }
-
- private UserDto insertUser(UserDto userDto) {
- dbClient.userDao().insert(dbSession, userDto);
- dbSession.commit();
- return userDto;
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsExternalAuthenticationTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsExternalAuthenticationTest.java
deleted file mode 100644
index ee90eb0d094..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsExternalAuthenticationTest.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.http.HttpServletRequest;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.security.Authenticator;
-import org.sonar.api.security.ExternalGroupsProvider;
-import org.sonar.api.security.ExternalUsersProvider;
-import org.sonar.api.security.SecurityRealm;
-import org.sonar.api.security.UserDetails;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.user.SecurityRealmFactory;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.rules.ExpectedException.none;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy.FORBID;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC_TOKEN;
-import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException;
-
-public class CredentialsExternalAuthenticationTest {
-
- private static final String LOGIN = "LOGIN";
- private static final String PASSWORD = "PASSWORD";
-
- private static final String REALM_NAME = "realm name";
-
- @Rule
- public ExpectedException expectedException = none();
-
- private MapSettings settings = new MapSettings();
-
- private SecurityRealmFactory securityRealmFactory = mock(SecurityRealmFactory.class);
- private SecurityRealm realm = mock(SecurityRealm.class);
- private Authenticator authenticator = mock(Authenticator.class);
- private ExternalUsersProvider externalUsersProvider = mock(ExternalUsersProvider.class);
- private ExternalGroupsProvider externalGroupsProvider = mock(ExternalGroupsProvider.class);
-
- private TestUserRegistrar userIdentityAuthenticator = new TestUserRegistrar();
- private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
-
- private HttpServletRequest request = mock(HttpServletRequest.class);
-
- private CredentialsExternalAuthentication underTest = new CredentialsExternalAuthentication(settings.asConfig(), securityRealmFactory, userIdentityAuthenticator, authenticationEvent);
-
- @Before
- public void setUp() throws Exception {
- when(realm.getName()).thenReturn(REALM_NAME);
- }
-
- @Test
- public void authenticate() {
- executeStartWithoutGroupSync();
- when(authenticator.doAuthenticate(any(Authenticator.Context.class))).thenReturn(true);
- UserDetails userDetails = new UserDetails();
- userDetails.setName("name");
- userDetails.setEmail("email");
- when(externalUsersProvider.doGetUserDetails(any(ExternalUsersProvider.Context.class))).thenReturn(userDetails);
-
- underTest.authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC);
-
- assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getExistingEmailStrategy()).isEqualTo(FORBID);
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getLogin()).isEqualTo(LOGIN);
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getProviderLogin()).isEqualTo(LOGIN);
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getProviderId()).isNull();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getName()).isEqualTo("name");
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getEmail()).isEqualTo("email");
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().shouldSyncGroups()).isFalse();
- verify(authenticationEvent).loginSuccess(request, LOGIN, Source.realm(BASIC, REALM_NAME));
- }
-
- @Test
- public void authenticate_with_sonarqube_identity_provider() {
- executeStartWithoutGroupSync();
- when(authenticator.doAuthenticate(any(Authenticator.Context.class))).thenReturn(true);
- UserDetails userDetails = new UserDetails();
- userDetails.setName("name");
- userDetails.setEmail("email");
- when(externalUsersProvider.doGetUserDetails(any(ExternalUsersProvider.Context.class))).thenReturn(userDetails);
-
- underTest.authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC);
-
- assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getProvider().getKey()).isEqualTo("sonarqube");
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getProvider().getName()).isEqualTo("sonarqube");
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getProvider().getDisplay()).isNull();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getProvider().isEnabled()).isTrue();
- verify(authenticationEvent).loginSuccess(request, LOGIN, Source.realm(BASIC, REALM_NAME));
- }
-
- @Test
- public void login_is_used_when_no_name_provided() {
- executeStartWithoutGroupSync();
- when(authenticator.doAuthenticate(any(Authenticator.Context.class))).thenReturn(true);
- UserDetails userDetails = new UserDetails();
- userDetails.setEmail("email");
- when(externalUsersProvider.doGetUserDetails(any(ExternalUsersProvider.Context.class))).thenReturn(userDetails);
-
- underTest.authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC);
-
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getProvider().getName()).isEqualTo("sonarqube");
- verify(authenticationEvent).loginSuccess(request, LOGIN, Source.realm(BASIC, REALM_NAME));
- }
-
- @Test
- public void authenticate_with_group_sync() {
- when(externalGroupsProvider.doGetGroups(any(ExternalGroupsProvider.Context.class))).thenReturn(asList("group1", "group2"));
- executeStartWithGroupSync();
-
- executeAuthenticate();
-
- assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().shouldSyncGroups()).isTrue();
- verify(authenticationEvent).loginSuccess(request, LOGIN, Source.realm(BASIC, REALM_NAME));
- }
-
- @Test
- public void use_login_if_user_details_contains_no_name() {
- executeStartWithoutGroupSync();
- when(authenticator.doAuthenticate(any(Authenticator.Context.class))).thenReturn(true);
- UserDetails userDetails = new UserDetails();
- userDetails.setName(null);
- when(externalUsersProvider.doGetUserDetails(any(ExternalUsersProvider.Context.class))).thenReturn(userDetails);
-
- underTest.authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC);
-
- assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getName()).isEqualTo(LOGIN);
- verify(authenticationEvent).loginSuccess(request, LOGIN, Source.realm(BASIC, REALM_NAME));
- }
-
- @Test
- public void use_downcase_login() {
- settings.setProperty("sonar.authenticator.downcase", true);
- executeStartWithoutGroupSync();
-
- executeAuthenticate("LOGIN");
-
- assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getLogin()).isEqualTo("login");
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getProviderLogin()).isEqualTo("login");
- verify(authenticationEvent).loginSuccess(request, "login", Source.realm(BASIC, REALM_NAME));
- }
-
- @Test
- public void does_not_user_downcase_login() {
- settings.setProperty("sonar.authenticator.downcase", false);
- executeStartWithoutGroupSync();
-
- executeAuthenticate("LoGiN");
-
- assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getLogin()).isEqualTo("LoGiN");
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getProviderLogin()).isEqualTo("LoGiN");
- verify(authenticationEvent).loginSuccess(request, "LoGiN", Source.realm(BASIC, REALM_NAME));
- }
-
- @Test
- public void fail_to_authenticate_when_user_details_are_null() {
- executeStartWithoutGroupSync();
- when(authenticator.doAuthenticate(any(Authenticator.Context.class))).thenReturn(true);
-
- when(externalUsersProvider.doGetUserDetails(any(ExternalUsersProvider.Context.class))).thenReturn(null);
-
- expectedException.expect(authenticationException().from(Source.realm(BASIC, REALM_NAME)).withLogin(LOGIN).andNoPublicMessage());
- expectedException.expectMessage("No user details");
- try {
- underTest.authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- @Test
- public void fail_to_authenticate_when_external_authentication_fails() {
- executeStartWithoutGroupSync();
- when(externalUsersProvider.doGetUserDetails(any(ExternalUsersProvider.Context.class))).thenReturn(new UserDetails());
-
- when(authenticator.doAuthenticate(any(Authenticator.Context.class))).thenReturn(false);
-
- expectedException.expect(authenticationException().from(Source.realm(BASIC, REALM_NAME)).withLogin(LOGIN).andNoPublicMessage());
- expectedException.expectMessage("Realm returned authenticate=false");
- try {
- underTest.authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- @Test
- public void fail_to_authenticate_when_any_exception_is_thrown() {
- executeStartWithoutGroupSync();
- String expectedMessage = "emulating exception in doAuthenticate";
- doThrow(new IllegalArgumentException(expectedMessage)).when(authenticator).doAuthenticate(any(Authenticator.Context.class));
-
- when(externalUsersProvider.doGetUserDetails(any(ExternalUsersProvider.Context.class))).thenReturn(new UserDetails());
-
- expectedException.expect(authenticationException().from(Source.realm(BASIC_TOKEN, REALM_NAME)).withLogin(LOGIN).andNoPublicMessage());
- expectedException.expectMessage(expectedMessage);
- try {
- underTest.authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC_TOKEN);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- @Test
- public void return_empty_user_when_no_realm() {
- assertThat(underTest.authenticate(new Credentials(LOGIN, PASSWORD), request, BASIC)).isEmpty();
- verifyNoMoreInteractions(authenticationEvent);
- }
-
- @Test
- public void fail_to_start_when_no_authenticator() {
- when(realm.doGetAuthenticator()).thenReturn(null);
- when(securityRealmFactory.getRealm()).thenReturn(realm);
-
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("No authenticator available");
- underTest.start();
- }
-
- @Test
- public void fail_to_start_when_no_user_provider() {
- when(realm.doGetAuthenticator()).thenReturn(authenticator);
- when(realm.getUsersProvider()).thenReturn(null);
- when(securityRealmFactory.getRealm()).thenReturn(realm);
-
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("No users provider available");
- underTest.start();
- }
-
- private void executeStartWithoutGroupSync() {
- when(realm.doGetAuthenticator()).thenReturn(authenticator);
- when(realm.getUsersProvider()).thenReturn(externalUsersProvider);
- when(securityRealmFactory.getRealm()).thenReturn(realm);
- underTest.start();
- }
-
- private void executeStartWithGroupSync() {
- when(realm.doGetAuthenticator()).thenReturn(authenticator);
- when(realm.getUsersProvider()).thenReturn(externalUsersProvider);
- when(realm.getGroupsProvider()).thenReturn(externalGroupsProvider);
- when(securityRealmFactory.getRealm()).thenReturn(realm);
- underTest.start();
- }
-
- private void executeAuthenticate() {
- executeAuthenticate(LOGIN);
- }
-
- private void executeAuthenticate(String login) {
- when(authenticator.doAuthenticate(any(Authenticator.Context.class))).thenReturn(true);
- UserDetails userDetails = new UserDetails();
- userDetails.setName("name");
- when(externalUsersProvider.doGetUserDetails(any(ExternalUsersProvider.Context.class))).thenReturn(userDetails);
- underTest.authenticate(new Credentials(login, PASSWORD), request, BASIC);
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsLocalAuthenticationTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsLocalAuthenticationTest.java
deleted file mode 100644
index 1f7078db322..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsLocalAuthenticationTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Optional;
-import java.util.Random;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mindrot.jbcrypt.BCrypt;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationException;
-
-import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.server.authentication.CredentialsLocalAuthentication.HashMethod.BCRYPT;
-import static org.sonar.server.authentication.CredentialsLocalAuthentication.HashMethod.SHA1;
-
-public class CredentialsLocalAuthenticationTest {
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- @Rule
- public DbTester db = DbTester.create();
-
- private static final Random RANDOM = new Random();
-
- private CredentialsLocalAuthentication underTest = new CredentialsLocalAuthentication(db.getDbClient());
-
- @Test
- public void incorrect_hash_should_throw_AuthenticationException() {
- UserDto user = newUserDto()
- .setHashMethod("ALGON2");
-
- expectedException.expect(AuthenticationException.class);
- expectedException.expectMessage("Unknown hash method [ALGON2]");
-
- underTest.authenticate(db.getSession(), user, "whatever", AuthenticationEvent.Method.BASIC);
- }
-
- @Test
- public void null_hash_should_throw_AuthenticationException() {
- UserDto user = newUserDto();
-
- expectedException.expect(AuthenticationException.class);
- expectedException.expectMessage("null hash method");
-
- underTest.authenticate(db.getSession(), user, "whatever", AuthenticationEvent.Method.BASIC);
- }
-
- @Test
- public void authentication_with_bcrypt_with_correct_password_should_work() {
- String password = randomAlphanumeric(60);
-
- UserDto user = newUserDto()
- .setHashMethod(BCRYPT.name())
- .setCryptedPassword(BCrypt.hashpw(password, BCrypt.gensalt(12)));
-
- underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC);
- }
-
- @Test
- public void authentication_with_sha1_with_correct_password_should_work() {
- String password = randomAlphanumeric(60);
-
- byte[] saltRandom = new byte[20];
- RANDOM.nextBytes(saltRandom);
- String salt = DigestUtils.sha1Hex(saltRandom);
-
- UserDto user = newUserDto()
- .setHashMethod(SHA1.name())
- .setCryptedPassword(DigestUtils.sha1Hex("--" + salt + "--" + password + "--"))
- .setSalt(salt);
-
- underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC);
- }
-
- @Test
- public void authentication_with_sha1_with_incorrect_password_should_throw_AuthenticationException() {
- String password = randomAlphanumeric(60);
-
- byte[] saltRandom = new byte[20];
- RANDOM.nextBytes(saltRandom);
- String salt = DigestUtils.sha1Hex(saltRandom);
-
- UserDto user = newUserDto()
- .setHashMethod(SHA1.name())
- .setCryptedPassword(DigestUtils.sha1Hex("--" + salt + "--" + password + "--"))
- .setSalt(salt);
-
- expectedException.expect(AuthenticationException.class);
- expectedException.expectMessage("wrong password");
-
- underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC);
- }
-
- @Test
- public void authentication_with_sha1_with_empty_password_should_throw_AuthenticationException() {
- byte[] saltRandom = new byte[20];
- RANDOM.nextBytes(saltRandom);
- String salt = DigestUtils.sha1Hex(saltRandom);
-
- UserDto user = newUserDto()
- .setCryptedPassword(null)
- .setHashMethod(SHA1.name())
- .setSalt(salt);
-
- expectedException.expect(AuthenticationException.class);
- expectedException.expectMessage("null password in DB");
-
- underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC);
- }
-
- @Test
- public void authentication_with_sha1_with_empty_salt_should_throw_AuthenticationException() {
- String password = randomAlphanumeric(60);
-
- UserDto user = newUserDto()
- .setHashMethod(SHA1.name())
- .setCryptedPassword(DigestUtils.sha1Hex("--0242b0b4c0a93ddfe09dd886de50bc25ba000b51--" + password + "--"))
- .setSalt(null);
-
- expectedException.expect(AuthenticationException.class);
- expectedException.expectMessage("null salt");
-
- underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC);
- }
-
- @Test
- public void authentication_with_bcrypt_with_incorrect_password_should_throw_AuthenticationException() {
- String password = randomAlphanumeric(60);
-
- UserDto user = newUserDto()
- .setHashMethod(BCRYPT.name())
- .setCryptedPassword(BCrypt.hashpw(password, BCrypt.gensalt(12)));
-
- expectedException.expect(AuthenticationException.class);
- expectedException.expectMessage("wrong password");
-
- underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC);
- }
-
- @Test
- public void authentication_upgrade_hash_function_when_SHA1_was_used() {
- String password = randomAlphanumeric(60);
-
- byte[] saltRandom = new byte[20];
- RANDOM.nextBytes(saltRandom);
- String salt = DigestUtils.sha1Hex(saltRandom);
-
- UserDto user = newUserDto()
- .setLogin("myself")
- .setHashMethod(SHA1.name())
- .setCryptedPassword(DigestUtils.sha1Hex("--" + salt + "--" + password + "--"))
- .setSalt(salt);
- db.users().insertUser(user);
-
- underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC);
-
- Optional<UserDto> myself = db.users().selectUserByLogin("myself");
- assertThat(myself).isPresent();
- assertThat(myself.get().getHashMethod()).isEqualTo(BCRYPT.name());
- assertThat(myself.get().getSalt()).isNull();
-
- // authentication must work with upgraded hash method
- underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsTest.java
deleted file mode 100644
index f767b0fa4a1..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.catchThrowable;
-
-public class CredentialsTest {
-
- @Test
- public void login_cant_be_empty() {
- Throwable thrown = catchThrowable(() -> new Credentials("", "bar"));
- assertThat(thrown)
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessage("login must not be null nor empty");
-
- thrown = catchThrowable(() -> new Credentials(null, "bar"));
- assertThat(thrown)
- .isInstanceOf(IllegalArgumentException.class)
- .hasMessage("login must not be null nor empty");
-
- Credentials underTest = new Credentials("foo", "bar");
- assertThat(underTest.getLogin()).isEqualTo("foo");
- }
-
- @Test
- public void password_cant_be_empty_string() {
- Credentials underTest = new Credentials("foo", "");
- assertThat(underTest.getPassword()).isEmpty();
-
- underTest = new Credentials("foo", null);
- assertThat(underTest.getPassword()).isEmpty();
-
- underTest = new Credentials("foo", " ");
- assertThat(underTest.getPassword()).hasValue(" ");
-
- underTest = new Credentials("foo", "bar");
- assertThat(underTest.getPassword()).hasValue("bar");
- }
-
- @Test
- public void test_equality() {
- assertThat(new Credentials("foo", "bar")).isEqualTo(new Credentials("foo", "bar"));
- assertThat(new Credentials("foo", "bar")).isNotEqualTo(new Credentials("foo", "baaaar"));
- assertThat(new Credentials("foo", "bar")).isNotEqualTo(new Credentials("foooooo", "bar"));
- assertThat(new Credentials("foo", "bar")).isNotEqualTo(new Credentials("foo", null));
-
- assertThat(new Credentials("foo", "bar").hashCode()).isEqualTo(new Credentials("foo", "bar").hashCode());
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/FakeBasicIdentityProvider.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/FakeBasicIdentityProvider.java
deleted file mode 100644
index 22e794abc93..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/FakeBasicIdentityProvider.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.sonar.api.server.authentication.BaseIdentityProvider;
-
-class FakeBasicIdentityProvider extends TestIdentityProvider implements BaseIdentityProvider {
-
- private boolean initCalled = false;
-
- public FakeBasicIdentityProvider(String key, boolean enabled) {
- setKey(key);
- setName("name of " + key);
- setEnabled(enabled);
- }
-
- @Override
- public void init(Context context) {
- initCalled = true;
- }
-
- public boolean isInitCalled() {
- return initCalled;
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/FakeOAuth2IdentityProvider.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/FakeOAuth2IdentityProvider.java
deleted file mode 100644
index ae50241c89a..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/FakeOAuth2IdentityProvider.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-
-class FakeOAuth2IdentityProvider extends TestIdentityProvider implements OAuth2IdentityProvider {
-
- private boolean initCalled = false;
- private boolean callbackCalled = false;
-
- public FakeOAuth2IdentityProvider(String key, boolean enabled) {
- setKey(key);
- setName("name of " + key);
- setEnabled(enabled);
- }
-
- @Override
- public void init(InitContext context) {
- initCalled = true;
- }
-
- @Override
- public void callback(CallbackContext context) {
- callbackCalled = true;
- }
-
- public boolean isInitCalled() {
- return initCalled;
- }
-
- public boolean isCallbackCalled() {
- return callbackCalled;
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java
deleted file mode 100644
index 0a1672b9dcc..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.collect.ImmutableMap;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.organization.OrganizationUpdater;
-import org.sonar.server.organization.TestDefaultOrganizationProvider;
-import org.sonar.server.organization.TestOrganizationFlags;
-import org.sonar.server.user.NewUserNotifier;
-import org.sonar.server.user.UserUpdater;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static java.util.Arrays.stream;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.rules.ExpectedException.none;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyMap;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException;
-
-public class HttpHeadersAuthenticationTest {
-
- private MapSettings settings = new MapSettings();
-
- @Rule
- public ExpectedException expectedException = none();
- @Rule
- public DbTester db = DbTester.create(new AlwaysIncreasingSystem2());
- @Rule
- public EsTester es = EsTester.create();
-
- private static final String DEFAULT_LOGIN = "john";
- private static final String DEFAULT_NAME = "John";
- private static final String DEFAULT_EMAIL = "john@doo.com";
- private static final String GROUP1 = "dev";
- private static final String GROUP2 = "admin";
- private static final String GROUPS = GROUP1 + "," + GROUP2;
-
- private static final Long NOW = 1_000_000L;
- private static final Long CLOSE_REFRESH_TIME = NOW - 1_000L;
-
- private static final UserDto DEFAULT_USER = newUserDto()
- .setLogin(DEFAULT_LOGIN)
- .setName(DEFAULT_NAME)
- .setEmail(DEFAULT_EMAIL)
- .setExternalLogin(DEFAULT_LOGIN)
- .setExternalIdentityProvider("sonarqube");
-
- private GroupDto group1;
- private GroupDto group2;
- private GroupDto sonarUsers;
-
- private System2 system2 = mock(System2.class);
- private OrganizationUpdater organizationUpdater = mock(OrganizationUpdater.class);
- private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
- private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient());
-
- private UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client());
- private UserRegistrarImpl userIdentityAuthenticator = new UserRegistrarImpl(
- db.getDbClient(),
- new UserUpdater(system2, mock(NewUserNotifier.class), db.getDbClient(), userIndexer, organizationFlags, defaultOrganizationProvider,
- new DefaultGroupFinder(db.getDbClient()), settings.asConfig(), localAuthentication),
- defaultOrganizationProvider, organizationFlags, new DefaultGroupFinder(db.getDbClient()), null);
-
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class);
- private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
-
- private HttpHeadersAuthentication underTest = new HttpHeadersAuthentication(system2, settings.asConfig(), userIdentityAuthenticator, jwtHttpHandler, authenticationEvent);
-
- @Before
- public void setUp() throws Exception {
- when(system2.now()).thenReturn(NOW);
- group1 = db.users().insertGroup(db.getDefaultOrganization(), GROUP1);
- group2 = db.users().insertGroup(db.getDefaultOrganization(), GROUP2);
- sonarUsers = db.users().insertDefaultGroup(db.getDefaultOrganization(), "sonar-users");
- }
-
- @Test
- public void create_user_when_authenticating_new_user() {
- startWithSso();
- setNotUserInToken();
- HttpServletRequest request = createRequest(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, GROUPS);
-
- underTest.authenticate(request, response);
-
- verifyUserInDb(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, group1, group2, sonarUsers);
- verifyTokenIsUpdated(NOW);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void use_login_when_name_is_not_provided() {
- startWithSso();
- setNotUserInToken();
-
- HttpServletRequest request = createRequest(DEFAULT_LOGIN, null, null, null);
- underTest.authenticate(request, response);
-
- verifyUserInDb(DEFAULT_LOGIN, DEFAULT_LOGIN, null, sonarUsers);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void update_user_when_authenticating_exiting_user() {
- startWithSso();
- setNotUserInToken();
- insertUser(newUserDto().setLogin(DEFAULT_LOGIN).setName("old name").setEmail("old email"), group1);
- // Name, email and groups are different
- HttpServletRequest request = createRequest(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, GROUP2);
-
- underTest.authenticate(request, response);
-
- verifyUserInDb(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, group2);
- verifyTokenIsUpdated(NOW);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void remove_groups_when_group_headers_is_empty() {
- startWithSso();
- setNotUserInToken();
- insertUser(DEFAULT_USER, group1);
- HttpServletRequest request = createRequest(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, "");
-
- underTest.authenticate(request, response);
-
- verityUserHasNoGroup(DEFAULT_LOGIN);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void remove_groups_when_group_headers_is_null() {
- startWithSso();
- setNotUserInToken();
- insertUser(DEFAULT_USER, group1);
- Map<String, String> headerValuesByName = new HashMap<>();
- headerValuesByName.put("X-Forwarded-Login", DEFAULT_LOGIN);
- headerValuesByName.put("X-Forwarded-Groups", null);
- HttpServletRequest request = createRequest(headerValuesByName);
-
- underTest.authenticate(request, response);
-
- verityUserHasNoGroup(DEFAULT_LOGIN);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void does_not_update_groups_when_no_group_headers() {
- startWithSso();
- setNotUserInToken();
- insertUser(DEFAULT_USER, group1, sonarUsers);
- HttpServletRequest request = createRequest(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, null);
-
- underTest.authenticate(request, response);
-
- verityUserGroups(DEFAULT_LOGIN, group1, sonarUsers);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void does_not_update_user_when_user_is_in_token_and_refresh_time_is_close() {
- startWithSso();
- UserDto user = insertUser(DEFAULT_USER, group1);
- setUserInToken(user, CLOSE_REFRESH_TIME);
- HttpServletRequest request = createRequest(DEFAULT_LOGIN, "new name", "new email", GROUP2);
-
- underTest.authenticate(request, response);
-
- // User is not updated
- verifyUserInDb(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, group1);
- verifyTokenIsNotUpdated();
- verifyZeroInteractions(authenticationEvent);
- }
-
- @Test
- public void update_user_when_user_in_token_but_refresh_time_is_old() {
- startWithSso();
- UserDto user = insertUser(DEFAULT_USER, group1);
- // Refresh time was updated 6 minutes ago => more than 5 minutes
- setUserInToken(user, NOW - 6 * 60 * 1000L);
- HttpServletRequest request = createRequest(DEFAULT_LOGIN, "new name", "new email", GROUP2);
-
- underTest.authenticate(request, response);
-
- // User is updated
- verifyUserInDb(DEFAULT_LOGIN, "new name", "new email", group2);
- verifyTokenIsUpdated(NOW);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void update_user_when_user_in_token_but_no_refresh_time() {
- startWithSso();
- UserDto user = insertUser(DEFAULT_USER, group1);
- setUserInToken(user, null);
- HttpServletRequest request = createRequest(DEFAULT_LOGIN, "new name", "new email", GROUP2);
-
- underTest.authenticate(request, response);
-
- // User is updated
- verifyUserInDb(DEFAULT_LOGIN, "new name", "new email", group2);
- verifyTokenIsUpdated(NOW);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void use_refresh_time_from_settings() {
- settings.setProperty("sonar.web.sso.refreshIntervalInMinutes", "10");
- startWithSso();
- UserDto user = insertUser(DEFAULT_USER, group1);
- // Refresh time was updated 6 minutes ago => less than 10 minutes ago so not updated
- setUserInToken(user, NOW - 6 * 60 * 1000L);
- HttpServletRequest request = createRequest(DEFAULT_LOGIN, "new name", "new email", GROUP2);
-
- underTest.authenticate(request, response);
-
- // User is not updated
- verifyUserInDb(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, group1);
- verifyTokenIsNotUpdated();
- verifyZeroInteractions(authenticationEvent);
- }
-
- @Test
- public void update_user_when_login_from_token_is_different_than_login_from_request() {
- startWithSso();
- insertUser(DEFAULT_USER, group1);
- setUserInToken(DEFAULT_USER, CLOSE_REFRESH_TIME);
- HttpServletRequest request = createRequest("AnotherLogin", "Another name", "Another email", GROUP2);
-
- underTest.authenticate(request, response);
-
- verifyUserInDb("AnotherLogin", "Another name", "Another email", group2, sonarUsers);
- verifyTokenIsUpdated(NOW);
- verify(authenticationEvent).loginSuccess(request, "AnotherLogin", Source.sso());
- }
-
- @Test
- public void use_headers_from_settings() {
- settings.setProperty("sonar.web.sso.loginHeader", "head-login");
- settings.setProperty("sonar.web.sso.nameHeader", "head-name");
- settings.setProperty("sonar.web.sso.emailHeader", "head-email");
- settings.setProperty("sonar.web.sso.groupsHeader", "head-groups");
- startWithSso();
- setNotUserInToken();
- HttpServletRequest request = createRequest(ImmutableMap.of("head-login", DEFAULT_LOGIN, "head-name", DEFAULT_NAME, "head-email", DEFAULT_EMAIL, "head-groups", GROUPS));
-
- underTest.authenticate(request, response);
-
- verifyUserInDb(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, group1, group2, sonarUsers);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void detect_group_header_even_with_wrong_case() {
- settings.setProperty("sonar.web.sso.loginHeader", "login");
- settings.setProperty("sonar.web.sso.nameHeader", "name");
- settings.setProperty("sonar.web.sso.emailHeader", "email");
- settings.setProperty("sonar.web.sso.groupsHeader", "Groups");
- startWithSso();
- setNotUserInToken();
- HttpServletRequest request = createRequest(ImmutableMap.of("login", DEFAULT_LOGIN, "name", DEFAULT_NAME, "email", DEFAULT_EMAIL, "groups", GROUPS));
-
- underTest.authenticate(request, response);
-
- verifyUserInDb(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, group1, group2, sonarUsers);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void trim_groups() {
- startWithSso();
- setNotUserInToken();
- HttpServletRequest request = createRequest(DEFAULT_LOGIN, null, null, " dev , admin ");
-
- underTest.authenticate(request, response);
-
- verifyUserInDb(DEFAULT_LOGIN, DEFAULT_LOGIN, null, group1, group2, sonarUsers);
- verify(authenticationEvent).loginSuccess(request, DEFAULT_LOGIN, Source.sso());
- }
-
- @Test
- public void does_not_authenticate_when_no_header() {
- startWithSso();
- setNotUserInToken();
-
- underTest.authenticate(createRequest(Collections.emptyMap()), response);
-
- verifyUserNotAuthenticated();
- verifyTokenIsNotUpdated();
- verifyZeroInteractions(authenticationEvent);
- }
-
- @Test
- public void does_not_authenticate_when_not_enabled() {
- startWithoutSso();
-
- underTest.authenticate(createRequest(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, GROUPS), response);
-
- verifyUserNotAuthenticated();
- verifyZeroInteractions(jwtHttpHandler, authenticationEvent);
- }
-
- @Test
- public void throw_AuthenticationException_when_BadRequestException_is_generated() {
- startWithSso();
- setNotUserInToken();
-
- expectedException.expect(authenticationException().from(Source.sso()).withoutLogin().andNoPublicMessage());
- expectedException.expectMessage("Use only letters, numbers, and .-_@ please.");
- try {
- underTest.authenticate(createRequest("invalid login", DEFAULT_NAME, DEFAULT_EMAIL, GROUPS), response);
- } finally {
- verifyZeroInteractions(authenticationEvent);
- }
- }
-
- private void startWithSso() {
- settings.setProperty("sonar.web.sso.enable", true);
- underTest.start();
- }
-
- private void startWithoutSso() {
- settings.setProperty("sonar.web.sso.enable", false);
- underTest.start();
- }
-
- private void setUserInToken(UserDto user, @Nullable Long lastRefreshTime) {
- when(jwtHttpHandler.getToken(any(HttpServletRequest.class), any(HttpServletResponse.class)))
- .thenReturn(Optional.of(new JwtHttpHandler.Token(
- user,
- lastRefreshTime == null ? Collections.emptyMap() : ImmutableMap.of("ssoLastRefreshTime", lastRefreshTime))));
- }
-
- private void setNotUserInToken() {
- when(jwtHttpHandler.getToken(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(Optional.empty());
- }
-
- private UserDto insertUser(UserDto user, GroupDto... groups) {
- db.users().insertUser(user);
- stream(groups).forEach(group -> db.users().insertMember(group, user));
- db.commit();
- return user;
- }
-
- private static HttpServletRequest createRequest(Map<String, String> headerValuesByName) {
- HttpServletRequest request = mock(HttpServletRequest.class);
- setHeaders(request, headerValuesByName);
- return request;
- }
-
- private static HttpServletRequest createRequest(String login, @Nullable String name, @Nullable String email, @Nullable String groups) {
- Map<String, String> headerValuesByName = new HashMap<>();
- headerValuesByName.put("X-Forwarded-Login", login);
- if (name != null) {
- headerValuesByName.put("X-Forwarded-Name", name);
- }
- if (email != null) {
- headerValuesByName.put("X-Forwarded-Email", email);
- }
- if (groups != null) {
- headerValuesByName.put("X-Forwarded-Groups", groups);
- }
- HttpServletRequest request = mock(HttpServletRequest.class);
- setHeaders(request, headerValuesByName);
- return request;
- }
-
- private static void setHeaders(HttpServletRequest request, Map<String, String> valuesByName) {
- valuesByName.entrySet().forEach(entry -> when(request.getHeader(entry.getKey())).thenReturn(entry.getValue()));
- when(request.getHeaderNames()).thenReturn(Collections.enumeration(valuesByName.keySet()));
- }
-
- private void verifyUserInDb(String expectedLogin, String expectedName, @Nullable String expectedEmail, GroupDto... expectedGroups) {
- UserDto userDto = db.users().selectUserByLogin(expectedLogin).get();
- assertThat(userDto.isActive()).isTrue();
- assertThat(userDto.getName()).isEqualTo(expectedName);
- assertThat(userDto.getEmail()).isEqualTo(expectedEmail);
- assertThat(userDto.getExternalLogin()).isEqualTo(expectedLogin);
- assertThat(userDto.getExternalIdentityProvider()).isEqualTo("sonarqube");
- verityUserGroups(expectedLogin, expectedGroups);
- }
-
- private void verityUserGroups(String login, GroupDto... expectedGroups) {
- UserDto userDto = db.users().selectUserByLogin(login).get();
- if (expectedGroups.length == 0) {
- assertThat(db.users().selectGroupIdsOfUser(userDto)).isEmpty();
- } else {
- assertThat(db.users().selectGroupIdsOfUser(userDto)).containsOnly(stream(expectedGroups).map(GroupDto::getId).collect(MoreCollectors.toList()).toArray(new Integer[] {}));
- }
- }
-
- private void verityUserHasNoGroup(String login) {
- verityUserGroups(login);
- }
-
- private void verifyUserNotAuthenticated() {
- assertThat(db.countRowsOfTable(db.getSession(), "users")).isZero();
- verifyTokenIsNotUpdated();
- }
-
- private void verifyTokenIsUpdated(long refreshTime) {
- verify(jwtHttpHandler).generateToken(any(UserDto.class), eq(ImmutableMap.of("ssoLastRefreshTime", refreshTime)), any(HttpServletRequest.class), any(HttpServletResponse.class));
- }
-
- private void verifyTokenIsNotUpdated() {
- verify(jwtHttpHandler, never()).generateToken(any(UserDto.class), anyMap(), any(HttpServletRequest.class), any(HttpServletResponse.class));
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/IdentityProviderRepositoryRule.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/IdentityProviderRepositoryRule.java
deleted file mode 100644
index 533c90934b3..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/IdentityProviderRepositoryRule.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-import org.sonar.api.server.authentication.IdentityProvider;
-
-public class IdentityProviderRepositoryRule extends IdentityProviderRepository implements TestRule {
-
- public IdentityProviderRepositoryRule addIdentityProvider(IdentityProvider identityProvider) {
- providersByKey.put(identityProvider.getKey(), identityProvider);
- return this;
- }
-
- @Override
- public Statement apply(final Statement statement, Description description) {
- return new Statement() {
- @Override
- public void evaluate() throws Throwable {
- try {
- statement.evaluate();
- } finally {
- providersByKey.clear();
- }
- }
- };
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/IdentityProviderRepositoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/IdentityProviderRepositoryTest.java
deleted file mode 100644
index 306ab69b70a..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/IdentityProviderRepositoryTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.List;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.server.authentication.IdentityProvider;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class IdentityProviderRepositoryTest {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- static IdentityProvider GITHUB = new TestIdentityProvider()
- .setKey("github")
- .setName("Github")
- .setEnabled(true);
-
- static IdentityProvider BITBUCKET = new TestIdentityProvider()
- .setKey("bitbucket")
- .setName("Bitbucket")
- .setEnabled(true);
-
- static IdentityProvider DISABLED = new TestIdentityProvider()
- .setKey("disabled")
- .setName("Disabled")
- .setEnabled(false);
-
- @Test
- public void return_enabled_provider() {
- IdentityProviderRepository underTest = new IdentityProviderRepository(asList(GITHUB, BITBUCKET, DISABLED));
-
- assertThat(underTest.getEnabledByKey(GITHUB.getKey())).isEqualTo(GITHUB);
- assertThat(underTest.getEnabledByKey(BITBUCKET.getKey())).isEqualTo(BITBUCKET);
- }
-
- @Test
- public void fail_on_disabled_provider() {
- IdentityProviderRepository underTest = new IdentityProviderRepository(asList(GITHUB, BITBUCKET, DISABLED));
-
- thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Identity provider disabled does not exist or is not enabled");
- underTest.getEnabledByKey(DISABLED.getKey());
- }
-
- @Test
- public void return_all_enabled_providers() {
- IdentityProviderRepository underTest = new IdentityProviderRepository(asList(GITHUB, BITBUCKET, DISABLED));
-
- List<IdentityProvider> providers = underTest.getAllEnabledAndSorted();
- assertThat(providers).containsOnly(GITHUB, BITBUCKET);
- }
-
- @Test
- public void return_sorted_enabled_providers() {
- IdentityProviderRepository underTest = new IdentityProviderRepository(asList(GITHUB, BITBUCKET));
-
- List<IdentityProvider> providers = underTest.getAllEnabledAndSorted();
- assertThat(providers).containsExactly(BITBUCKET, GITHUB);
- }
-
- @Test
- public void return_nothing_when_no_identity_provider() {
- IdentityProviderRepository underTest = new IdentityProviderRepository();
-
- assertThat(underTest.getAllEnabledAndSorted()).isEmpty();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/InitFilterTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/InitFilterTest.java
deleted file mode 100644
index c23bb1ed59a..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/InitFilterTest.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.FilterChain;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.server.authentication.BaseIdentityProvider;
-import org.sonar.api.server.authentication.Display;
-import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.api.server.authentication.UnauthorizedException;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.authentication.exception.EmailAlreadyExistsRedirectionException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.user.UserTesting.newUserDto;
-
-public class InitFilterTest {
-
- private static final String OAUTH2_PROVIDER_KEY = "github";
- private static final String BASIC_PROVIDER_KEY = "openid";
-
- @Rule
- public LogTester logTester = new LogTester();
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
- @Rule
- public IdentityProviderRepositoryRule identityProviderRepository = new IdentityProviderRepositoryRule();
-
- private BaseContextFactory baseContextFactory = mock(BaseContextFactory.class);
- private OAuth2ContextFactory oAuth2ContextFactory = mock(OAuth2ContextFactory.class);
-
- private HttpServletRequest request = mock(HttpServletRequest.class);
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private FilterChain chain = mock(FilterChain.class);
-
- private FakeOAuth2IdentityProvider oAuth2IdentityProvider = new FakeOAuth2IdentityProvider(OAUTH2_PROVIDER_KEY, true);
- private OAuth2IdentityProvider.InitContext oauth2Context = mock(OAuth2IdentityProvider.InitContext.class);
-
- private FakeBasicIdentityProvider baseIdentityProvider = new FakeBasicIdentityProvider(BASIC_PROVIDER_KEY, true);
- private BaseIdentityProvider.Context baseContext = mock(BaseIdentityProvider.Context.class);
- private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
- private OAuth2AuthenticationParameters auth2AuthenticationParameters = mock(OAuth2AuthenticationParameters.class);
-
- private ArgumentCaptor<AuthenticationException> authenticationExceptionCaptor = ArgumentCaptor.forClass(AuthenticationException.class);
- private ArgumentCaptor<Cookie> cookieArgumentCaptor = ArgumentCaptor.forClass(Cookie.class);
-
- private InitFilter underTest = new InitFilter(identityProviderRepository, baseContextFactory, oAuth2ContextFactory, authenticationEvent, auth2AuthenticationParameters);
-
- @Before
- public void setUp() throws Exception {
- when(oAuth2ContextFactory.newContext(request, response, oAuth2IdentityProvider)).thenReturn(oauth2Context);
- when(baseContextFactory.newContext(request, response, baseIdentityProvider)).thenReturn(baseContext);
- when(request.getContextPath()).thenReturn("");
- }
-
- @Test
- public void do_get_pattern() {
- assertThat(underTest.doGetPattern()).isNotNull();
- }
-
- @Test
- public void do_filter_with_context() {
- when(request.getContextPath()).thenReturn("/sonarqube");
- when(request.getRequestURI()).thenReturn("/sonarqube/sessions/init/" + OAUTH2_PROVIDER_KEY);
- identityProviderRepository.addIdentityProvider(oAuth2IdentityProvider);
-
- underTest.doFilter(request, response, chain);
-
- assertOAuth2InitCalled();
- verifyZeroInteractions(authenticationEvent);
- }
-
- @Test
- public void do_filter_on_auth2_identity_provider() {
- when(request.getRequestURI()).thenReturn("/sessions/init/" + OAUTH2_PROVIDER_KEY);
- identityProviderRepository.addIdentityProvider(oAuth2IdentityProvider);
-
- underTest.doFilter(request, response, chain);
-
- assertOAuth2InitCalled();
- verifyZeroInteractions(authenticationEvent);
- }
-
- @Test
- public void do_filter_on_basic_identity_provider() {
- when(request.getRequestURI()).thenReturn("/sessions/init/" + BASIC_PROVIDER_KEY);
- identityProviderRepository.addIdentityProvider(baseIdentityProvider);
-
- underTest.doFilter(request, response, chain);
-
- assertBasicInitCalled();
- verifyZeroInteractions(authenticationEvent);
- }
-
- @Test
- public void init_authentication_parameter_on_auth2_identity_provider() {
- when(request.getContextPath()).thenReturn("/sonarqube");
- when(request.getRequestURI()).thenReturn("/sonarqube/sessions/init/" + OAUTH2_PROVIDER_KEY);
- identityProviderRepository.addIdentityProvider(oAuth2IdentityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(auth2AuthenticationParameters).init(eq(request), eq(response));
- }
-
- @Test
- public void does_not_init_authentication_parameter_on_basic_authentication() {
- when(request.getRequestURI()).thenReturn("/sessions/init/" + BASIC_PROVIDER_KEY);
- identityProviderRepository.addIdentityProvider(baseIdentityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(auth2AuthenticationParameters, never()).init(eq(request), eq(response));
- }
-
- @Test
- public void fail_if_identity_provider_key_is_empty() throws Exception {
- when(request.getRequestURI()).thenReturn("/sessions/init/");
-
- underTest.doFilter(request, response, chain);
-
- assertError("No provider key found in URI");
- verifyZeroInteractions(authenticationEvent);
- verifyZeroInteractions(auth2AuthenticationParameters);
- }
-
- @Test
- public void fail_if_uri_does_not_contains_callback() throws Exception {
- when(request.getRequestURI()).thenReturn("/sessions/init");
-
- underTest.doFilter(request, response, chain);
-
- assertError("No provider key found in URI");
- verifyZeroInteractions(authenticationEvent);
- verifyZeroInteractions(auth2AuthenticationParameters);
- }
-
- @Test
- public void fail_if_identity_provider_class_is_unsupported() throws Exception {
- String unsupportedKey = "unsupported";
- when(request.getRequestURI()).thenReturn("/sessions/init/" + unsupportedKey);
- IdentityProvider identityProvider = new UnsupportedIdentityProvider(unsupportedKey);
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- assertError("Unsupported IdentityProvider class: class org.sonar.server.authentication.InitFilterTest$UnsupportedIdentityProvider");
- verifyZeroInteractions(authenticationEvent);
- verifyZeroInteractions(auth2AuthenticationParameters);
- }
-
- @Test
- public void redirect_contains_cookie_with_error_message_when_failing_because_of_UnauthorizedExceptionException() throws Exception {
- IdentityProvider identityProvider = new FailWithUnauthorizedExceptionIdProvider("failing");
- when(request.getRequestURI()).thenReturn("/sessions/init/" + identityProvider.getKey());
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(response).sendRedirect("/sessions/unauthorized");
- verify(authenticationEvent).loginFailure(eq(request), authenticationExceptionCaptor.capture());
- AuthenticationException authenticationException = authenticationExceptionCaptor.getValue();
- assertThat(authenticationException).hasMessage("Email john@email.com is already used");
- assertThat(authenticationException.getSource()).isEqualTo(AuthenticationEvent.Source.external(identityProvider));
- assertThat(authenticationException.getLogin()).isNull();
- assertThat(authenticationException.getPublicMessage()).isEqualTo("Email john@email.com is already used");
- verifyDeleteAuthCookie();
-
- verify(response).addCookie(cookieArgumentCaptor.capture());
- Cookie cookie = cookieArgumentCaptor.getValue();
- assertThat(cookie.getName()).isEqualTo("AUTHENTICATION-ERROR");
- assertThat(cookie.getValue()).isEqualTo("Email%20john%40email.com%20is%20already%20used");
- assertThat(cookie.getPath()).isEqualTo("/");
- assertThat(cookie.isHttpOnly()).isFalse();
- assertThat(cookie.getMaxAge()).isEqualTo(300);
- assertThat(cookie.getSecure()).isFalse();
- }
-
- @Test
- public void redirect_with_context_path_when_failing_because_of_UnauthorizedException() throws Exception {
- when(request.getContextPath()).thenReturn("/sonarqube");
- IdentityProvider identityProvider = new FailWithUnauthorizedExceptionIdProvider("failing");
- when(request.getRequestURI()).thenReturn("/sonarqube/sessions/init/" + identityProvider.getKey());
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(response).sendRedirect("/sonarqube/sessions/unauthorized");
- }
-
- @Test
- public void redirect_contains_cookie_when_failing_because_of_EmailAlreadyExistException() throws Exception {
- UserDto existingUser = newUserDto().setEmail("john@email.com").setExternalLogin("john.bitbucket").setExternalIdentityProvider("bitbucket");
- FailWithEmailAlreadyExistException identityProvider = new FailWithEmailAlreadyExistException("failing", existingUser);
- when(request.getRequestURI()).thenReturn("/sessions/init/" + identityProvider.getKey());
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(response).sendRedirect("/sessions/email_already_exists");
- verify(auth2AuthenticationParameters).delete(eq(request), eq(response));
- verify(response).addCookie(cookieArgumentCaptor.capture());
- Cookie cookie = cookieArgumentCaptor.getValue();
- assertThat(cookie.getName()).isEqualTo("AUTHENTICATION-ERROR");
- assertThat(cookie.getValue()).contains("john%40email.com");
- assertThat(cookie.getPath()).isEqualTo("/");
- assertThat(cookie.isHttpOnly()).isFalse();
- assertThat(cookie.getMaxAge()).isEqualTo(300);
- assertThat(cookie.getSecure()).isFalse();
- }
-
- @Test
- public void redirect_when_failing_because_of_Exception() throws Exception {
- IdentityProvider identityProvider = new FailWithIllegalStateException("failing");
- when(request.getRequestURI()).thenReturn("/sessions/init/" + identityProvider.getKey());
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(response).sendRedirect("/sessions/unauthorized");
- assertThat(logTester.logs(LoggerLevel.WARN)).containsExactlyInAnyOrder("Fail to initialize authentication with provider 'failing'");
- verifyDeleteAuthCookie();
- }
-
- @Test
- public void redirect_with_context_when_failing_because_of_Exception() throws Exception {
- when(request.getContextPath()).thenReturn("/sonarqube");
- IdentityProvider identityProvider = new FailWithIllegalStateException("failing");
- when(request.getRequestURI()).thenReturn("/sessions/init/" + identityProvider.getKey());
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(response).sendRedirect("/sonarqube/sessions/unauthorized");
- }
-
- private void assertOAuth2InitCalled() {
- assertThat(logTester.logs(LoggerLevel.ERROR)).isEmpty();
- assertThat(oAuth2IdentityProvider.isInitCalled()).isTrue();
- }
-
- private void assertBasicInitCalled() {
- assertThat(logTester.logs(LoggerLevel.ERROR)).isEmpty();
- assertThat(baseIdentityProvider.isInitCalled()).isTrue();
- }
-
- private void assertError(String expectedError) throws Exception {
- assertThat(logTester.logs(LoggerLevel.WARN)).contains(expectedError);
- verify(response).sendRedirect("/sessions/unauthorized");
- assertThat(oAuth2IdentityProvider.isInitCalled()).isFalse();
- }
-
- private void verifyDeleteAuthCookie() {
- verify(auth2AuthenticationParameters).delete(eq(request), eq(response));
- }
-
- private static class FailWithUnauthorizedExceptionIdProvider extends FakeBasicIdentityProvider {
-
- public FailWithUnauthorizedExceptionIdProvider(String key) {
- super(key, true);
- }
-
- @Override
- public void init(Context context) {
- throw new UnauthorizedException("Email john@email.com is already used");
- }
- }
-
- private static class FailWithIllegalStateException extends FakeBasicIdentityProvider {
-
- public FailWithIllegalStateException(String key) {
- super(key, true);
- }
-
- @Override
- public void init(Context context) {
- throw new IllegalStateException("Failure !");
- }
- }
-
- private static class FailWithEmailAlreadyExistException extends FakeBasicIdentityProvider {
-
- private final UserDto existingUser;
-
- public FailWithEmailAlreadyExistException(String key, UserDto existingUser) {
- super(key, true);
- this.existingUser = existingUser;
- }
-
- @Override
- public void init(Context context) {
- throw new EmailAlreadyExistsRedirectionException(existingUser.getEmail(), existingUser, UserIdentity.builder()
- .setProviderLogin("john.github")
- .setLogin("john.github")
- .setName(existingUser.getName())
- .setEmail(existingUser.getEmail())
- .build(), this);
- }
- }
-
- private static class UnsupportedIdentityProvider implements IdentityProvider {
- private final String unsupportedKey;
-
- public UnsupportedIdentityProvider(String unsupportedKey) {
- this.unsupportedKey = unsupportedKey;
- }
-
- @Override
- public String getKey() {
- return unsupportedKey;
- }
-
- @Override
- public String getName() {
- return null;
- }
-
- @Override
- public Display getDisplay() {
- return null;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
-
- @Override
- public boolean allowsUsersToSignUp() {
- return false;
- }
-
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/JwtCsrfVerifierTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/JwtCsrfVerifierTest.java
deleted file mode 100644
index cdf97bc3b59..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/JwtCsrfVerifierTest.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException;
-
-public class JwtCsrfVerifierTest {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private static final int TIMEOUT = 30;
- private static final String CSRF_STATE = "STATE";
- private static final String JAVA_WS_URL = "/api/metrics/create";
- private static final String LOGIN = "foo login";
-
- private ArgumentCaptor<Cookie> cookieArgumentCaptor = ArgumentCaptor.forClass(Cookie.class);
-
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private HttpServletRequest request = mock(HttpServletRequest.class);
-
- private JwtCsrfVerifier underTest = new JwtCsrfVerifier();
-
- @Before
- public void setUp() throws Exception {
- when(request.getContextPath()).thenReturn("");
- }
-
- @Test
- public void generate_state() {
- String state = underTest.generateState(request, response, TIMEOUT);
- assertThat(state).isNotEmpty();
-
- verify(response).addCookie(cookieArgumentCaptor.capture());
- verifyCookie(cookieArgumentCaptor.getValue());
- }
-
- @Test
- public void verify_state() {
- mockRequestCsrf(CSRF_STATE);
- mockPostJavaWsRequest();
-
- underTest.verifyState(request, CSRF_STATE, LOGIN);
- }
-
- @Test
- public void fail_with_AuthenticationException_when_state_header_is_not_the_same_as_state_parameter() {
- mockRequestCsrf("other value");
- mockPostJavaWsRequest();
-
- thrown.expect(authenticationException().from(Source.local(Method.JWT)).withLogin(LOGIN).andNoPublicMessage());
- thrown.expectMessage("Wrong CSFR in request");
- underTest.verifyState(request, CSRF_STATE, LOGIN);
- }
-
- @Test
- public void fail_with_AuthenticationException_when_state_is_null() {
- mockRequestCsrf(CSRF_STATE);
- mockPostJavaWsRequest();
-
- thrown.expect(authenticationException().from(Source.local(Method.JWT)).withLogin(LOGIN).andNoPublicMessage());
- thrown.expectMessage("Missing reference CSRF value");
- underTest.verifyState(request, null, LOGIN);
- }
-
- @Test
- public void fail_with_AuthenticationException_when_state_parameter_is_empty() {
- mockRequestCsrf(CSRF_STATE);
- mockPostJavaWsRequest();
-
- thrown.expect(authenticationException().from(Source.local(Method.JWT)).withLogin(LOGIN).andNoPublicMessage());
- thrown.expectMessage("Missing reference CSRF value");
- underTest.verifyState(request, "", LOGIN);
- }
-
- @Test
- public void verify_POST_request() {
- mockRequestCsrf("other value");
- when(request.getRequestURI()).thenReturn(JAVA_WS_URL);
- when(request.getMethod()).thenReturn("POST");
-
- thrown.expect(authenticationException().from(Source.local(Method.JWT)).withLogin(LOGIN).andNoPublicMessage());
- thrown.expectMessage("Wrong CSFR in request");
- underTest.verifyState(request, CSRF_STATE, LOGIN);
- }
-
- @Test
- public void verify_PUT_request() {
- mockRequestCsrf("other value");
- when(request.getRequestURI()).thenReturn(JAVA_WS_URL);
- when(request.getMethod()).thenReturn("PUT");
-
- thrown.expect(authenticationException().from(Source.local(Method.JWT)).withLogin(LOGIN).andNoPublicMessage());
- thrown.expectMessage("Wrong CSFR in request");
- underTest.verifyState(request, CSRF_STATE, LOGIN);
- }
-
- @Test
- public void verify_DELETE_request() {
- mockRequestCsrf("other value");
- when(request.getRequestURI()).thenReturn(JAVA_WS_URL);
- when(request.getMethod()).thenReturn("DELETE");
-
- thrown.expect(authenticationException().from(Source.local(Method.JWT)).withLogin(LOGIN).andNoPublicMessage());
- thrown.expectMessage("Wrong CSFR in request");
- underTest.verifyState(request, CSRF_STATE, LOGIN);
- }
-
- @Test
- public void ignore_GET_request() {
- when(request.getRequestURI()).thenReturn(JAVA_WS_URL);
- when(request.getMethod()).thenReturn("GET");
-
- underTest.verifyState(request, null, LOGIN);
- }
-
- @Test
- public void ignore_not_api_requests() {
- executeVerifyStateDoesNotFailOnRequest("/events", "POST");
- executeVerifyStateDoesNotFailOnRequest("/favorites", "POST");
- }
-
- @Test
- public void refresh_state() {
- underTest.refreshState(request, response, CSRF_STATE, 30);
-
- verify(response).addCookie(cookieArgumentCaptor.capture());
- verifyCookie(cookieArgumentCaptor.getValue());
- }
-
- @Test
- public void remove_state() {
- underTest.removeState(request, response);
-
- verify(response).addCookie(cookieArgumentCaptor.capture());
- Cookie cookie = cookieArgumentCaptor.getValue();
- assertThat(cookie.getValue()).isNull();
- assertThat(cookie.getMaxAge()).isEqualTo(0);
- }
-
- private void verifyCookie(Cookie cookie) {
- assertThat(cookie.getName()).isEqualTo("XSRF-TOKEN");
- assertThat(cookie.getValue()).isNotEmpty();
- assertThat(cookie.getPath()).isEqualTo("/");
- assertThat(cookie.isHttpOnly()).isFalse();
- assertThat(cookie.getMaxAge()).isEqualTo(TIMEOUT);
- assertThat(cookie.getSecure()).isFalse();
- }
-
- private void mockPostJavaWsRequest() {
- when(request.getRequestURI()).thenReturn(JAVA_WS_URL);
- when(request.getMethod()).thenReturn("POST");
- }
-
- private void mockRequestCsrf(String csrfState) {
- when(request.getHeader("X-XSRF-TOKEN")).thenReturn(csrfState);
- }
-
- private void executeVerifyStateDoesNotFailOnRequest(String uri, String method) {
- when(request.getRequestURI()).thenReturn(uri);
- when(request.getMethod()).thenReturn(method);
-
- underTest.verifyState(request, null, LOGIN);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/JwtHttpHandlerTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/JwtHttpHandlerTest.java
deleted file mode 100644
index ed1f5c22084..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/JwtHttpHandlerTest.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.impl.DefaultClaims;
-import java.util.Date;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.UserDto;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.user.UserTesting.newUserDto;
-
-public class JwtHttpHandlerTest {
-
- private static final String JWT_TOKEN = "TOKEN";
- private static final String CSRF_STATE = "CSRF_STATE";
-
- private static final long NOW = 10_000_000_000L;
- private static final long FOUR_MINUTES_AGO = NOW - 4 * 60 * 1000L;
- private static final long SIX_MINUTES_AGO = NOW - 6 * 60 * 1000L;
- private static final long TEN_DAYS_AGO = NOW - 10 * 24 * 60 * 60 * 1000L;
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Rule
- public DbTester db = DbTester.create();
-
- private DbClient dbClient = db.getDbClient();
- private DbSession dbSession = db.getSession();
- private ArgumentCaptor<Cookie> cookieArgumentCaptor = ArgumentCaptor.forClass(Cookie.class);
- private ArgumentCaptor<JwtSerializer.JwtSession> jwtArgumentCaptor = ArgumentCaptor.forClass(JwtSerializer.JwtSession.class);
- private HttpServletRequest request = mock(HttpServletRequest.class);
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private HttpSession httpSession = mock(HttpSession.class);
- private System2 system2 = spy(System2.INSTANCE);
- private MapSettings settings = new MapSettings();
- private JwtSerializer jwtSerializer = mock(JwtSerializer.class);
- private JwtCsrfVerifier jwtCsrfVerifier = mock(JwtCsrfVerifier.class);
-
- private JwtHttpHandler underTest = new JwtHttpHandler(system2, dbClient, settings.asConfig(), jwtSerializer, jwtCsrfVerifier);
-
- @Before
- public void setUp() throws Exception {
- when(system2.now()).thenReturn(NOW);
- when(request.getSession()).thenReturn(httpSession);
- when(jwtSerializer.encode(any(JwtSerializer.JwtSession.class))).thenReturn(JWT_TOKEN);
- when(jwtCsrfVerifier.generateState(eq(request), eq(response), anyInt())).thenReturn(CSRF_STATE);
- }
-
- @Test
- public void create_token() {
- UserDto user = db.users().insertUser();
- underTest.generateToken(user, request, response);
-
- Optional<Cookie> jwtCookie = findCookie("JWT-SESSION");
- assertThat(jwtCookie).isPresent();
- verifyCookie(jwtCookie.get(), JWT_TOKEN, 3 * 24 * 60 * 60);
-
- verify(jwtSerializer).encode(jwtArgumentCaptor.capture());
- verifyToken(jwtArgumentCaptor.getValue(), user, 3 * 24 * 60 * 60, NOW);
- }
-
- @Test
- public void generate_csrf_state_when_creating_token() {
- UserDto user = db.users().insertUser();
- underTest.generateToken(user, request, response);
-
- verify(jwtCsrfVerifier).generateState(request, response, 3 * 24 * 60 * 60);
-
- verify(jwtSerializer).encode(jwtArgumentCaptor.capture());
- JwtSerializer.JwtSession token = jwtArgumentCaptor.getValue();
- assertThat(token.getProperties().get("xsrfToken")).isEqualTo(CSRF_STATE);
- }
-
- @Test
- public void generate_token_is_using_session_timeout_from_settings() {
- UserDto user = db.users().insertUser();
- int sessionTimeoutInMinutes = 10;
- settings.setProperty("sonar.web.sessionTimeoutInMinutes", sessionTimeoutInMinutes);
-
- underTest = new JwtHttpHandler(system2, dbClient, settings.asConfig(), jwtSerializer, jwtCsrfVerifier);
- underTest.generateToken(user, request, response);
-
- verify(jwtSerializer).encode(jwtArgumentCaptor.capture());
- verifyToken(jwtArgumentCaptor.getValue(), user, sessionTimeoutInMinutes * 60, NOW);
- }
-
- @Test
- public void session_timeout_property_cannot_be_updated() {
- UserDto user = db.users().insertUser();
- int firstSessionTimeoutInMinutes = 10;
- settings.setProperty("sonar.web.sessionTimeoutInMinutes", firstSessionTimeoutInMinutes);
-
- underTest = new JwtHttpHandler(system2, dbClient, settings.asConfig(), jwtSerializer, jwtCsrfVerifier);
- underTest.generateToken(user, request, response);
-
- // The property is updated, but it won't be taking into account
- settings.setProperty("sonar.web.sessionTimeoutInMinutes", 15);
- underTest.generateToken(user, request, response);
- verify(jwtSerializer, times(2)).encode(jwtArgumentCaptor.capture());
- verifyToken(jwtArgumentCaptor.getAllValues().get(0), user,firstSessionTimeoutInMinutes * 60, NOW);
- verifyToken(jwtArgumentCaptor.getAllValues().get(1), user, firstSessionTimeoutInMinutes * 60, NOW);
- }
-
- @Test
- public void session_timeout_property_cannot_be_zero() {
- settings.setProperty("sonar.web.sessionTimeoutInMinutes", 0);
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Property sonar.web.sessionTimeoutInMinutes must be strictly positive. Got 0");
-
- new JwtHttpHandler(system2, dbClient, settings.asConfig(), jwtSerializer, jwtCsrfVerifier);
- }
-
- @Test
- public void session_timeout_property_cannot_be_negative() {
- settings.setProperty("sonar.web.sessionTimeoutInMinutes", -10);
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Property sonar.web.sessionTimeoutInMinutes must be strictly positive. Got -10");
-
- new JwtHttpHandler(system2, dbClient, settings.asConfig(), jwtSerializer, jwtCsrfVerifier);
- }
-
- @Test
- public void session_timeout_property_cannot_be_greater_than_three_months() {
- settings.setProperty("sonar.web.sessionTimeoutInMinutes", 4 * 30 * 24 * 60);
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Property sonar.web.sessionTimeoutInMinutes must not be greater than 3 months (129600 minutes). Got 172800 minutes");
-
- new JwtHttpHandler(system2, dbClient, settings.asConfig(), jwtSerializer, jwtCsrfVerifier);
- }
-
- @Test
- public void validate_token() {
- UserDto user = db.users().insertUser();
- addJwtCookie();
- Claims claims = createToken(user.getUuid(), NOW);
- when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.of(claims));
-
- assertThat(underTest.validateToken(request, response).isPresent()).isTrue();
-
- verify(jwtSerializer, never()).encode(any(JwtSerializer.JwtSession.class));
- }
-
- @Test
- public void validate_token_refresh_session_when_refresh_time_is_reached() {
- UserDto user = db.users().insertUser();
- addJwtCookie();
- // Token was created 10 days ago and refreshed 6 minutes ago
- Claims claims = createToken(user.getUuid(), TEN_DAYS_AGO);
- claims.put("lastRefreshTime", SIX_MINUTES_AGO);
- when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.of(claims));
-
- assertThat(underTest.validateToken(request, response).isPresent()).isTrue();
-
- verify(jwtSerializer).refresh(any(Claims.class), eq(3 * 24 * 60 * 60));
- }
-
- @Test
- public void validate_token_does_not_refresh_session_when_refresh_time_is_not_reached() {
- UserDto user = db.users().insertUser();
- addJwtCookie();
- // Token was created 10 days ago and refreshed 4 minutes ago
- Claims claims = createToken(user.getUuid(), TEN_DAYS_AGO);
- claims.put("lastRefreshTime", FOUR_MINUTES_AGO);
- when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.of(claims));
-
- assertThat(underTest.validateToken(request, response).isPresent()).isTrue();
-
- verify(jwtSerializer, never()).refresh(any(Claims.class), anyInt());
- }
-
- @Test
- public void validate_token_does_not_refresh_session_when_disconnected_timeout_is_reached() {
- UserDto user = db.users().insertUser();
- addJwtCookie();
- // Token was created 4 months ago, refreshed 4 minutes ago, and it expired in 5 minutes
- Claims claims = createToken(user.getUuid(), NOW - (4L * 30 * 24 * 60 * 60 * 1000));
- claims.setExpiration(new Date(NOW + 5 * 60 * 1000));
- claims.put("lastRefreshTime", FOUR_MINUTES_AGO);
- when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.of(claims));
-
- assertThat(underTest.validateToken(request, response).isPresent()).isFalse();
- }
-
- @Test
- public void validate_token_does_not_refresh_session_when_user_is_disabled() {
- addJwtCookie();
- UserDto user = addUser(false);
-
- Claims claims = createToken(user.getLogin(), NOW);
- when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.of(claims));
-
- assertThat(underTest.validateToken(request, response).isPresent()).isFalse();
- }
-
- @Test
- public void validate_token_does_not_refresh_session_when_token_is_no_more_valid() {
- addJwtCookie();
-
- when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.empty());
-
- assertThat(underTest.validateToken(request, response).isPresent()).isFalse();
- }
-
- @Test
- public void validate_token_does_nothing_when_no_jwt_cookie() {
- underTest.validateToken(request, response);
-
- verifyZeroInteractions(httpSession, jwtSerializer);
- assertThat(underTest.validateToken(request, response).isPresent()).isFalse();
- }
-
- @Test
- public void validate_token_does_nothing_when_empty_value_in_jwt_cookie() {
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie("JWT-SESSION", "")});
-
- underTest.validateToken(request, response);
-
- verifyZeroInteractions(httpSession, jwtSerializer);
- assertThat(underTest.validateToken(request, response).isPresent()).isFalse();
- }
-
- @Test
- public void validate_token_verify_csrf_state() {
- UserDto user = db.users().insertUser();
- addJwtCookie();
- Claims claims = createToken(user.getUuid(), NOW);
- claims.put("xsrfToken", CSRF_STATE);
- when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.of(claims));
-
- underTest.validateToken(request, response);
-
- verify(jwtCsrfVerifier).verifyState(request, CSRF_STATE, user.getUuid());
- }
-
- @Test
- public void validate_token_refresh_state_when_refreshing_token() {
- UserDto user = db.users().insertUser();
- addJwtCookie();
-
- // Token was created 10 days ago and refreshed 6 minutes ago
- Claims claims = createToken(user.getUuid(), TEN_DAYS_AGO);
- claims.put("xsrfToken", "CSRF_STATE");
- when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.of(claims));
-
- underTest.validateToken(request, response);
-
- verify(jwtSerializer).refresh(any(Claims.class), anyInt());
- verify(jwtCsrfVerifier).refreshState(request, response, "CSRF_STATE", 3 * 24 * 60 * 60);
- }
-
- @Test
- public void remove_token() {
- underTest.removeToken(request, response);
-
- verifyCookie(findCookie("JWT-SESSION").get(), null, 0);
- verify(jwtCsrfVerifier).removeState(request, response);
- }
-
- private void verifyToken(JwtSerializer.JwtSession token, UserDto user, int expectedExpirationTime, long expectedRefreshTime) {
- assertThat(token.getExpirationTimeInSeconds()).isEqualTo(expectedExpirationTime);
- assertThat(token.getUserLogin()).isEqualTo(user.getUuid());
- assertThat(token.getProperties().get("lastRefreshTime")).isEqualTo(expectedRefreshTime);
- }
-
- private Optional<Cookie> findCookie(String name) {
- verify(response).addCookie(cookieArgumentCaptor.capture());
- return cookieArgumentCaptor.getAllValues().stream()
- .filter(cookie -> name.equals(cookie.getName()))
- .findFirst();
- }
-
- private void verifyCookie(Cookie cookie, @Nullable String value, int expiry) {
- assertThat(cookie.getPath()).isEqualTo("/");
- assertThat(cookie.isHttpOnly()).isTrue();
- assertThat(cookie.getMaxAge()).isEqualTo(expiry);
- assertThat(cookie.getSecure()).isFalse();
- assertThat(cookie.getValue()).isEqualTo(value);
- }
-
- private UserDto addUser(boolean active) {
- UserDto user = newUserDto()
- .setActive(active);
- dbClient.userDao().insert(dbSession, user);
- dbSession.commit();
- return user;
- }
-
- private Cookie addJwtCookie() {
- Cookie cookie = new Cookie("JWT-SESSION", JWT_TOKEN);
- when(request.getCookies()).thenReturn(new Cookie[] {cookie});
- return cookie;
- }
-
- private Claims createToken(String userUuid, long createdAt) {
- // Expired in 5 minutes by default
- return createToken(userUuid, createdAt, NOW + 5 * 60 * 1000);
- }
-
- private Claims createToken(String userUuid, long createdAt, long expiredAt) {
- DefaultClaims claims = new DefaultClaims();
- claims.setId("ID");
- claims.setSubject(userUuid);
- claims.setIssuedAt(new Date(createdAt));
- claims.setExpiration(new Date(expiredAt));
- claims.put("lastRefreshTime", createdAt);
- return claims;
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/JwtSerializerTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/JwtSerializerTest.java
deleted file mode 100644
index 08aae1e567e..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/JwtSerializerTest.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.collect.ImmutableMap;
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.SignatureAlgorithm;
-import io.jsonwebtoken.impl.DefaultClaims;
-import java.util.Base64;
-import java.util.Date;
-import java.util.Optional;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.UuidFactory;
-import org.sonar.core.util.UuidFactoryImpl;
-import org.sonar.server.authentication.JwtSerializer.JwtSession;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException;
-
-public class JwtSerializerTest {
-
- private static final String A_SECRET_KEY = "HrPSavOYLNNrwTY+SOqpChr7OwvbR/zbDLdVXRN0+Eg=";
- private static final String USER_LOGIN = "john";
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- private MapSettings settings = new MapSettings();
- private System2 system2 = System2.INSTANCE;
- private UuidFactory uuidFactory = UuidFactoryImpl.INSTANCE;
- private JwtSerializer underTest = new JwtSerializer(settings.asConfig(), system2, uuidFactory);
-
- @Test
- public void generate_token() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
-
- String token = underTest.encode(new JwtSession(USER_LOGIN, 10));
-
- assertThat(token).isNotEmpty();
- }
-
- @Test
- public void generate_token_with_expiration_date() {
- setSecretKey(A_SECRET_KEY);
-
- underTest.start();
- Date now = new Date();
-
- long expirationTimeInSeconds = 10L;
- String token = underTest.encode(new JwtSession(USER_LOGIN, expirationTimeInSeconds));
-
- assertThat(token).isNotEmpty();
- Claims claims = underTest.decode(token).get();
- assertThat(claims.getExpiration().getTime()).isGreaterThanOrEqualTo(now.getTime() + expirationTimeInSeconds * 1000L - 1000L);
- }
-
- @Test
- public void generate_token_with_big_expiration_date() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
- Date now = new Date();
-
- long oneYearInSeconds = 12 * 30 * 24 * 60 * 60L;
- String token = underTest.encode(new JwtSession(USER_LOGIN, oneYearInSeconds));
-
- assertThat(token).isNotEmpty();
- Claims claims = underTest.decode(token).get();
- // Check expiration date it set to one year in the future
- assertThat(claims.getExpiration().getTime()).isGreaterThanOrEqualTo(now.getTime() + oneYearInSeconds * 1000L - 1000L);
- }
-
- @Test
- public void generate_token_with_property() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
-
- String token = underTest.encode(new JwtSession(USER_LOGIN, 10, ImmutableMap.of("custom", "property")));
-
- assertThat(token).isNotEmpty();
- Claims claims = underTest.decode(token).get();
- assertThat(claims.get("custom")).isEqualTo("property");
- }
-
- @Test
- public void decode_token() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
- Date now = new Date();
-
- String token = underTest.encode(new JwtSession(USER_LOGIN, 20 * 60));
-
- Claims claims = underTest.decode(token).get();
- assertThat(claims.getId()).isNotEmpty();
- assertThat(claims.getSubject()).isEqualTo(USER_LOGIN);
- assertThat(claims.getExpiration()).isNotNull();
- assertThat(claims.getIssuedAt()).isNotNull();
- // Check expiration date it set to more than 19 minutes in the future
- assertThat(claims.getExpiration()).isAfterOrEqualsTo(new Date(now.getTime() + 19 * 60 * 1000));
- }
-
- @Test
- public void return_no_token_when_expiration_date_is_reached() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
-
- String token = Jwts.builder()
- .setId("123")
- .setIssuedAt(new Date(system2.now()))
- .setExpiration(new Date(system2.now()))
- .signWith(SignatureAlgorithm.HS256, decodeSecretKey(A_SECRET_KEY))
- .compact();
-
- assertThat(underTest.decode(token)).isEmpty();
- }
-
- @Test
- public void return_no_token_when_secret_key_has_changed() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
-
- String token = Jwts.builder()
- .setId("123")
- .setSubject(USER_LOGIN)
- .setIssuedAt(new Date(system2.now()))
- .setExpiration(new Date(system2.now() + 20 * 60 * 1000))
- .signWith(SignatureAlgorithm.HS256, decodeSecretKey("LyWgHktP0FuHB2K+kMs3KWMCJyFHVZDdDSqpIxAMVaQ="))
- .compact();
-
- assertThat(underTest.decode(token)).isEmpty();
- }
-
- @Test
- public void fail_to_decode_token_when_no_id() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
-
- String token = Jwts.builder()
- .setSubject(USER_LOGIN)
- .setIssuer("sonarqube")
- .setIssuedAt(new Date(system2.now()))
- .setExpiration(new Date(system2.now() + 20 * 60 * 1000))
- .signWith(SignatureAlgorithm.HS256, decodeSecretKey(A_SECRET_KEY))
- .compact();
-
- expectedException.expect(authenticationException().from(Source.jwt()).withLogin(USER_LOGIN).andNoPublicMessage());
- expectedException.expectMessage("Token id hasn't been found");
- underTest.decode(token);
- }
-
- @Test
- public void fail_to_decode_token_when_no_subject() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
-
- String token = Jwts.builder()
- .setId("123")
- .setIssuer("sonarqube")
- .setIssuedAt(new Date(system2.now()))
- .setExpiration(new Date(system2.now() + 20 * 60 * 1000))
- .signWith(SignatureAlgorithm.HS256, decodeSecretKey(A_SECRET_KEY))
- .compact();
-
- expectedException.expect(authenticationException().from(Source.jwt()).withoutLogin().andNoPublicMessage());
- expectedException.expectMessage("Token subject hasn't been found");
- underTest.decode(token);
- }
-
- @Test
- public void fail_to_decode_token_when_no_expiration_date() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
-
- String token = Jwts.builder()
- .setId("123")
- .setIssuer("sonarqube")
- .setSubject(USER_LOGIN)
- .setIssuedAt(new Date(system2.now()))
- .signWith(SignatureAlgorithm.HS256, decodeSecretKey(A_SECRET_KEY))
- .compact();
-
- expectedException.expect(authenticationException().from(Source.jwt()).withLogin(USER_LOGIN).andNoPublicMessage());
- expectedException.expectMessage("Token expiration date hasn't been found");
- underTest.decode(token);
- }
-
- @Test
- public void fail_to_decode_token_when_no_creation_date() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
-
- String token = Jwts.builder()
- .setId("123")
- .setSubject(USER_LOGIN)
- .setExpiration(new Date(system2.now() + 20 * 60 * 1000))
- .signWith(SignatureAlgorithm.HS256, decodeSecretKey(A_SECRET_KEY))
- .compact();
-
- expectedException.expect(authenticationException().from(Source.jwt()).withLogin(USER_LOGIN).andNoPublicMessage());
- expectedException.expectMessage("Token creation date hasn't been found");
- underTest.decode(token);
- }
-
- @Test
- public void generate_new_secret_key_if_not_set_by_settings() {
- assertThat(underTest.getSecretKey()).isNull();
-
- underTest.start();
-
- assertThat(underTest.getSecretKey()).isNotNull();
- assertThat(underTest.getSecretKey().getAlgorithm()).isEqualTo(SignatureAlgorithm.HS256.getJcaName());
- }
-
- @Test
- public void load_secret_key_from_settings() {
- setSecretKey(A_SECRET_KEY);
-
- underTest.start();
-
- assertThat(settings.getString("sonar.auth.jwtBase64Hs256Secret")).isEqualTo(A_SECRET_KEY);
- }
-
- @Test
- public void refresh_token() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
-
- Date now = new Date();
- Date createdAt = DateUtils.parseDate("2016-01-01");
- // Expired in 10 minutes
- Date expiredAt = new Date(now.getTime() + 10 * 60 * 1000);
- Claims token = new DefaultClaims()
- .setId("id")
- .setSubject("subject")
- .setIssuer("sonarqube")
- .setIssuedAt(createdAt)
- .setExpiration(expiredAt);
- token.put("key", "value");
-
- // Refresh the token with a higher expiration time
- String encodedToken = underTest.refresh(token, 20 * 60);
-
- Claims result = underTest.decode(encodedToken).get();
- assertThat(result.getId()).isEqualTo("id");
- assertThat(result.getSubject()).isEqualTo("subject");
- assertThat(result.getIssuer()).isEqualTo("sonarqube");
- assertThat(result.getIssuedAt()).isEqualTo(createdAt);
- assertThat(result.get("key")).isEqualTo("value");
- // Expiration date has been changed
- assertThat(result.getExpiration()).isNotEqualTo(expiredAt)
- .isAfterOrEqualsTo(new Date(now.getTime() + 19 * 1000));
- }
-
- @Test
- public void refresh_token_generate_a_new_hash() {
- setSecretKey(A_SECRET_KEY);
- underTest.start();
- String token = underTest.encode(new JwtSession(USER_LOGIN, 30));
- Optional<Claims> claims = underTest.decode(token);
-
- String newToken = underTest.refresh(claims.get(), 45);
-
- assertThat(newToken).isNotEqualTo(token);
- }
-
- @Test
- public void encode_fail_when_not_started() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("org.sonar.server.authentication.JwtSerializer not started");
-
- underTest.encode(new JwtSession(USER_LOGIN, 10));
- }
-
- @Test
- public void decode_fail_when_not_started() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("org.sonar.server.authentication.JwtSerializer not started");
-
- underTest.decode("token");
- }
-
- @Test
- public void refresh_fail_when_not_started() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("org.sonar.server.authentication.JwtSerializer not started");
-
- underTest.refresh(new DefaultClaims(), 10);
- }
-
- private SecretKey decodeSecretKey(String encodedKey) {
- byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
- return new SecretKeySpec(decodedKey, 0, decodedKey.length, SignatureAlgorithm.HS256.getJcaName());
- }
-
- private void setSecretKey(String s) {
- settings.setProperty("sonar.auth.jwtBase64Hs256Secret", s);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/LogOAuthWarningTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/LogOAuthWarningTest.java
deleted file mode 100644
index 50d26ce5d8d..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/LogOAuthWarningTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.platform.Server;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-
-public class LogOAuthWarningTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- @Rule
- public LogTester logTester = new LogTester();
-
-
- private Server server = mock(Server.class);
-
- @Test
- public void log_warning_at_startup_if_non_secured_base_url_and_oauth_is_installed() {
- when(server.getPublicRootUrl()).thenReturn("http://mydomain.com");
-
- LogOAuthWarning underTest = new LogOAuthWarning(server, new OAuth2IdentityProvider[1]);
-
- underTest.start();
-
- assertThat(logTester.logs(LoggerLevel.WARN)).containsOnly("For security reasons, OAuth authentication should use HTTPS. You should set the property 'Administration > Configuration > Server base URL' to a HTTPS URL.");
-
- underTest.stop();
- }
-
- @Test
- public void do_not_log_warning_at_startup_if_secured_base_url_and_oauth_is_installed() {
- when(server.getPublicRootUrl()).thenReturn("https://mydomain.com");
-
- LogOAuthWarning underTest = new LogOAuthWarning(server, new OAuth2IdentityProvider[1]);
-
- underTest.start();
-
- assertThat(logTester.logs(LoggerLevel.WARN)).isEmpty();
-
- underTest.stop();
- }
-
- @Test
- public void do_not_log_warning_at_startup_if_non_secured_base_url_but_oauth_is_not_installed() {
- when(server.getPublicRootUrl()).thenReturn("http://mydomain.com");
-
- LogOAuthWarning underTest = new LogOAuthWarning(server);
-
- underTest.start();
-
- assertThat(logTester.logs(LoggerLevel.WARN)).isEmpty();
-
- underTest.stop();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2AuthenticationParametersImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2AuthenticationParametersImplTest.java
deleted file mode 100644
index 07a6fbe79e8..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2AuthenticationParametersImplTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Optional;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class OAuth2AuthenticationParametersImplTest {
-
- private static final String AUTHENTICATION_COOKIE_NAME = "AUTH-PARAMS";
- private ArgumentCaptor<Cookie> cookieArgumentCaptor = ArgumentCaptor.forClass(Cookie.class);
-
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private HttpServletRequest request = mock(HttpServletRequest.class);
-
- private OAuth2AuthenticationParameters underTest = new OAuth2AuthenticationParametersImpl();
-
- @Before
- public void setUp() throws Exception {
- when(request.getContextPath()).thenReturn("");
- }
-
- @Test
- public void init_create_cookie() {
- when(request.getParameter("return_to")).thenReturn("/settings");
-
- underTest.init(request, response);
-
- verify(response).addCookie(cookieArgumentCaptor.capture());
- Cookie cookie = cookieArgumentCaptor.getValue();
- assertThat(cookie.getName()).isEqualTo(AUTHENTICATION_COOKIE_NAME);
- assertThat(cookie.getValue()).isNotEmpty();
- assertThat(cookie.getPath()).isEqualTo("/");
- assertThat(cookie.isHttpOnly()).isTrue();
- assertThat(cookie.getMaxAge()).isEqualTo(300);
- assertThat(cookie.getSecure()).isFalse();
- }
-
- @Test
- public void init_does_not_create_cookie_when_no_parameter() {
- underTest.init(request, response);
-
- verify(response, never()).addCookie(any(Cookie.class));
- }
-
- @Test
- public void init_does_not_create_cookie_when_parameters_are_empty() {
- when(request.getParameter("return_to")).thenReturn("");
- when(request.getParameter("allowEmailShift")).thenReturn("");
-
- underTest.init(request, response);
-
- verify(response, never()).addCookie(any(Cookie.class));
- }
-
- @Test
- public void init_does_not_create_cookie_when_parameters_are_null() {
- when(request.getParameter("return_to")).thenReturn(null);
- when(request.getParameter("allowEmailShift")).thenReturn(null);
-
- underTest.init(request, response);
-
- verify(response, never()).addCookie(any(Cookie.class));
- }
-
- @Test
- public void return_to_is_not_set_when_not_local() {
- when(request.getParameter("return_to")).thenReturn("http://external_url");
- underTest.init(request, response);
- verify(response, never()).addCookie(any());
-
- when(request.getParameter("return_to")).thenReturn("//local_file");
- underTest.init(request, response);
- verify(response, never()).addCookie(any());
-
- when(request.getParameter("return_to")).thenReturn("/\\local_file");
- underTest.init(request, response);
- verify(response, never()).addCookie(any());
-
- when(request.getParameter("return_to")).thenReturn("something_else");
- underTest.init(request, response);
- verify(response, never()).addCookie(any());
- }
-
- @Test
- public void get_return_to_parameter() {
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie(AUTHENTICATION_COOKIE_NAME, "{\"return_to\":\"/settings\"}")});
-
- Optional<String> redirection = underTest.getReturnTo(request);
-
- assertThat(redirection).isNotEmpty();
- assertThat(redirection.get()).isEqualTo("/settings");
- }
-
- @Test
- public void get_return_to_is_empty_when_no_cookie() {
- when(request.getCookies()).thenReturn(new Cookie[] {});
-
- Optional<String> redirection = underTest.getReturnTo(request);
-
- assertThat(redirection).isEmpty();
- }
-
- @Test
- public void get_return_to_is_empty_when_no_value() {
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie(AUTHENTICATION_COOKIE_NAME, "{}")});
-
- Optional<String> redirection = underTest.getReturnTo(request);
-
- assertThat(redirection).isEmpty();
- }
-
- @Test
- public void get_allowEmailShift_parameter() {
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie(AUTHENTICATION_COOKIE_NAME, "{\"allowEmailShift\":\"true\"}")});
-
- Optional<Boolean> allowEmailShift = underTest.getAllowEmailShift(request);
-
- assertThat(allowEmailShift).isNotEmpty();
- assertThat(allowEmailShift.get()).isTrue();
- }
-
- @Test
- public void get_allowEmailShift_is_empty_when_no_cookie() {
- when(request.getCookies()).thenReturn(new Cookie[] {});
-
- Optional<Boolean> allowEmailShift = underTest.getAllowEmailShift(request);
-
- assertThat(allowEmailShift).isEmpty();
- }
-
- @Test
- public void get_allowEmailShift_is_empty_when_no_value() {
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie(AUTHENTICATION_COOKIE_NAME, "{}")});
-
- Optional<Boolean> allowEmailShift = underTest.getAllowEmailShift(request);
-
- assertThat(allowEmailShift).isEmpty();
- }
-
- @Test
- public void getAllowUpdateLogin_is_empty_when_no_cookie() {
- when(request.getCookies()).thenReturn(new Cookie[] {});
-
- Optional<Boolean> allowLoginUpdate = underTest.getAllowUpdateLogin(request);
-
- assertThat(allowLoginUpdate).isEmpty();
- }
-
- @Test
- public void getAllowUpdateLogin_is_empty_when_no_value() {
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie(AUTHENTICATION_COOKIE_NAME, "{}")});
-
- Optional<Boolean> allowLoginUpdate = underTest.getAllowUpdateLogin(request);
-
- assertThat(allowLoginUpdate).isEmpty();
- }
-
- @Test
- public void delete() {
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie(AUTHENTICATION_COOKIE_NAME, "{\"return_to\":\"/settings\"}")});
-
- underTest.delete(request, response);
-
- verify(response).addCookie(cookieArgumentCaptor.capture());
- Cookie updatedCookie = cookieArgumentCaptor.getValue();
- assertThat(updatedCookie.getName()).isEqualTo(AUTHENTICATION_COOKIE_NAME);
- assertThat(updatedCookie.getValue()).isNull();
- assertThat(updatedCookie.getPath()).isEqualTo("/");
- assertThat(updatedCookie.getMaxAge()).isEqualTo(0);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2CallbackFilterTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2CallbackFilterTest.java
deleted file mode 100644
index a42f29cf059..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2CallbackFilterTest.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.FilterChain;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.api.server.authentication.UnauthorizedException;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.authentication.exception.EmailAlreadyExistsRedirectionException;
-import org.sonar.server.user.ThreadLocalUserSession;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-public class OAuth2CallbackFilterTest {
-
- private static final String OAUTH2_PROVIDER_KEY = "github";
- private static final String LOGIN = "foo";
-
- @Rule
- public LogTester logTester = new LogTester();
- @Rule
- public ExpectedException thrown = ExpectedException.none();
- @Rule
- public IdentityProviderRepositoryRule identityProviderRepository = new IdentityProviderRepositoryRule();
-
- private OAuth2ContextFactory oAuth2ContextFactory = mock(OAuth2ContextFactory.class);
-
- private HttpServletRequest request = mock(HttpServletRequest.class);
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private FilterChain chain = mock(FilterChain.class);
-
- private FakeOAuth2IdentityProvider oAuth2IdentityProvider = new WellbehaveFakeOAuth2IdentityProvider(OAUTH2_PROVIDER_KEY, true, LOGIN);
- private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
- private OAuth2AuthenticationParameters oAuthRedirection = mock(OAuth2AuthenticationParameters.class);
- private ThreadLocalUserSession threadLocalUserSession = mock(ThreadLocalUserSession.class);
-
- private ArgumentCaptor<AuthenticationException> authenticationExceptionCaptor = ArgumentCaptor.forClass(AuthenticationException.class);
- private ArgumentCaptor<Cookie> cookieArgumentCaptor = ArgumentCaptor.forClass(Cookie.class);
-
- private OAuth2CallbackFilter underTest = new OAuth2CallbackFilter(identityProviderRepository, oAuth2ContextFactory, authenticationEvent, oAuthRedirection,
- threadLocalUserSession);
-
- @Before
- public void setUp() throws Exception {
- when(oAuth2ContextFactory.newCallback(request, response, oAuth2IdentityProvider)).thenReturn(mock(OAuth2IdentityProvider.CallbackContext.class));
- when(request.getContextPath()).thenReturn("");
- }
-
- @Test
- public void do_get_pattern() {
- assertThat(underTest.doGetPattern()).isNotNull();
- }
-
- @Test
- public void do_filter_with_context() {
- when(request.getContextPath()).thenReturn("/sonarqube");
- when(request.getRequestURI()).thenReturn("/sonarqube/oauth2/callback/" + OAUTH2_PROVIDER_KEY);
- identityProviderRepository.addIdentityProvider(oAuth2IdentityProvider);
- when(threadLocalUserSession.hasSession()).thenReturn(true);
- when(threadLocalUserSession.getLogin()).thenReturn(LOGIN);
-
- underTest.doFilter(request, response, chain);
-
- assertCallbackCalled(oAuth2IdentityProvider);
- verify(authenticationEvent).loginSuccess(request, LOGIN, Source.oauth2(oAuth2IdentityProvider));
- }
-
- @Test
- public void do_filter_with_context_no_log_if_provider_did_not_call_authenticate_on_context() {
- when(request.getContextPath()).thenReturn("/sonarqube");
- when(request.getRequestURI()).thenReturn("/sonarqube/oauth2/callback/" + OAUTH2_PROVIDER_KEY);
- FakeOAuth2IdentityProvider identityProvider = new FakeOAuth2IdentityProvider(OAUTH2_PROVIDER_KEY, true);
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- assertCallbackCalled(identityProvider);
- verify(authenticationEvent).loginFailure(eq(request), authenticationExceptionCaptor.capture());
- AuthenticationException authenticationException = authenticationExceptionCaptor.getValue();
- assertThat(authenticationException).hasMessage("Plugin did not call authenticate");
- assertThat(authenticationException.getSource()).isEqualTo(Source.oauth2(identityProvider));
- assertThat(authenticationException.getLogin()).isNull();
- assertThat(authenticationException.getPublicMessage()).isNull();
- }
-
- @Test
- public void do_filter_on_auth2_identity_provider() {
- when(request.getRequestURI()).thenReturn("/oauth2/callback/" + OAUTH2_PROVIDER_KEY);
- identityProviderRepository.addIdentityProvider(oAuth2IdentityProvider);
- when(threadLocalUserSession.hasSession()).thenReturn(true);
- when(threadLocalUserSession.getLogin()).thenReturn(LOGIN);
-
- underTest.doFilter(request, response, chain);
-
- assertCallbackCalled(oAuth2IdentityProvider);
- verify(authenticationEvent).loginSuccess(request, LOGIN, Source.oauth2(oAuth2IdentityProvider));
- }
-
- @Test
- public void fail_on_not_oauth2_provider() throws Exception {
- String providerKey = "openid";
- when(request.getRequestURI()).thenReturn("/oauth2/callback/" + providerKey);
- identityProviderRepository.addIdentityProvider(new FakeBasicIdentityProvider(providerKey, true));
-
- underTest.doFilter(request, response, chain);
-
- assertError("Not an OAuth2IdentityProvider: class org.sonar.server.authentication.FakeBasicIdentityProvider");
- verifyZeroInteractions(authenticationEvent);
- }
-
- @Test
- public void fail_on_disabled_provider() throws Exception {
- when(request.getRequestURI()).thenReturn("/oauth2/callback/" + OAUTH2_PROVIDER_KEY);
- identityProviderRepository.addIdentityProvider(new FakeOAuth2IdentityProvider(OAUTH2_PROVIDER_KEY, false));
-
- underTest.doFilter(request, response, chain);
-
- assertError("Failed to retrieve IdentityProvider for key 'github'");
- verifyZeroInteractions(authenticationEvent);
- }
-
- @Test
- public void redirect_when_failing_because_of_UnauthorizedExceptionException() throws Exception {
- FailWithUnauthorizedExceptionIdProvider identityProvider = new FailWithUnauthorizedExceptionIdProvider();
- when(request.getRequestURI()).thenReturn("/oauth2/callback/" + identityProvider.getKey());
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(response).sendRedirect("/sessions/unauthorized");
- verify(authenticationEvent).loginFailure(eq(request), authenticationExceptionCaptor.capture());
- AuthenticationException authenticationException = authenticationExceptionCaptor.getValue();
- assertThat(authenticationException).hasMessage("Email john@email.com is already used");
- assertThat(authenticationException.getSource()).isEqualTo(Source.oauth2(identityProvider));
- assertThat(authenticationException.getLogin()).isNull();
- assertThat(authenticationException.getPublicMessage()).isEqualTo("Email john@email.com is already used");
- verify(oAuthRedirection).delete(eq(request), eq(response));
-
- verify(response).addCookie(cookieArgumentCaptor.capture());
- Cookie cookie = cookieArgumentCaptor.getValue();
- assertThat(cookie.getName()).isEqualTo("AUTHENTICATION-ERROR");
- assertThat(cookie.getValue()).isEqualTo("Email%20john%40email.com%20is%20already%20used");
- assertThat(cookie.getPath()).isEqualTo("/");
- assertThat(cookie.isHttpOnly()).isFalse();
- assertThat(cookie.getMaxAge()).isEqualTo(300);
- assertThat(cookie.getSecure()).isFalse();
- }
-
- @Test
- public void redirect_with_context_path_when_failing_because_of_UnauthorizedExceptionException() throws Exception {
- when(request.getContextPath()).thenReturn("/sonarqube");
- FailWithUnauthorizedExceptionIdProvider identityProvider = new FailWithUnauthorizedExceptionIdProvider();
- when(request.getRequestURI()).thenReturn("/sonarqube/oauth2/callback/" + identityProvider.getKey());
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(response).sendRedirect("/sonarqube/sessions/unauthorized");
- verify(oAuthRedirection).delete(eq(request), eq(response));
- }
-
- @Test
- public void redirect_when_failing_because_of_Exception() throws Exception {
- FailWithIllegalStateException identityProvider = new FailWithIllegalStateException();
- when(request.getRequestURI()).thenReturn("/oauth2/callback/" + identityProvider.getKey());
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(response).sendRedirect("/sessions/unauthorized");
- assertThat(logTester.logs(LoggerLevel.WARN)).containsExactlyInAnyOrder("Fail to callback authentication with 'failing'");
- verify(oAuthRedirection).delete(eq(request), eq(response));
- }
-
- @Test
- public void redirect_with_context_when_failing_because_of_Exception() throws Exception {
- when(request.getContextPath()).thenReturn("/sonarqube");
- FailWithIllegalStateException identityProvider = new FailWithIllegalStateException();
- when(request.getRequestURI()).thenReturn("/oauth2/callback/" + identityProvider.getKey());
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(response).sendRedirect("/sonarqube/sessions/unauthorized");
- }
-
- @Test
- public void redirect_when_failing_because_of_EmailAlreadyExistException() throws Exception {
- UserDto existingUser = newUserDto().setEmail("john@email.com").setExternalLogin("john.bitbucket").setExternalIdentityProvider("bitbucket");
- FailWithEmailAlreadyExistException identityProvider = new FailWithEmailAlreadyExistException(existingUser);
- when(request.getRequestURI()).thenReturn("/oauth2/callback/" + identityProvider.getKey());
- identityProviderRepository.addIdentityProvider(identityProvider);
-
- underTest.doFilter(request, response, chain);
-
- verify(response).sendRedirect("/sessions/email_already_exists");
- verify(oAuthRedirection).delete(eq(request), eq(response));
- verify(response).addCookie(cookieArgumentCaptor.capture());
- Cookie cookie = cookieArgumentCaptor.getValue();
- assertThat(cookie.getName()).isEqualTo("AUTHENTICATION-ERROR");
- assertThat(cookie.getValue()).contains("john%40email.com");
- assertThat(cookie.getPath()).isEqualTo("/");
- assertThat(cookie.isHttpOnly()).isFalse();
- assertThat(cookie.getMaxAge()).isEqualTo(300);
- assertThat(cookie.getSecure()).isFalse();
- }
-
- @Test
- public void fail_when_no_oauth2_provider_provided() throws Exception {
- when(request.getRequestURI()).thenReturn("/oauth2/callback");
-
- underTest.doFilter(request, response, chain);
-
- assertError("No provider key found in URI");
- verifyZeroInteractions(authenticationEvent);
- }
-
- private void assertCallbackCalled(FakeOAuth2IdentityProvider oAuth2IdentityProvider) {
- assertThat(logTester.logs(LoggerLevel.ERROR)).isEmpty();
- assertThat(oAuth2IdentityProvider.isCallbackCalled()).isTrue();
- }
-
- private void assertError(String expectedError) throws Exception {
- assertThat(logTester.logs(LoggerLevel.WARN)).contains(expectedError);
- verify(response).sendRedirect("/sessions/unauthorized");
- assertThat(oAuth2IdentityProvider.isInitCalled()).isFalse();
- }
-
- private static class FailWithUnauthorizedExceptionIdProvider extends FailingIdentityProvider {
- @Override
- public void callback(CallbackContext context) {
- throw new UnauthorizedException("Email john@email.com is already used");
- }
- }
-
- private static class FailWithIllegalStateException extends FailingIdentityProvider {
- @Override
- public void callback(CallbackContext context) {
- throw new IllegalStateException("Failure !");
- }
- }
-
- private static class FailWithEmailAlreadyExistException extends FailingIdentityProvider {
-
- private final UserDto existingUser;
-
- public FailWithEmailAlreadyExistException(UserDto existingUser) {
- this.existingUser = existingUser;
- }
-
- @Override
- public void callback(CallbackContext context) {
- throw new EmailAlreadyExistsRedirectionException(existingUser.getEmail(), existingUser, UserIdentity.builder()
- .setProviderLogin("john.github")
- .setLogin("john.github")
- .setName(existingUser.getName())
- .setEmail(existingUser.getEmail())
- .build(), this);
- }
- }
-
- private static abstract class FailingIdentityProvider extends TestIdentityProvider implements OAuth2IdentityProvider {
- FailingIdentityProvider() {
- this.setKey("failing");
- this.setName("Failing");
- this.setEnabled(true);
- }
-
- @Override
- public void init(InitContext context) {
- // Nothing to do
- }
- }
-
- /**
- * An extension of {@link FakeOAuth2IdentityProvider} that actually call {@link org.sonar.api.server.authentication.OAuth2IdentityProvider.CallbackContext#authenticate(UserIdentity)}.
- */
- private static class WellbehaveFakeOAuth2IdentityProvider extends FakeOAuth2IdentityProvider {
- private final String login;
-
- public WellbehaveFakeOAuth2IdentityProvider(String key, boolean enabled, String login) {
- super(key, enabled);
- this.login = login;
- }
-
- @Override
- public void callback(CallbackContext context) {
- super.callback(context);
- context.authenticate(UserIdentity.builder()
- .setLogin(login)
- .setProviderLogin(login)
- .setEmail(login + "@toto.com")
- .setName("name of " + login)
- .build());
- }
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2ContextFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2ContextFactoryTest.java
deleted file mode 100644
index cf2eb5f19fe..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2ContextFactoryTest.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.collect.ImmutableSet;
-import java.util.Optional;
-import java.util.Set;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.platform.Server;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.OAuth2ContextFactory.OAuthContextImpl;
-import org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy;
-import org.sonar.server.user.TestUserSessionFactory;
-import org.sonar.server.user.ThreadLocalUserSession;
-import org.sonar.server.user.UserSession;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class OAuth2ContextFactoryTest {
-
- private static final String PROVIDER_KEY = "github";
- private static final String SECURED_PUBLIC_ROOT_URL = "https://mydomain.com";
- private static final String PROVIDER_NAME = "provider name";
- private static final UserIdentity USER_IDENTITY = UserIdentity.builder()
- .setProviderId("ABCD")
- .setProviderLogin("johndoo")
- .setLogin("id:johndoo")
- .setName("John")
- .setEmail("john@email.com")
- .build();
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private ThreadLocalUserSession threadLocalUserSession = mock(ThreadLocalUserSession.class);
- private TestUserRegistrar userIdentityAuthenticator = new TestUserRegistrar();
- private Server server = mock(Server.class);
- private OAuthCsrfVerifier csrfVerifier = mock(OAuthCsrfVerifier.class);
- private JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class);
- private TestUserSessionFactory userSessionFactory = TestUserSessionFactory.standalone();
- private OAuth2AuthenticationParameters oAuthParameters = mock(OAuth2AuthenticationParameters.class);
- private HttpServletRequest request = mock(HttpServletRequest.class);
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private HttpSession session = mock(HttpSession.class);
- private OAuth2IdentityProvider identityProvider = mock(OAuth2IdentityProvider.class);
-
- private OAuth2ContextFactory underTest = new OAuth2ContextFactory(threadLocalUserSession, userIdentityAuthenticator, server, csrfVerifier, jwtHttpHandler, userSessionFactory,
- oAuthParameters);
-
- @Before
- public void setUp() throws Exception {
- when(request.getSession()).thenReturn(session);
- when(identityProvider.getKey()).thenReturn(PROVIDER_KEY);
- when(identityProvider.getName()).thenReturn(PROVIDER_NAME);
- }
-
- @Test
- public void create_context() {
- when(server.getPublicRootUrl()).thenReturn(SECURED_PUBLIC_ROOT_URL);
-
- OAuth2IdentityProvider.InitContext context = newInitContext();
-
- assertThat(context.getRequest()).isEqualTo(request);
- assertThat(context.getResponse()).isEqualTo(response);
- assertThat(context.getCallbackUrl()).isEqualTo("https://mydomain.com/oauth2/callback/github");
- }
-
- @Test
- public void generate_csrf_state() {
- OAuth2IdentityProvider.InitContext context = newInitContext();
-
- context.generateCsrfState();
-
- verify(csrfVerifier).generateState(request, response);
- }
-
- @Test
- public void redirect_to() throws Exception {
- OAuth2IdentityProvider.InitContext context = newInitContext();
-
- context.redirectTo("/test");
-
- verify(response).sendRedirect("/test");
- }
-
- @Test
- public void create_callback() {
- when(server.getPublicRootUrl()).thenReturn(SECURED_PUBLIC_ROOT_URL);
-
- OAuth2IdentityProvider.CallbackContext callback = newCallbackContext();
-
- assertThat(callback.getRequest()).isEqualTo(request);
- assertThat(callback.getResponse()).isEqualTo(response);
- assertThat(callback.getCallbackUrl()).isEqualTo("https://mydomain.com/oauth2/callback/github");
- }
-
- @Test
- public void authenticate() {
- OAuth2IdentityProvider.CallbackContext callback = newCallbackContext();
-
- callback.authenticate(USER_IDENTITY);
-
- assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- verify(threadLocalUserSession).set(any(UserSession.class));
- ArgumentCaptor<UserDto> userArgumentCaptor = ArgumentCaptor.forClass(UserDto.class);
- verify(jwtHttpHandler).generateToken(userArgumentCaptor.capture(), eq(request), eq(response));
- assertThat(userArgumentCaptor.getValue().getLogin()).isEqualTo(USER_IDENTITY.getLogin());
- assertThat(userArgumentCaptor.getValue().getExternalId()).isEqualTo(USER_IDENTITY.getProviderId());
- assertThat(userArgumentCaptor.getValue().getExternalLogin()).isEqualTo(USER_IDENTITY.getProviderLogin());
- assertThat(userArgumentCaptor.getValue().getExternalIdentityProvider()).isEqualTo(PROVIDER_KEY);
- }
-
- @Test
- public void authenticate_with_allow_email_shift() {
- when(oAuthParameters.getAllowEmailShift(request)).thenReturn(Optional.of(true));
- OAuth2IdentityProvider.CallbackContext callback = newCallbackContext();
-
- callback.authenticate(USER_IDENTITY);
-
- assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getExistingEmailStrategy()).isEqualTo(ExistingEmailStrategy.ALLOW);
- }
-
- @Test
- public void authenticate_without_email_shift() {
- when(oAuthParameters.getAllowEmailShift(request)).thenReturn(Optional.of(false));
- OAuth2IdentityProvider.CallbackContext callback = newCallbackContext();
-
- callback.authenticate(USER_IDENTITY);
-
- assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getExistingEmailStrategy()).isEqualTo(ExistingEmailStrategy.WARN);
- }
-
- @Test
- public void authenticate_with_organization_alm_ids() {
- OAuthContextImpl callback = (OAuthContextImpl) newCallbackContext();
- Set<String> organizationAlmIds = ImmutableSet.of("ABCD", "EFGH");
-
- callback.authenticate(USER_IDENTITY, organizationAlmIds);
-
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getOrganizationAlmIds()).containsAll(organizationAlmIds);
- }
-
- @Test
- public void redirect_to_home() throws Exception {
- when(server.getContextPath()).thenReturn("");
- when(oAuthParameters.getReturnTo(request)).thenReturn(Optional.empty());
- OAuth2IdentityProvider.CallbackContext callback = newCallbackContext();
-
- callback.redirectToRequestedPage();
-
- verify(response).sendRedirect("/");
- }
-
- @Test
- public void redirect_to_home_with_context() throws Exception {
- when(server.getContextPath()).thenReturn("/sonarqube");
- when(oAuthParameters.getReturnTo(request)).thenReturn(Optional.empty());
- OAuth2IdentityProvider.CallbackContext callback = newCallbackContext();
-
- callback.redirectToRequestedPage();
-
- verify(response).sendRedirect("/sonarqube/");
- }
-
- @Test
- public void redirect_to_requested_page() throws Exception {
- when(oAuthParameters.getReturnTo(request)).thenReturn(Optional.of("/settings"));
- when(server.getContextPath()).thenReturn("");
- OAuth2IdentityProvider.CallbackContext callback = newCallbackContext();
-
- callback.redirectToRequestedPage();
-
- verify(response).sendRedirect("/settings");
- }
-
- @Test
- public void redirect_to_requested_page_does_not_need_context() throws Exception {
- when(oAuthParameters.getReturnTo(request)).thenReturn(Optional.of("/sonarqube/settings"));
- when(server.getContextPath()).thenReturn("/other");
- OAuth2IdentityProvider.CallbackContext callback = newCallbackContext();
-
- callback.redirectToRequestedPage();
-
- verify(response).sendRedirect("/sonarqube/settings");
- }
-
- @Test
- public void verify_csrf_state() {
- OAuth2IdentityProvider.CallbackContext callback = newCallbackContext();
-
- callback.verifyCsrfState();
-
- verify(csrfVerifier).verifyState(request, response, identityProvider);
- }
-
- @Test
- public void delete_oauth2_parameters_during_redirection() {
- when(oAuthParameters.getReturnTo(request)).thenReturn(Optional.of("/settings"));
- when(server.getContextPath()).thenReturn("");
- OAuth2IdentityProvider.CallbackContext callback = newCallbackContext();
-
- callback.redirectToRequestedPage();
-
- verify(oAuthParameters).delete(eq(request), eq(response));
- }
-
- private OAuth2IdentityProvider.InitContext newInitContext() {
- return underTest.newContext(request, response, identityProvider);
- }
-
- private OAuth2IdentityProvider.CallbackContext newCallbackContext() {
- return underTest.newCallback(request, response, identityProvider);
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuthCsrfVerifierTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuthCsrfVerifierTest.java
deleted file mode 100644
index d1165e1aea6..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/OAuthCsrfVerifierTest.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.platform.Server;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-
-import static org.apache.commons.codec.digest.DigestUtils.sha1Hex;
-import static org.apache.commons.codec.digest.DigestUtils.sha256Hex;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException;
-
-public class OAuthCsrfVerifierTest {
- private static final String PROVIDER_NAME = "provider name";
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private ArgumentCaptor<Cookie> cookieArgumentCaptor = ArgumentCaptor.forClass(Cookie.class);
-
- private OAuth2IdentityProvider identityProvider = mock(OAuth2IdentityProvider.class);
- private Server server = mock(Server.class);
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private HttpServletRequest request = mock(HttpServletRequest.class);
-
- private OAuthCsrfVerifier underTest = new OAuthCsrfVerifier();
-
- @Before
- public void setUp() throws Exception {
- when(server.getContextPath()).thenReturn("");
- when(identityProvider.getName()).thenReturn(PROVIDER_NAME);
- }
-
- @Test
- public void generate_state() {
- String state = underTest.generateState(request, response);
- assertThat(state).isNotEmpty();
-
- verify(response).addCookie(cookieArgumentCaptor.capture());
-
- verifyCookie(cookieArgumentCaptor.getValue());
- }
-
- @Test
- public void verify_state() {
- String state = "state";
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie("OAUTHSTATE", sha256Hex(state))});
- when(request.getParameter("aStateParameter")).thenReturn(state);
-
- underTest.verifyState(request, response, identityProvider, "aStateParameter");
-
- verify(response).addCookie(cookieArgumentCaptor.capture());
- Cookie updatedCookie = cookieArgumentCaptor.getValue();
- assertThat(updatedCookie.getName()).isEqualTo("OAUTHSTATE");
- assertThat(updatedCookie.getValue()).isNull();
- assertThat(updatedCookie.getPath()).isEqualTo("/");
- assertThat(updatedCookie.getMaxAge()).isEqualTo(0);
- }
-
- @Test
- public void verify_state_using_default_state_parameter() {
- String state = "state";
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie("OAUTHSTATE", sha256Hex(state))});
- when(request.getParameter("state")).thenReturn(state);
-
- underTest.verifyState(request, response, identityProvider);
-
- verify(response).addCookie(cookieArgumentCaptor.capture());
- Cookie updatedCookie = cookieArgumentCaptor.getValue();
- assertThat(updatedCookie.getName()).isEqualTo("OAUTHSTATE");
- assertThat(updatedCookie.getValue()).isNull();
- assertThat(updatedCookie.getPath()).isEqualTo("/");
- assertThat(updatedCookie.getMaxAge()).isEqualTo(0);
- }
-
- @Test
- public void fail_with_AuthenticationException_when_state_cookie_is_not_the_same_as_state_parameter() {
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie("OAUTHSTATE", sha1Hex("state"))});
- when(request.getParameter("state")).thenReturn("other value");
-
- thrown.expect(authenticationException().from(AuthenticationEvent.Source.oauth2(identityProvider)).withoutLogin().andNoPublicMessage());
- thrown.expectMessage("CSRF state value is invalid");
- underTest.verifyState(request, response, identityProvider);
- }
-
- @Test
- public void fail_with_AuthenticationException_when_state_cookie_is_null() {
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie("OAUTHSTATE", null)});
- when(request.getParameter("state")).thenReturn("state");
-
- thrown.expect(authenticationException().from(AuthenticationEvent.Source.oauth2(identityProvider)).withoutLogin().andNoPublicMessage());
- thrown.expectMessage("CSRF state value is invalid");
- underTest.verifyState(request, response, identityProvider);
- }
-
- @Test
- public void fail_with_AuthenticationException_when_state_parameter_is_empty() {
- when(request.getCookies()).thenReturn(new Cookie[] {new Cookie("OAUTHSTATE", sha1Hex("state"))});
- when(request.getParameter("state")).thenReturn("");
-
- thrown.expect(authenticationException().from(AuthenticationEvent.Source.oauth2(identityProvider)).withoutLogin().andNoPublicMessage());
- thrown.expectMessage("CSRF state value is invalid");
- underTest.verifyState(request, response, identityProvider);
- }
-
- @Test
- public void fail_with_AuthenticationException_when_cookie_is_missing() {
- when(request.getCookies()).thenReturn(new Cookie[] {});
-
- thrown.expect(authenticationException().from(AuthenticationEvent.Source.oauth2(identityProvider)).withoutLogin().andNoPublicMessage());
- thrown.expectMessage("Cookie 'OAUTHSTATE' is missing");
- underTest.verifyState(request, response, identityProvider);
- }
-
- private void verifyCookie(Cookie cookie) {
- assertThat(cookie.getName()).isEqualTo("OAUTHSTATE");
- assertThat(cookie.getValue()).isNotEmpty();
- assertThat(cookie.getPath()).isEqualTo("/");
- assertThat(cookie.isHttpOnly()).isTrue();
- assertThat(cookie.getMaxAge()).isEqualTo(-1);
- assertThat(cookie.getSecure()).isFalse();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/RequestAuthenticatorImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/RequestAuthenticatorImplTest.java
deleted file mode 100644
index be9a12754db..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/RequestAuthenticatorImplTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Optional;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.tester.AnonymousMockUserSession;
-import org.sonar.server.tester.MockUserSession;
-import org.sonar.server.user.UserSession;
-import org.sonar.server.user.UserSessionFactory;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.user.UserTesting.newUserDto;
-
-public class RequestAuthenticatorImplTest {
-
- private static final UserDto A_USER = newUserDto();
-
- private HttpServletRequest request = mock(HttpServletRequest.class);
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class);
- private BasicAuthentication basicAuthentication = mock(BasicAuthentication.class);
- private HttpHeadersAuthentication httpHeadersAuthentication = mock(HttpHeadersAuthentication.class);
- private UserSessionFactory sessionFactory = mock(UserSessionFactory.class);
- private CustomAuthentication customAuthentication1 = mock(CustomAuthentication.class);
- private CustomAuthentication customAuthentication2 = mock(CustomAuthentication.class);
- private RequestAuthenticator underTest = new RequestAuthenticatorImpl(jwtHttpHandler, basicAuthentication, httpHeadersAuthentication, sessionFactory,
- new CustomAuthentication[]{customAuthentication1, customAuthentication2});
-
- @Before
- public void setUp() throws Exception {
- when(sessionFactory.create(A_USER)).thenReturn(new MockUserSession(A_USER));
- when(sessionFactory.createAnonymous()).thenReturn(new AnonymousMockUserSession());
- }
-
- @Test
- public void authenticate_from_jwt_token() {
- when(httpHeadersAuthentication.authenticate(request, response)).thenReturn(Optional.empty());
- when(jwtHttpHandler.validateToken(request, response)).thenReturn(Optional.of(A_USER));
-
- assertThat(underTest.authenticate(request, response).getUuid()).isEqualTo(A_USER.getUuid());
- verify(response, never()).setStatus(anyInt());
- }
-
- @Test
- public void authenticate_from_basic_header() {
- when(basicAuthentication.authenticate(request)).thenReturn(Optional.of(A_USER));
- when(httpHeadersAuthentication.authenticate(request, response)).thenReturn(Optional.empty());
- when(jwtHttpHandler.validateToken(request, response)).thenReturn(Optional.empty());
-
- assertThat(underTest.authenticate(request, response).getUuid()).isEqualTo(A_USER.getUuid());
-
- verify(jwtHttpHandler).validateToken(request, response);
- verify(basicAuthentication).authenticate(request);
- verify(response, never()).setStatus(anyInt());
- }
-
- @Test
- public void authenticate_from_sso() {
- when(httpHeadersAuthentication.authenticate(request, response)).thenReturn(Optional.of(A_USER));
- when(jwtHttpHandler.validateToken(request, response)).thenReturn(Optional.empty());
-
- assertThat(underTest.authenticate(request, response).getUuid()).isEqualTo(A_USER.getUuid());
-
- verify(httpHeadersAuthentication).authenticate(request, response);
- verify(jwtHttpHandler, never()).validateToken(request, response);
- verify(response, never()).setStatus(anyInt());
- }
-
- @Test
- public void return_empty_if_not_authenticated() {
- when(jwtHttpHandler.validateToken(request, response)).thenReturn(Optional.empty());
- when(httpHeadersAuthentication.authenticate(request, response)).thenReturn(Optional.empty());
- when(basicAuthentication.authenticate(request)).thenReturn(Optional.empty());
-
- UserSession session = underTest.authenticate(request, response);
- assertThat(session.isLoggedIn()).isFalse();
- assertThat(session.getUuid()).isNull();
- verify(response, never()).setStatus(anyInt());
- }
-
- @Test
- public void delegate_to_CustomAuthentication() {
- when(customAuthentication1.authenticate(request, response)).thenReturn(Optional.of(new MockUserSession("foo")));
-
- UserSession session = underTest.authenticate(request, response);
-
- assertThat(session.getLogin()).isEqualTo("foo");
- }
-
- @Test
- public void CustomAuthentication_has_priority_over_core_authentications() {
- // use-case: both custom and core authentications check the HTTP header "Authorization".
- // The custom authentication should be able to test the header because that the core authentication
- // throws an exception.
- when(customAuthentication1.authenticate(request, response)).thenReturn(Optional.of(new MockUserSession("foo")));
- when(basicAuthentication.authenticate(request)).thenThrow(AuthenticationException.newBuilder()
- .setSource(AuthenticationEvent.Source.sso())
- .setMessage("message")
- .build());
-
- UserSession session = underTest.authenticate(request, response);
-
- assertThat(session.getLogin()).isEqualTo("foo");
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/SafeModeUserSessionTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/SafeModeUserSessionTest.java
deleted file mode 100644
index 9ba9f5c6f62..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/SafeModeUserSessionTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.junit.Test;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.permission.OrganizationPermission;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;
-
-public class SafeModeUserSessionTest {
-
- private SafeModeUserSession underTest = new SafeModeUserSession();
-
- @Test
- public void session_is_anonymous() {
- assertThat(underTest.getLogin()).isNull();
- assertThat(underTest.getUuid()).isNull();
- assertThat(underTest.isLoggedIn()).isFalse();
- assertThat(underTest.getName()).isNull();
- assertThat(underTest.getUserId()).isNull();
- assertThat(underTest.getGroups()).isEmpty();
- }
-
- @Test
- public void session_has_no_permissions() {
- assertThat(underTest.isRoot()).isFalse();
- assertThat(underTest.isSystemAdministrator()).isFalse();
- assertThat(underTest.hasPermissionImpl(OrganizationPermission.ADMINISTER, "foo")).isFalse();
- assertThat(underTest.hasProjectUuidPermission(UserRole.USER, "foo")).isFalse();
- assertThat(underTest.hasMembership(newOrganizationDto())).isFalse();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/TestIdentityProvider.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/TestIdentityProvider.java
deleted file mode 100644
index fdc950b673c..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/TestIdentityProvider.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.sonar.api.server.authentication.Display;
-import org.sonar.api.server.authentication.IdentityProvider;
-
-public class TestIdentityProvider implements IdentityProvider {
-
- private String key;
- private String name;
- private Display display;
- private boolean enabled;
- private boolean allowsUsersToSignUp;
-
- @Override
- public String getKey() {
- return key;
- }
-
- public TestIdentityProvider setKey(String key) {
- this.key = key;
- return this;
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- public TestIdentityProvider setName(String name) {
- this.name = name;
- return this;
- }
-
- @Override
- public Display getDisplay() {
- return display;
- }
-
- public TestIdentityProvider setDisplay(Display display) {
- this.display = display;
- return this;
- }
-
- @Override
- public boolean isEnabled() {
- return enabled;
- }
-
- public TestIdentityProvider setEnabled(boolean enabled) {
- this.enabled = enabled;
- return this;
- }
-
- @Override
- public boolean allowsUsersToSignUp() {
- return allowsUsersToSignUp;
- }
-
- public TestIdentityProvider setAllowsUsersToSignUp(boolean allowsUsersToSignUp) {
- this.allowsUsersToSignUp = allowsUsersToSignUp;
- return this;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (getClass() != o.getClass()) {
- return false;
- }
-
- TestIdentityProvider that = (TestIdentityProvider) o;
- return key.equals(that.key);
- }
-
- @Override
- public int hashCode() {
- return key.hashCode();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/TestUserRegistrar.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/TestUserRegistrar.java
deleted file mode 100644
index 4244c842138..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/TestUserRegistrar.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTesting;
-
-public class TestUserRegistrar implements UserRegistrar {
-
- private UserRegistration authenticatorParameters;
-
- @Override
- public UserDto register(UserRegistration registration) {
- this.authenticatorParameters = registration;
- String providerId = registration.getUserIdentity().getProviderId();
- return UserTesting.newUserDto()
- .setLocal(false)
- .setLogin(registration.getUserIdentity().getLogin())
- .setExternalLogin(registration.getUserIdentity().getProviderLogin())
- .setExternalId(providerId == null ? registration.getUserIdentity().getProviderLogin() : providerId)
- .setExternalIdentityProvider(registration.getProvider().getKey());
- }
-
- boolean isAuthenticated() {
- return authenticatorParameters != null;
- }
-
- UserRegistration getAuthenticatorParameters() {
- return authenticatorParameters;
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserLastConnectionDatesUpdaterImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/UserLastConnectionDatesUpdaterImplTest.java
deleted file mode 100644
index f20e6c6bdf0..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserLastConnectionDatesUpdaterImplTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.authentication;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.api.impl.utils.TestSystem2;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTokenDto;
-
-import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
-
-public class UserLastConnectionDatesUpdaterImplTest {
-
- private static final long NOW = 10_000_000_000L;
- private static final long ONE_MINUTE = 60_000L;
- private static final long ONE_HOUR = ONE_MINUTE * 60L;
- private static final long TWO_HOUR = ONE_HOUR * 2L;
-
- @Rule
- public DbTester db = DbTester.create();
-
- private System2 system2 = new TestSystem2().setNow(NOW);
-
- private UserLastConnectionDatesUpdaterImpl underTest = new UserLastConnectionDatesUpdaterImpl(db.getDbClient(), system2);
-
- @Test
- public void update_last_connection_date_from_user_when_last_connection_was_more_than_one_hour() {
- UserDto user = db.users().insertUser();
- db.users().updateLastConnectionDate(user, NOW - TWO_HOUR);
-
- underTest.updateLastConnectionDateIfNeeded(user);
-
- UserDto userReloaded = db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid());
- assertThat(userReloaded.getLastConnectionDate()).isEqualTo(NOW);
- }
-
- @Test
- public void update_last_connection_date_from_user_when_no_last_connection_date() {
- UserDto user = db.users().insertUser();
-
- underTest.updateLastConnectionDateIfNeeded(user);
-
- UserDto userReloaded = db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid());
- assertThat(userReloaded.getLastConnectionDate()).isEqualTo(NOW);
- }
-
- @Test
- public void do_not_update_when_last_connection_from_user_was_less_than_one_hour() {
- UserDto user = db.users().insertUser();
- db.users().updateLastConnectionDate(user, NOW - ONE_MINUTE);
-
- underTest.updateLastConnectionDateIfNeeded(user);
-
- UserDto userReloaded = db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid());
- assertThat(userReloaded.getLastConnectionDate()).isEqualTo(NOW - ONE_MINUTE);
- }
-
- @Test
- public void update_last_connection_date_from_user_token_when_last_connection_was_more_than_one_hour() {
- UserDto user = db.users().insertUser();
- UserTokenDto userToken = db.users().insertToken(user);
- db.getDbClient().userTokenDao().update(db.getSession(), userToken.setLastConnectionDate(NOW - TWO_HOUR));
- db.commit();
-
- underTest.updateLastConnectionDateIfNeeded(userToken);
-
- UserTokenDto userTokenReloaded = db.getDbClient().userTokenDao().selectByTokenHash(db.getSession(), userToken.getTokenHash());
- assertThat(userTokenReloaded.getLastConnectionDate()).isEqualTo(NOW);
- }
-
- @Test
- public void update_last_connection_date_from_user_token_when_no_last_connection_date() {
- UserDto user = db.users().insertUser();
- UserTokenDto userToken = db.users().insertToken(user);
-
- underTest.updateLastConnectionDateIfNeeded(userToken);
-
- UserTokenDto userTokenReloaded = db.getDbClient().userTokenDao().selectByTokenHash(db.getSession(), userToken.getTokenHash());
- assertThat(userTokenReloaded.getLastConnectionDate()).isEqualTo(NOW);
- }
-
- @Test
- public void do_not_update_when_last_connection_from_user_token_was_less_than_one_hour() {
- UserDto user = db.users().insertUser();
- UserTokenDto userToken = db.users().insertToken(user);
- db.getDbClient().userTokenDao().update(db.getSession(), userToken.setLastConnectionDate(NOW - ONE_MINUTE));
- db.commit();
-
- underTest.updateLastConnectionDateIfNeeded(userToken);
-
- UserTokenDto userTokenReloaded = db.getDbClient().userTokenDao().selectByTokenHash(db.getSession(), userToken.getTokenHash());
- assertThat(userTokenReloaded.getLastConnectionDate()).isEqualTo(NOW - ONE_MINUTE);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserRegistrarImplOrgMembershipSyncTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/UserRegistrarImplOrgMembershipSyncTest.java
deleted file mode 100644
index c43fdb7f616..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserRegistrarImplOrgMembershipSyncTest.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import com.google.common.collect.ImmutableSet;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbTester;
-import org.sonar.db.alm.AlmAppInstallDto;
-import org.sonar.db.component.ResourceTypesRule;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.organization.MemberUpdater;
-import org.sonar.server.organization.OrganizationUpdater;
-import org.sonar.server.organization.TestDefaultOrganizationProvider;
-import org.sonar.server.organization.TestOrganizationFlags;
-import org.sonar.server.permission.PermissionService;
-import org.sonar.server.permission.PermissionServiceImpl;
-import org.sonar.server.user.NewUserNotifier;
-import org.sonar.server.user.UserUpdater;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static org.mockito.Mockito.mock;
-import static org.sonar.db.alm.ALM.BITBUCKETCLOUD;
-import static org.sonar.db.alm.ALM.GITHUB;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC;
-
-public class UserRegistrarImplOrgMembershipSyncTest {
-
- private System2 system2 = new AlwaysIncreasingSystem2();
-
- private static String USER_LOGIN = "github-johndoo";
-
- private static UserIdentity USER_IDENTITY = UserIdentity.builder()
- .setProviderId("ABCD")
- .setProviderLogin("johndoo")
- .setLogin(USER_LOGIN)
- .setName("John")
- .setEmail("john@email.com")
- .build();
-
- private static TestIdentityProvider GITHUB_PROVIDER = new TestIdentityProvider()
- .setKey("github")
- .setName("Github")
- .setEnabled(true)
- .setAllowsUsersToSignUp(true);
-
- private static TestIdentityProvider BITBUCKET_PROVIDER = new TestIdentityProvider()
- .setKey("bitbucket")
- .setName("Bitbucket")
- .setEnabled(true)
- .setAllowsUsersToSignUp(true);
-
- private MapSettings settings = new MapSettings();
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- @Rule
- public DbTester db = DbTester.create(new AlwaysIncreasingSystem2());
- @Rule
- public EsTester es = EsTester.create();
- private UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client());
- private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- private OrganizationUpdater organizationUpdater = mock(OrganizationUpdater.class);
- private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
- private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient());
- private UserUpdater userUpdater = new UserUpdater(
- system2,
- mock(NewUserNotifier.class),
- db.getDbClient(),
- userIndexer,
- organizationFlags,
- defaultOrganizationProvider,
- new DefaultGroupFinder(db.getDbClient()),
- settings.asConfig(),
- localAuthentication);
-
- private ResourceTypes resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT);
- private PermissionService permissionService = new PermissionServiceImpl(resourceTypes);
- private DefaultGroupFinder defaultGroupFinder = new DefaultGroupFinder(db.getDbClient());
-
- private UserRegistrarImpl underTest = new UserRegistrarImpl(db.getDbClient(), userUpdater, defaultOrganizationProvider, organizationFlags,
- defaultGroupFinder, new MemberUpdater(db.getDbClient(), defaultGroupFinder, userIndexer));
-
- @Test
- public void authenticate_new_github_user_syncs_organization() {
- organizationFlags.setEnabled(true);
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- AlmAppInstallDto gitHubInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization, gitHubInstall, true);
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(GITHUB_PROVIDER)
- .setSource(Source.realm(BASIC, GITHUB_PROVIDER.getName()))
- .setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
- .setOrganizationAlmIds(ImmutableSet.of(gitHubInstall.getOrganizationAlmId()))
- .build());
-
- UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
- db.organizations().assertUserIsMemberOfOrganization(organization, user);
- }
-
- @Test
- public void authenticate_new_github_user_does_not_sync_organization_when_no_org_alm_ids_provided() {
- organizationFlags.setEnabled(true);
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- AlmAppInstallDto gitHubInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization, gitHubInstall, true);
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(GITHUB_PROVIDER)
- .setSource(Source.realm(BASIC, GITHUB_PROVIDER.getName()))
- .setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
- .setOrganizationAlmIds(null)
- .build());
-
- UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
- db.organizations().assertUserIsNotMemberOfOrganization(organization, user);
- }
-
- @Test
- public void authenticate_new_bitbucket_user_does_not_sync_organization() {
- organizationFlags.setEnabled(true);
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- AlmAppInstallDto gitHubInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(BITBUCKETCLOUD));
- db.alm().insertOrganizationAlmBinding(organization, gitHubInstall, true);
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(BITBUCKET_PROVIDER)
- .setSource(Source.realm(BASIC, BITBUCKET_PROVIDER.getName()))
- .setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
- .setOrganizationAlmIds(ImmutableSet.of(gitHubInstall.getOrganizationAlmId()))
- .build());
-
- UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
- db.organizations().assertUserIsNotMemberOfOrganization(organization, user);
- }
-
- @Test
- public void authenticate_new_user_using_unknown_alm_does_not_sync_organization() {
- organizationFlags.setEnabled(true);
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- AlmAppInstallDto almAppInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization, almAppInstall, true);
- TestIdentityProvider identityProvider = new TestIdentityProvider()
- .setKey("unknown")
- .setName("unknown")
- .setEnabled(true)
- .setAllowsUsersToSignUp(true);
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(identityProvider)
- .setSource(Source.realm(BASIC, identityProvider.getName()))
- .setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
- .setOrganizationAlmIds(ImmutableSet.of(almAppInstall.getOrganizationAlmId()))
- .build());
-
- UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
- db.organizations().assertUserIsNotMemberOfOrganization(organization, user);
- }
-
- @Test
- public void authenticate_existing_github_user_does_not_sync_organization() {
- organizationFlags.setEnabled(true);
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- AlmAppInstallDto gitHubInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization, gitHubInstall, true);
- UserDto user = db.users().insertUser(u -> u
- .setLogin("Old login")
- .setExternalId(USER_IDENTITY.getProviderId())
- .setExternalIdentityProvider(GITHUB_PROVIDER.getKey()));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(GITHUB_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .setOrganizationAlmIds(ImmutableSet.of(gitHubInstall.getOrganizationAlmId()))
- .build());
-
- db.organizations().assertUserIsNotMemberOfOrganization(organization, user);
- }
-
- @Test
- public void authenticate_disabled_github_user_syncs_organization() {
- organizationFlags.setEnabled(true);
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- AlmAppInstallDto gitHubInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization, gitHubInstall, true);
- UserDto user = db.users().insertDisabledUser(u -> u.setLogin(USER_LOGIN));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(GITHUB_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .setOrganizationAlmIds(ImmutableSet.of(gitHubInstall.getOrganizationAlmId()))
- .build());
-
- db.organizations().assertUserIsMemberOfOrganization(organization, user);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java
deleted file mode 100644
index 4673a5fce22..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java
+++ /dev/null
@@ -1,791 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Optional;
-import java.util.stream.Collectors;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
-import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbTester;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.authentication.exception.EmailAlreadyExistsRedirectionException;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.organization.MemberUpdater;
-import org.sonar.server.organization.OrganizationUpdater;
-import org.sonar.server.organization.TestDefaultOrganizationProvider;
-import org.sonar.server.organization.TestOrganizationFlags;
-import org.sonar.server.user.NewUserNotifier;
-import org.sonar.server.user.UserUpdater;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static com.google.common.collect.Sets.newHashSet;
-import static java.util.Arrays.stream;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.process.ProcessProperties.Property.ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS;
-import static org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy.FORBID;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC;
-import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException;
-
-public class UserRegistrarImplTest {
-
- private System2 system2 = new AlwaysIncreasingSystem2();
-
- private static String USER_LOGIN = "github-johndoo";
-
- private static UserIdentity USER_IDENTITY = UserIdentity.builder()
- .setProviderId("ABCD")
- .setProviderLogin("johndoo")
- .setLogin(USER_LOGIN)
- .setName("John")
- .setEmail("john@email.com")
- .build();
-
- private static TestIdentityProvider IDENTITY_PROVIDER = new TestIdentityProvider()
- .setKey("github")
- .setName("name of github")
- .setEnabled(true)
- .setAllowsUsersToSignUp(true);
-
- private MapSettings settings = new MapSettings();
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- @Rule
- public DbTester db = DbTester.create(new AlwaysIncreasingSystem2());
- @Rule
- public EsTester es = EsTester.create();
- private UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client());
- private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- private OrganizationUpdater organizationUpdater = mock(OrganizationUpdater.class);
- private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
- private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient());
- private UserUpdater userUpdater = new UserUpdater(
- system2,
- mock(NewUserNotifier.class),
- db.getDbClient(),
- userIndexer,
- organizationFlags,
- defaultOrganizationProvider,
- new DefaultGroupFinder(db.getDbClient()),
- settings.asConfig(),
- localAuthentication);
-
- private DefaultGroupFinder defaultGroupFinder = new DefaultGroupFinder(db.getDbClient());
-
- private UserRegistrarImpl underTest = new UserRegistrarImpl(db.getDbClient(), userUpdater, defaultOrganizationProvider, organizationFlags,
- defaultGroupFinder, new MemberUpdater(db.getDbClient(), defaultGroupFinder, userIndexer));
-
- @Test
- public void authenticate_new_user() {
- organizationFlags.setEnabled(true);
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.realm(BASIC, IDENTITY_PROVIDER.getName()))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
- assertThat(user).isNotNull();
- assertThat(user.isActive()).isTrue();
- assertThat(user.getName()).isEqualTo("John");
- assertThat(user.getEmail()).isEqualTo("john@email.com");
- assertThat(user.getExternalLogin()).isEqualTo("johndoo");
- assertThat(user.getExternalIdentityProvider()).isEqualTo("github");
- assertThat(user.getExternalId()).isEqualTo("ABCD");
- assertThat(user.isRoot()).isFalse();
- checkGroupMembership(user);
- }
-
- @Test
- public void authenticate_new_user_generate_login_when_no_login_provided() {
- organizationFlags.setEnabled(true);
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(UserIdentity.builder()
- .setProviderId("ABCD")
- .setProviderLogin("johndoo")
- .setName("John Doe")
- .setEmail("john@email.com")
- .build())
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.realm(BASIC, IDENTITY_PROVIDER.getName()))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- UserDto user = db.getDbClient().userDao().selectByEmail(db.getSession(), "john@email.com").get(0);
- assertThat(user).isNotNull();
- assertThat(user.isActive()).isTrue();
- assertThat(user.getLogin()).isNotEqualTo("John Doe").startsWith("john-doe");
- assertThat(user.getEmail()).isEqualTo("john@email.com");
- assertThat(user.getExternalLogin()).isEqualTo("johndoo");
- assertThat(user.getExternalIdentityProvider()).isEqualTo("github");
- assertThat(user.getExternalId()).isEqualTo("ABCD");
- }
-
- @Test
- public void authenticate_new_user_with_groups() {
- organizationFlags.setEnabled(true);
- GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
- GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
-
- authenticate(USER_LOGIN, "group1", "group2", "group3");
-
- Optional<UserDto> user = db.users().selectUserByLogin(USER_LOGIN);
- checkGroupMembership(user.get(), group1, group2);
- }
-
- @Test
- public void authenticate_new_user_and_force_default_group_when_organizations_are_disabled() {
- organizationFlags.setEnabled(false);
- UserDto user = db.users().insertUser();
- GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
- GroupDto defaultGroup = insertDefaultGroup();
- db.users().insertMember(group1, user);
- db.users().insertMember(defaultGroup, user);
-
- authenticate(user.getLogin(), "group1");
-
- checkGroupMembership(user, group1, defaultGroup);
- }
-
- @Test
- public void does_not_force_default_group_when_authenticating_new_user_if_organizations_are_enabled() {
- organizationFlags.setEnabled(true);
- UserDto user = db.users().insertUser();
- GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
- GroupDto defaultGroup = insertDefaultGroup();
- db.users().insertMember(group1, user);
- db.users().insertMember(defaultGroup, user);
-
- authenticate(user.getLogin(), "group1");
-
- checkGroupMembership(user, group1);
- }
-
- @Test
- public void authenticate_new_user_sets_onboarded_flag_to_false_when_onboarding_setting_is_set_to_true() {
- organizationFlags.setEnabled(true);
- settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey(), true);
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- assertThat(db.users().selectUserByLogin(USER_LOGIN).get().isOnboarded()).isFalse();
- }
-
- @Test
- public void authenticate_new_user_sets_onboarded_flag_to_true_when_onboarding_setting_is_set_to_false() {
- organizationFlags.setEnabled(true);
- settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey(), false);
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- assertThat(db.users().selectUserByLogin(USER_LOGIN).get().isOnboarded()).isTrue();
- }
-
- @Test
- public void external_id_is_set_to_provider_login_when_null() {
- organizationFlags.setEnabled(true);
- UserIdentity newUser = UserIdentity.builder()
- .setProviderId(null)
- .setLogin("john")
- .setProviderLogin("johndoo")
- .setName("JOhn")
- .build();
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(newUser)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- assertThat(db.users().selectUserByLogin(newUser.getLogin()).get())
- .extracting(UserDto::getLogin, UserDto::getExternalId, UserDto::getExternalLogin)
- .contains("john", "johndoo", "johndoo");
- }
-
- @Test
- public void authenticate_new_user_update_existing_user_email_when_strategy_is_ALLOW() {
- organizationFlags.setEnabled(true);
- UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
- UserIdentity newUser = UserIdentity.builder()
- .setProviderLogin("johndoo")
- .setLogin("new_login")
- .setName(existingUser.getName())
- .setEmail(existingUser.getEmail())
- .build();
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(newUser)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
- .build());
-
- UserDto newUserReloaded = db.users().selectUserByLogin(newUser.getLogin()).get();
- assertThat(newUserReloaded.getEmail()).isEqualTo(existingUser.getEmail());
- UserDto existingUserReloaded = db.users().selectUserByLogin(existingUser.getLogin()).get();
- assertThat(existingUserReloaded.getEmail()).isNull();
- }
-
- @Test
- public void throw_EmailAlreadyExistException_when_authenticating_new_user_when_email_already_exists_and_strategy_is_WARN() {
- organizationFlags.setEnabled(true);
- UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
- UserIdentity newUser = UserIdentity.builder()
- .setProviderLogin("johndoo")
- .setLogin("new_login")
- .setName(existingUser.getName())
- .setEmail(existingUser.getEmail())
- .build();
-
- expectedException.expect(EmailAlreadyExistsRedirectionException.class);
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(newUser)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.WARN)
- .build());
- }
-
- @Test
- public void throw_AuthenticationException_when_authenticating_new_user_when_email_already_exists_and_strategy_is_FORBID() {
- db.users().insertUser(u -> u.setEmail("john@email.com"));
- Source source = Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName());
-
- expectedException.expect(authenticationException().from(source)
- .withLogin(USER_IDENTITY.getProviderLogin())
- .andPublicMessage("You can't sign up because email 'john@email.com' is already used by an existing user. " +
- "This means that you probably already registered with another account."));
- expectedException.expectMessage("Email 'john@email.com' is already used");
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(source)
- .setExistingEmailStrategy(FORBID)
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
- }
-
- @Test
- public void throw_AuthenticationException_when_authenticating_new_user_and_email_already_exists_multiple_times() {
- db.users().insertUser(u -> u.setEmail("john@email.com"));
- db.users().insertUser(u -> u.setEmail("john@email.com"));
- Source source = Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName());
-
- expectedException.expect(authenticationException().from(source)
- .withLogin(USER_IDENTITY.getProviderLogin())
- .andPublicMessage("You can't sign up because email 'john@email.com' is already used by an existing user. " +
- "This means that you probably already registered with another account."));
- expectedException.expectMessage("Email 'john@email.com' is already used");
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(source)
- .setExistingEmailStrategy(FORBID)
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
- }
-
- @Test
- public void fail_to_authenticate_new_user_when_allow_users_to_signup_is_false() {
- TestIdentityProvider identityProvider = new TestIdentityProvider()
- .setKey("github")
- .setName("Github")
- .setEnabled(true)
- .setAllowsUsersToSignUp(false);
- Source source = Source.realm(AuthenticationEvent.Method.FORM, identityProvider.getName());
-
- expectedException.expect(authenticationException().from(source).withLogin(USER_IDENTITY.getProviderLogin()).andPublicMessage("'github' users are not allowed to sign up"));
- expectedException.expectMessage("User signup disabled for provider 'github'");
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(identityProvider)
- .setSource(source)
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
- }
-
- @Test
- public void authenticate_and_update_existing_user_matching_login() {
- db.users().insertUser(u -> u
- .setLogin(USER_LOGIN)
- .setName("Old name")
- .setEmail("Old email")
- .setExternalId("old id")
- .setExternalLogin("old identity")
- .setExternalIdentityProvider("old provide"));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- assertThat(db.users().selectUserByLogin(USER_LOGIN).get())
- .extracting(UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider, UserDto::isActive)
- .contains("John", "john@email.com", "ABCD", "johndoo", "github", true);
- }
-
- @Test
- public void authenticate_and_update_existing_user_matching_external_id() {
- UserDto user = db.users().insertUser(u -> u
- .setLogin("Old login")
- .setName("Old name")
- .setEmail("Old email")
- .setExternalId(USER_IDENTITY.getProviderId())
- .setExternalLogin("old identity")
- .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
- assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
- .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
- UserDto::isActive)
- .contains(USER_LOGIN, "John", "john@email.com", "ABCD", "johndoo", "github", true);
- }
-
- @Test
- public void authenticate_and_update_existing_user_matching_external_login() {
- UserDto user = db.users().insertUser(u -> u
- .setLogin("Old login")
- .setName("Old name")
- .setEmail(USER_IDENTITY.getEmail())
- .setExternalId("Old id")
- .setExternalLogin(USER_IDENTITY.getProviderLogin())
- .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
- assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
- .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
- UserDto::isActive)
- .contains(USER_LOGIN, "John", "john@email.com", "ABCD", "johndoo", "github", true);
- }
-
- @Test
- public void authenticate_existing_user_and_update_only_login() {
- UserDto user = db.users().insertUser(u -> u
- .setLogin("old login")
- .setName(USER_IDENTITY.getName())
- .setEmail(USER_IDENTITY.getEmail())
- .setExternalId(USER_IDENTITY.getProviderId())
- .setExternalLogin("old identity")
- .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
- assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
- .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
- UserDto::isActive)
- .containsExactlyInAnyOrder(USER_LOGIN, USER_IDENTITY.getName(), USER_IDENTITY.getEmail(), USER_IDENTITY.getProviderId(), USER_IDENTITY.getProviderLogin(),
- IDENTITY_PROVIDER.getKey(),
- true);
- }
-
- @Test
- public void authenticate_existing_user_and_update_only_identity_provider_key() {
- UserDto user = db.users().insertUser(u -> u
- .setLogin(USER_LOGIN)
- .setName(USER_IDENTITY.getName())
- .setEmail(USER_IDENTITY.getEmail())
- .setExternalId(USER_IDENTITY.getProviderId())
- .setExternalLogin(USER_IDENTITY.getProviderLogin())
- .setExternalIdentityProvider("old identity provider"));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
- .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
- UserDto::isActive)
- .containsExactlyInAnyOrder(USER_LOGIN, USER_IDENTITY.getName(), USER_IDENTITY.getEmail(), USER_IDENTITY.getProviderId(), USER_IDENTITY.getProviderLogin(),
- IDENTITY_PROVIDER.getKey(),
- true);
- }
-
- @Test
- public void authenticate_existing_user_matching_login_when_external_id_is_null() {
- UserDto user = db.users().insertUser(u -> u
- .setLogin(USER_LOGIN)
- .setName("Old name")
- .setEmail("Old email")
- .setExternalId("Old id")
- .setExternalLogin("old identity")
- .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(UserIdentity.builder()
- .setProviderId(null)
- .setProviderLogin("johndoo")
- .setLogin(USER_LOGIN)
- .setName("John")
- .setEmail("john@email.com")
- .build())
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
- .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
- UserDto::isActive)
- .contains(user.getLogin(), "John", "john@email.com", "johndoo", "johndoo", "github", true);
- }
-
- @Test
- public void authenticate_existing_user_when_login_is_not_provided() {
- UserDto user = db.users().insertUser(u -> u.setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(UserIdentity.builder()
- .setProviderId(user.getExternalId())
- .setProviderLogin(user.getExternalLogin())
- // No login provided
- .setName(user.getName())
- .setEmail(user.getEmail())
- .build())
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- // No new user is created
- assertThat(db.countRowsOfTable(db.getSession(), "users")).isEqualTo(1);
- assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
- .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
- UserDto::isActive)
- .contains(user.getLogin(), user.getName(), user.getEmail(), user.getExternalId(), user.getExternalLogin(), user.getExternalIdentityProvider(), true);
- }
-
- @Test
- public void authenticate_existing_user_with_login_update_and_strategy_is_ALLOW() {
- UserDto user = db.users().insertUser(u -> u
- .setLogin("Old login")
- .setExternalId(USER_IDENTITY.getProviderId())
- .setExternalLogin("old identity")
- .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
- .extracting(UserDto::getLogin, UserDto::getExternalLogin)
- .contains(USER_LOGIN, USER_IDENTITY.getProviderLogin());
- }
-
- @Test
- public void authenticate_existing_disabled_user() {
- organizationFlags.setEnabled(true);
- db.users().insertUser(u -> u
- .setLogin(USER_LOGIN)
- .setActive(false)
- .setName("Old name")
- .setEmail("Old email")
- .setExternalId("old id")
- .setExternalLogin("old identity")
- .setExternalIdentityProvider("old provide"));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- UserDto userDto = db.users().selectUserByLogin(USER_LOGIN).get();
- assertThat(userDto.isActive()).isTrue();
- assertThat(userDto.getName()).isEqualTo("John");
- assertThat(userDto.getEmail()).isEqualTo("john@email.com");
- assertThat(userDto.getExternalId()).isEqualTo("ABCD");
- assertThat(userDto.getExternalLogin()).isEqualTo("johndoo");
- assertThat(userDto.getExternalIdentityProvider()).isEqualTo("github");
- assertThat(userDto.isRoot()).isFalse();
- }
-
- @Test
- public void authenticate_existing_user_when_email_already_exists_and_strategy_is_ALLOW() {
- organizationFlags.setEnabled(true);
- UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
- UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
- UserIdentity userIdentity = UserIdentity.builder()
- .setLogin(currentUser.getLogin())
- .setProviderLogin("johndoo")
- .setName("John")
- .setEmail("john@email.com")
- .build();
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(userIdentity)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
- .build());
-
- UserDto currentUserReloaded = db.users().selectUserByLogin(currentUser.getLogin()).get();
- assertThat(currentUserReloaded.getEmail()).isEqualTo("john@email.com");
- UserDto existingUserReloaded = db.users().selectUserByLogin(existingUser.getLogin()).get();
- assertThat(existingUserReloaded.getEmail()).isNull();
- }
-
- @Test
- public void throw_EmailAlreadyExistException_when_authenticating_existing_user_when_email_already_exists_and_strategy_is_WARN() {
- organizationFlags.setEnabled(true);
- UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
- UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
- UserIdentity userIdentity = UserIdentity.builder()
- .setLogin(currentUser.getLogin())
- .setProviderLogin("johndoo")
- .setName("John")
- .setEmail("john@email.com")
- .build();
-
- expectedException.expect(EmailAlreadyExistsRedirectionException.class);
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(userIdentity)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.WARN)
- .build());
- }
-
- @Test
- public void throw_AuthenticationException_when_authenticating_existing_user_when_email_already_exists_and_strategy_is_FORBID() {
- organizationFlags.setEnabled(true);
- UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
- UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
- UserIdentity userIdentity = UserIdentity.builder()
- .setLogin(currentUser.getLogin())
- .setProviderLogin("johndoo")
- .setName("John")
- .setEmail("john@email.com")
- .build();
-
- expectedException.expect(authenticationException().from(Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName()))
- .withLogin(userIdentity.getProviderLogin())
- .andPublicMessage("You can't sign up because email 'john@email.com' is already used by an existing user. " +
- "This means that you probably already registered with another account."));
- expectedException.expectMessage("Email 'john@email.com' is already used");
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(userIdentity)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName()))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
- }
-
- @Test
- public void does_not_fail_to_authenticate_user_when_email_has_not_changed_and_strategy_is_FORBID() {
- organizationFlags.setEnabled(true);
- UserDto currentUser = db.users().insertUser(u -> u.setEmail("john@email.com")
- .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
- UserIdentity userIdentity = UserIdentity.builder()
- .setLogin(currentUser.getLogin())
- .setProviderId(currentUser.getExternalId())
- .setProviderLogin(currentUser.getExternalLogin())
- .setName("John")
- .setEmail("john@email.com")
- .build();
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(userIdentity)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- UserDto currentUserReloaded = db.users().selectUserByLogin(currentUser.getLogin()).get();
- assertThat(currentUserReloaded.getEmail()).isEqualTo("john@email.com");
- }
-
- @Test
- public void authenticate_existing_user_and_add_new_groups() {
- organizationFlags.setEnabled(true);
- UserDto user = db.users().insertUser(newUserDto()
- .setLogin(USER_LOGIN)
- .setActive(true)
- .setName("John"));
- GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
- GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
-
- authenticate(USER_LOGIN, "group1", "group2", "group3");
-
- checkGroupMembership(user, group1, group2);
- }
-
- @Test
- public void authenticate_existing_user_and_remove_groups() {
- organizationFlags.setEnabled(true);
- UserDto user = db.users().insertUser(newUserDto()
- .setLogin(USER_LOGIN)
- .setActive(true)
- .setName("John"));
- GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
- GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
- db.users().insertMember(group1, user);
- db.users().insertMember(group2, user);
-
- authenticate(USER_LOGIN, "group1");
-
- checkGroupMembership(user, group1);
- }
-
- @Test
- public void authenticate_existing_user_and_remove_all_groups_expect_default_when_organizations_are_disabled() {
- organizationFlags.setEnabled(false);
- UserDto user = db.users().insertUser();
- GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
- GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
- GroupDto defaultGroup = insertDefaultGroup();
- db.users().insertMember(group1, user);
- db.users().insertMember(group2, user);
- db.users().insertMember(defaultGroup, user);
-
- authenticate(user.getLogin());
-
- checkGroupMembership(user, defaultGroup);
- }
-
- @Test
- public void does_not_force_default_group_when_authenticating_existing_user_when_organizations_are_enabled() {
- organizationFlags.setEnabled(true);
- UserDto user = db.users().insertUser();
- GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
- GroupDto defaultGroup = insertDefaultGroup();
- db.users().insertMember(group1, user);
- db.users().insertMember(defaultGroup, user);
-
- authenticate(user.getLogin(), "group1");
-
- checkGroupMembership(user, group1);
- }
-
- @Test
- public void ignore_groups_on_non_default_organizations() {
- organizationFlags.setEnabled(true);
- OrganizationDto org = db.organizations().insert();
- UserDto user = db.users().insertUser(newUserDto()
- .setLogin(USER_LOGIN)
- .setActive(true)
- .setName("John"));
- String groupName = "a-group";
- GroupDto groupInDefaultOrg = db.users().insertGroup(db.getDefaultOrganization(), groupName);
- GroupDto groupInOrg = db.users().insertGroup(org, groupName);
-
- // adding a group with the same name than in non-default organization
- underTest.register(UserRegistration.builder()
- .setUserIdentity(UserIdentity.builder()
- .setProviderLogin("johndoo")
- .setLogin(user.getLogin())
- .setName(user.getName())
- .setGroups(newHashSet(groupName))
- .build())
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
- checkGroupMembership(user, groupInDefaultOrg);
- }
-
- private void authenticate(String login, String... groups) {
- underTest.register(UserRegistration.builder()
- .setUserIdentity(UserIdentity.builder()
- .setProviderLogin("johndoo")
- .setLogin(login)
- .setName("John")
- // No group
- .setGroups(stream(groups).collect(MoreCollectors.toSet()))
- .build())
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
- }
-
- private void checkGroupMembership(UserDto user, GroupDto... expectedGroups) {
- assertThat(db.users().selectGroupIdsOfUser(user)).containsOnly(stream(expectedGroups).map(GroupDto::getId).collect(Collectors.toList()).toArray(new Integer[] {}));
- }
-
- private GroupDto insertDefaultGroup() {
- return db.users().insertDefaultGroup(db.getDefaultOrganization(), "sonar-users");
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java
deleted file mode 100644
index cac1b7ceaf7..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.server.authentication.BaseIdentityProvider;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbTester;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationEvent.Method;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.tester.AnonymousMockUserSession;
-import org.sonar.server.tester.MockUserSession;
-import org.sonar.server.user.ThreadLocalUserSession;
-import org.sonar.server.user.UserSession;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-public class UserSessionInitializerTest {
-
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- private ThreadLocalUserSession threadLocalSession = mock(ThreadLocalUserSession.class);
- private HttpServletRequest request = mock(HttpServletRequest.class);
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private RequestAuthenticator authenticator = mock(RequestAuthenticator.class);
- private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
- private MapSettings settings = new MapSettings();
- private ArgumentCaptor<Cookie> cookieArgumentCaptor = ArgumentCaptor.forClass(Cookie.class);
-
- private UserSessionInitializer underTest = new UserSessionInitializer(settings.asConfig(), threadLocalSession, authenticationEvent, authenticator);
-
- @Before
- public void setUp() throws Exception {
- when(request.getContextPath()).thenReturn("");
- when(request.getRequestURI()).thenReturn("/measures");
- }
-
- @Test
- public void check_urls() {
- assertPathIsNotIgnored("/");
- assertPathIsNotIgnored("/foo");
- assertPathIsNotIgnored("/api/server_id/show");
-
- assertPathIsIgnored("/api/authentication/login");
- assertPathIsIgnored("/api/authentication/logout");
- assertPathIsIgnored("/api/authentication/validate");
- assertPathIsIgnored("/batch/index");
- assertPathIsIgnored("/batch/file");
- assertPathIsIgnored("/maintenance/index");
- assertPathIsIgnored("/setup/index");
- assertPathIsIgnored("/sessions/new");
- assertPathIsIgnored("/sessions/logout");
- assertPathIsIgnored("/sessions/unauthorized");
- assertPathIsIgnored("/oauth2/callback/github");
- assertPathIsIgnored("/oauth2/callback/foo");
- assertPathIsIgnored("/api/system/db_migration_status");
- assertPathIsIgnored("/api/system/status");
- assertPathIsIgnored("/api/system/migrate_db");
- assertPathIsIgnored("/api/server/version");
- assertPathIsIgnored("/api/users/identity_providers");
- assertPathIsIgnored("/api/l10n/index");
-
- // exlude passcode urls
- assertPathIsIgnoredWithAnonymousAccess("/api/ce/info");
- assertPathIsIgnoredWithAnonymousAccess("/api/ce/pause");
- assertPathIsIgnoredWithAnonymousAccess("/api/ce/resume");
- assertPathIsIgnoredWithAnonymousAccess("/api/system/health");
-
- // exclude static resources
- assertPathIsIgnored("/css/style.css");
- assertPathIsIgnored("/images/logo.png");
- assertPathIsIgnored("/js/jquery.js");
- }
-
- @Test
- public void return_code_401_when_not_authenticated_and_with_force_authentication() {
- ArgumentCaptor<AuthenticationException> exceptionArgumentCaptor = ArgumentCaptor.forClass(AuthenticationException.class);
- when(threadLocalSession.isLoggedIn()).thenReturn(false);
- when(authenticator.authenticate(request, response)).thenReturn(new AnonymousMockUserSession());
- settings.setProperty("sonar.forceAuthentication", true);
-
- assertThat(underTest.initUserSession(request, response)).isTrue();
-
- verifyZeroInteractions(response);
- verify(authenticationEvent).loginFailure(eq(request), exceptionArgumentCaptor.capture());
- verifyZeroInteractions(threadLocalSession);
- AuthenticationException authenticationException = exceptionArgumentCaptor.getValue();
- assertThat(authenticationException.getSource()).isEqualTo(Source.local(Method.BASIC));
- assertThat(authenticationException.getLogin()).isNull();
- assertThat(authenticationException.getMessage()).isEqualTo("User must be authenticated");
- assertThat(authenticationException.getPublicMessage()).isNull();
- }
-
- @Test
- public void return_401_and_stop_on_ws() {
- when(request.getRequestURI()).thenReturn("/api/issues");
- AuthenticationException authenticationException = AuthenticationException.newBuilder().setSource(Source.jwt()).setMessage("Token id hasn't been found").build();
- doThrow(authenticationException).when(authenticator).authenticate(request, response);
-
- assertThat(underTest.initUserSession(request, response)).isFalse();
-
- verify(response).setStatus(401);
- verify(authenticationEvent).loginFailure(request, authenticationException);
- verifyZeroInteractions(threadLocalSession);
- }
-
- @Test
- public void return_401_and_stop_on_batch_ws() {
- when(request.getRequestURI()).thenReturn("/batch/global");
- doThrow(AuthenticationException.newBuilder().setSource(Source.jwt()).setMessage("Token id hasn't been found").build())
- .when(authenticator).authenticate(request, response);
-
- assertThat(underTest.initUserSession(request, response)).isFalse();
-
- verify(response).setStatus(401);
- verifyZeroInteractions(threadLocalSession);
- }
-
- @Test
- public void return_to_session_unauthorized_when_error_on_from_external_provider() throws Exception {
- doThrow(AuthenticationException.newBuilder().setSource(Source.external(newBasicIdentityProvider("failing"))).setPublicMessage("Token id hasn't been found").build())
- .when(authenticator).authenticate(request, response);
-
- assertThat(underTest.initUserSession(request, response)).isFalse();
-
- verify(response).sendRedirect("/sessions/unauthorized");
- verify(response).addCookie(cookieArgumentCaptor.capture());
- Cookie cookie = cookieArgumentCaptor.getValue();
- assertThat(cookie.getName()).isEqualTo("AUTHENTICATION-ERROR");
- assertThat(cookie.getValue()).isEqualTo("Token%20id%20hasn%27t%20been%20found");
- assertThat(cookie.getPath()).isEqualTo("/");
- assertThat(cookie.isHttpOnly()).isFalse();
- assertThat(cookie.getMaxAge()).isEqualTo(300);
- assertThat(cookie.getSecure()).isFalse();
- }
-
- @Test
- public void return_to_session_unauthorized_when_error_on_from_external_provider_with_context_path() throws Exception {
- when(request.getContextPath()).thenReturn("/sonarqube");
- doThrow(AuthenticationException.newBuilder().setSource(Source.external(newBasicIdentityProvider("failing"))).setPublicMessage("Token id hasn't been found").build())
- .when(authenticator).authenticate(request, response);
-
- assertThat(underTest.initUserSession(request, response)).isFalse();
-
- verify(response).sendRedirect("/sonarqube/sessions/unauthorized");
- }
-
- private void assertPathIsIgnored(String path) {
- when(request.getRequestURI()).thenReturn(path);
-
- assertThat(underTest.initUserSession(request, response)).isTrue();
-
- verifyZeroInteractions(threadLocalSession, authenticator);
- reset(threadLocalSession, authenticator);
- }
-
- private void assertPathIsIgnoredWithAnonymousAccess(String path) {
- when(request.getRequestURI()).thenReturn(path);
- UserSession session = new AnonymousMockUserSession();
- when(authenticator.authenticate(request, response)).thenReturn(session);
-
- assertThat(underTest.initUserSession(request, response)).isTrue();
-
- verify(threadLocalSession).set(session);
- reset(threadLocalSession, authenticator);
- }
-
- private void assertPathIsNotIgnored(String path) {
- when(request.getRequestURI()).thenReturn(path);
- UserSession session = new MockUserSession("foo");
- when(authenticator.authenticate(request, response)).thenReturn(session);
-
- assertThat(underTest.initUserSession(request, response)).isTrue();
-
- verify(threadLocalSession).set(session);
- reset(threadLocalSession, authenticator);
- }
-
- private static BaseIdentityProvider newBasicIdentityProvider(String name) {
- BaseIdentityProvider mock = mock(BaseIdentityProvider.class);
- when(mock.getName()).thenReturn(name);
- return mock;
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventImplTest.java
deleted file mode 100644
index 7ea7b9be47a..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventImplTest.java
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication.event;
-
-import com.google.common.base.Joiner;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-import javax.servlet.http.HttpServletRequest;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import static org.sonar.server.authentication.event.AuthenticationException.newBuilder;
-
-public class AuthenticationEventImplTest {
- private static final String LOGIN_129_CHARS = "012345678901234567890123456789012345678901234567890123456789" +
- "012345678901234567890123456789012345678901234567890123456789012345678";
-
- @Rule
- public LogTester logTester = new LogTester();
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- private AuthenticationEventImpl underTest = new AuthenticationEventImpl();
-
- @Before
- public void setUp() throws Exception {
- logTester.setLevel(LoggerLevel.DEBUG);
- }
-
- @Test
- public void login_success_fails_with_NPE_if_request_is_null() {
- logTester.setLevel(LoggerLevel.INFO);
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("request can't be null");
-
- underTest.loginSuccess(null, "login", Source.sso());
- }
-
- @Test
- public void login_success_fails_with_NPE_if_source_is_null() {
- logTester.setLevel(LoggerLevel.INFO);
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("source can't be null");
-
- underTest.loginSuccess(mock(HttpServletRequest.class), "login", null);
- }
-
- @Test
- public void login_success_does_not_interact_with_request_if_log_level_is_above_DEBUG() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- logTester.setLevel(LoggerLevel.INFO);
-
- underTest.loginSuccess(request, "login", Source.sso());
-
- verifyZeroInteractions(request);
- }
-
- @Test
- public void login_success_creates_DEBUG_log_with_empty_login_if_login_argument_is_null() {
- underTest.loginSuccess(mockRequest(), null, Source.sso());
-
- verifyLog("login success [method|SSO][provider|SSO|sso][IP||][login|]");
- }
-
- @Test
- public void login_success_creates_DEBUG_log_with_method_provider_and_login() {
- underTest.loginSuccess(mockRequest(), "foo", Source.realm(Method.BASIC, "some provider name"));
-
- verifyLog("login success [method|BASIC][provider|REALM|some provider name][IP||][login|foo]");
- }
-
- @Test
- public void login_success_prevents_log_flooding_on_login_starting_from_128_chars() {
- underTest.loginSuccess(mockRequest(), LOGIN_129_CHARS, Source.realm(Method.BASIC, "some provider name"));
-
- verifyLog("login success [method|BASIC][provider|REALM|some provider name][IP||][login|012345678901234567890123456789012345678901234567890123456789" +
- "01234567890123456789012345678901234567890123456789012345678901234567...(129)]");
- }
-
- @Test
- public void login_success_logs_remote_ip_from_request() {
- underTest.loginSuccess(mockRequest("1.2.3.4"), "foo", Source.realm(Method.EXTERNAL, "bar"));
-
- verifyLog("login success [method|EXTERNAL][provider|REALM|bar][IP|1.2.3.4|][login|foo]");
- }
-
- @Test
- public void login_success_logs_X_Forwarded_For_header_from_request() {
- HttpServletRequest request = mockRequest("1.2.3.4", asList("2.3.4.5"));
- underTest.loginSuccess(request, "foo", Source.realm(Method.EXTERNAL, "bar"));
-
- verifyLog("login success [method|EXTERNAL][provider|REALM|bar][IP|1.2.3.4|2.3.4.5][login|foo]");
- }
-
- @Test
- public void login_success_logs_X_Forwarded_For_header_from_request_and_supports_multiple_headers() {
- HttpServletRequest request = mockRequest("1.2.3.4", asList("2.3.4.5", "6.5.4.3"), asList("9.5.6.7"), asList("6.3.2.4"));
- underTest.loginSuccess(request, "foo", Source.realm(Method.EXTERNAL, "bar"));
-
- verifyLog("login success [method|EXTERNAL][provider|REALM|bar][IP|1.2.3.4|2.3.4.5,6.5.4.3,9.5.6.7,6.3.2.4][login|foo]");
- }
-
- @Test
- public void login_failure_fails_with_NPE_if_request_is_null() {
- logTester.setLevel(LoggerLevel.INFO);
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("request can't be null");
-
- underTest.loginFailure(null, newBuilder().setSource(Source.sso()).build());
- }
-
- @Test
- public void login_failure_fails_with_NPE_if_AuthenticationException_is_null() {
- logTester.setLevel(LoggerLevel.INFO);
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("AuthenticationException can't be null");
-
- underTest.loginFailure(mock(HttpServletRequest.class), null);
- }
-
- @Test
- public void login_failure_does_not_interact_with_arguments_if_log_level_is_above_DEBUG() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- AuthenticationException exception = mock(AuthenticationException.class);
- logTester.setLevel(LoggerLevel.INFO);
-
- underTest.loginFailure(request, exception);
-
- verifyZeroInteractions(request, exception);
- }
-
- @Test
- public void login_failure_creates_DEBUG_log_with_empty_login_if_AuthenticationException_has_no_login() {
- AuthenticationException exception = newBuilder().setSource(Source.sso()).setMessage("message").build();
- underTest.loginFailure(mockRequest(), exception);
-
- verifyLog("login failure [cause|message][method|SSO][provider|SSO|sso][IP||][login|]");
- }
-
- @Test
- public void login_failure_creates_DEBUG_log_with_empty_cause_if_AuthenticationException_has_no_message() {
- AuthenticationException exception = newBuilder().setSource(Source.sso()).setLogin("FoO").build();
- underTest.loginFailure(mockRequest(), exception);
-
- verifyLog("login failure [cause|][method|SSO][provider|SSO|sso][IP||][login|FoO]");
- }
-
- @Test
- public void login_failure_creates_DEBUG_log_with_method_provider_and_login() {
- AuthenticationException exception = newBuilder()
- .setSource(Source.realm(Method.BASIC, "some provider name"))
- .setMessage("something got terribly wrong")
- .setLogin("BaR")
- .build();
- underTest.loginFailure(mockRequest(), exception);
-
- verifyLog("login failure [cause|something got terribly wrong][method|BASIC][provider|REALM|some provider name][IP||][login|BaR]");
- }
-
- @Test
- public void login_failure_prevents_log_flooding_on_login_starting_from_128_chars() {
- AuthenticationException exception = newBuilder()
- .setSource(Source.realm(Method.BASIC, "some provider name"))
- .setMessage("pop")
- .setLogin(LOGIN_129_CHARS)
- .build();
- underTest.loginFailure(mockRequest(), exception);
-
- verifyLog("login failure [cause|pop][method|BASIC][provider|REALM|some provider name][IP||][login|012345678901234567890123456789012345678901234567890123456789" +
- "01234567890123456789012345678901234567890123456789012345678901234567...(129)]");
- }
-
- @Test
- public void login_failure_logs_remote_ip_from_request() {
- AuthenticationException exception = newBuilder()
- .setSource(Source.realm(Method.EXTERNAL, "bar"))
- .setMessage("Damn it!")
- .setLogin("Baaad")
- .build();
- underTest.loginFailure(mockRequest("1.2.3.4"), exception);
-
- verifyLog("login failure [cause|Damn it!][method|EXTERNAL][provider|REALM|bar][IP|1.2.3.4|][login|Baaad]");
- }
-
- @Test
- public void login_failure_logs_X_Forwarded_For_header_from_request() {
- AuthenticationException exception = newBuilder()
- .setSource(Source.realm(Method.EXTERNAL, "bar"))
- .setMessage("Hop la!")
- .setLogin("foo")
- .build();
- HttpServletRequest request = mockRequest("1.2.3.4", asList("2.3.4.5"));
- underTest.loginFailure(request, exception);
-
- verifyLog("login failure [cause|Hop la!][method|EXTERNAL][provider|REALM|bar][IP|1.2.3.4|2.3.4.5][login|foo]");
- }
-
- @Test
- public void login_failure_logs_X_Forwarded_For_header_from_request_and_supports_multiple_headers() {
- AuthenticationException exception = newBuilder()
- .setSource(Source.realm(Method.EXTERNAL, "bar"))
- .setMessage("Boom!")
- .setLogin("foo")
- .build();
- HttpServletRequest request = mockRequest("1.2.3.4", asList("2.3.4.5", "6.5.4.3"), asList("9.5.6.7"), asList("6.3.2.4"));
- underTest.loginFailure(request, exception);
-
- verifyLog("login failure [cause|Boom!][method|EXTERNAL][provider|REALM|bar][IP|1.2.3.4|2.3.4.5,6.5.4.3,9.5.6.7,6.3.2.4][login|foo]");
- }
-
- @Test
- public void logout_success_fails_with_NPE_if_request_is_null() {
- logTester.setLevel(LoggerLevel.INFO);
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("request can't be null");
-
- underTest.logoutSuccess(null, "foo");
- }
-
- @Test
- public void logout_success_does_not_interact_with_request_if_log_level_is_above_DEBUG() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- logTester.setLevel(LoggerLevel.INFO);
-
- underTest.logoutSuccess(request, "foo");
-
- verifyZeroInteractions(request);
- }
-
- @Test
- public void logout_success_creates_DEBUG_log_with_empty_login_if_login_argument_is_null() {
- underTest.logoutSuccess(mockRequest(), null);
-
- verifyLog("logout success [IP||][login|]");
- }
-
- @Test
- public void logout_success_creates_DEBUG_log_with_login() {
- underTest.logoutSuccess(mockRequest(), "foo");
-
- verifyLog("logout success [IP||][login|foo]");
- }
-
- @Test
- public void logout_success_logs_remote_ip_from_request() {
- underTest.logoutSuccess(mockRequest("1.2.3.4"), "foo");
-
- verifyLog("logout success [IP|1.2.3.4|][login|foo]");
- }
-
- @Test
- public void logout_success_logs_X_Forwarded_For_header_from_request() {
- HttpServletRequest request = mockRequest("1.2.3.4", asList("2.3.4.5"));
- underTest.logoutSuccess(request, "foo");
-
- verifyLog("logout success [IP|1.2.3.4|2.3.4.5][login|foo]");
- }
-
- @Test
- public void logout_success_logs_X_Forwarded_For_header_from_request_and_supports_multiple_headers() {
- HttpServletRequest request = mockRequest("1.2.3.4", asList("2.3.4.5", "6.5.4.3"), asList("9.5.6.7"), asList("6.3.2.4"));
- underTest.logoutSuccess(request, "foo");
-
- verifyLog("logout success [IP|1.2.3.4|2.3.4.5,6.5.4.3,9.5.6.7,6.3.2.4][login|foo]");
- }
-
- @Test
- public void logout_failure_with_NPE_if_request_is_null() {
- logTester.setLevel(LoggerLevel.INFO);
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("request can't be null");
-
- underTest.logoutFailure(null, "bad csrf");
- }
-
- @Test
- public void login_fails_with_NPE_if_error_message_is_null() {
- logTester.setLevel(LoggerLevel.INFO);
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("error message can't be null");
-
- underTest.logoutFailure(mock(HttpServletRequest.class), null);
- }
-
- @Test
- public void logout_does_not_interact_with_request_if_log_level_is_above_DEBUG() {
- HttpServletRequest request = mock(HttpServletRequest.class);
- logTester.setLevel(LoggerLevel.INFO);
-
- underTest.logoutFailure(request, "bad csrf");
-
- verifyZeroInteractions(request);
- }
-
- @Test
- public void logout_creates_DEBUG_log_with_error() {
- underTest.logoutFailure(mockRequest(), "bad token");
-
- verifyLog("logout failure [error|bad token][IP||]");
- }
-
- @Test
- public void logout_logs_remote_ip_from_request() {
- underTest.logoutFailure(mockRequest("1.2.3.4"), "bad token");
-
- verifyLog("logout failure [error|bad token][IP|1.2.3.4|]");
- }
-
- @Test
- public void logout_logs_X_Forwarded_For_header_from_request() {
- HttpServletRequest request = mockRequest("1.2.3.4", asList("2.3.4.5"));
- underTest.logoutFailure(request, "bad token");
-
- verifyLog("logout failure [error|bad token][IP|1.2.3.4|2.3.4.5]");
- }
-
- @Test
- public void logout_logs_X_Forwarded_For_header_from_request_and_supports_multiple_headers() {
- HttpServletRequest request = mockRequest("1.2.3.4", asList("2.3.4.5", "6.5.4.3"), asList("9.5.6.7"), asList("6.3.2.4"));
- underTest.logoutFailure(request, "bad token");
-
- verifyLog("logout failure [error|bad token][IP|1.2.3.4|2.3.4.5,6.5.4.3,9.5.6.7,6.3.2.4]");
- }
-
- private void verifyLog(String expected) {
- assertThat(logTester.logs()).hasSize(1);
- assertThat(logTester.logs(LoggerLevel.DEBUG))
- .containsOnly(expected);
- }
-
- private static HttpServletRequest mockRequest() {
- return mockRequest("");
- }
-
- private static HttpServletRequest mockRequest(String remoteAddr, List<String>... remoteIps) {
- HttpServletRequest res = mock(HttpServletRequest.class);
- when(res.getRemoteAddr()).thenReturn(remoteAddr);
- when(res.getHeaders("X-Forwarded-For"))
- .thenReturn(Collections.enumeration(
- Arrays.stream(remoteIps)
- .map(Joiner.on(",")::join)
- .collect(Collectors.toList())));
- return res;
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventSourceTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventSourceTest.java
deleted file mode 100644
index 0bfac54e537..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationEventSourceTest.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication.event;
-
-import java.io.Serializable;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.server.authentication.BaseIdentityProvider;
-import org.sonar.api.server.authentication.OAuth2IdentityProvider;
-
-import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Method;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Provider;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-public class AuthenticationEventSourceTest {
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Test
- public void local_fails_with_NPE_if_method_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("method can't be null");
-
- Source.local(null);
- }
-
- @Test
- public void local_creates_source_instance_with_specified_method_and_hardcoded_provider_and_provider_name() {
- Source underTest = Source.local(Method.BASIC_TOKEN);
-
- assertThat(underTest.getMethod()).isEqualTo(Method.BASIC_TOKEN);
- assertThat(underTest.getProvider()).isEqualTo(Provider.LOCAL);
- assertThat(underTest.getProviderName()).isEqualTo("local");
- }
-
- @Test
- public void oauth2_fails_with_NPE_if_provider_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("identityProvider can't be null");
-
- Source.oauth2(null);
- }
-
- @Test
- public void oauth2_fails_with_NPE_if_providerName_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("provider name can't be null");
-
- Source.oauth2(newOauth2IdentityProvider(null));
- }
-
- @Test
- public void oauth2_fails_with_IAE_if_providerName_is_empty() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("provider name can't be empty");
-
- Source.oauth2(newOauth2IdentityProvider(""));
- }
-
- @Test
- public void oauth2_creates_source_instance_with_specified_provider_name_and_hardcoded_provider_and_method() {
- Source underTest = Source.oauth2(newOauth2IdentityProvider("some name"));
-
- assertThat(underTest.getMethod()).isEqualTo(Method.OAUTH2);
- assertThat(underTest.getProvider()).isEqualTo(Provider.EXTERNAL);
- assertThat(underTest.getProviderName()).isEqualTo("some name");
- }
-
- @Test
- public void realm_fails_with_NPE_if_method_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("method can't be null");
-
- Source.realm(null, "name");
- }
-
- @Test
- public void realm_fails_with_NPE_if_providerName_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("provider name can't be null");
-
- Source.realm(Method.BASIC, null);
- }
-
- @Test
- public void realm_fails_with_IAE_if_providerName_is_empty() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("provider name can't be empty");
-
- Source.realm(Method.BASIC, "");
- }
-
- @Test
- public void realm_creates_source_instance_with_specified_method_and_provider_name_and_hardcoded_provider() {
- Source underTest = Source.realm(Method.BASIC, "some name");
-
- assertThat(underTest.getMethod()).isEqualTo(Method.BASIC);
- assertThat(underTest.getProvider()).isEqualTo(Provider.REALM);
- assertThat(underTest.getProviderName()).isEqualTo("some name");
- }
-
- @Test
- public void sso_returns_source_instance_with_hardcoded_method_provider_and_providerName() {
- Source underTest = Source.sso();
-
- assertThat(underTest.getMethod()).isEqualTo(Method.SSO);
- assertThat(underTest.getProvider()).isEqualTo(Provider.SSO);
- assertThat(underTest.getProviderName()).isEqualTo("sso");
-
- assertThat(underTest).isSameAs(Source.sso());
- }
-
- @Test
- public void jwt_returns_source_instance_with_hardcoded_method_provider_and_providerName() {
- Source underTest = Source.jwt();
-
- assertThat(underTest.getMethod()).isEqualTo(Method.JWT);
- assertThat(underTest.getProvider()).isEqualTo(Provider.JWT);
- assertThat(underTest.getProviderName()).isEqualTo("jwt");
-
- assertThat(underTest).isSameAs(Source.jwt());
- }
-
- @Test
- public void external_fails_with_NPE_if_provider_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("identityProvider can't be null");
-
- Source.external(null);
- }
-
- @Test
- public void external_fails_with_NPE_if_providerName_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("provider name can't be null");
-
- Source.external(newBasicIdentityProvider(null));
- }
-
- @Test
- public void external_fails_with_IAE_if_providerName_is_empty() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("provider name can't be empty");
-
- Source.external(newBasicIdentityProvider(""));
- }
-
- @Test
- public void external_creates_source_instance_with_specified_provider_name_and_hardcoded_provider_and_method() {
- Source underTest = Source.external(newBasicIdentityProvider("some name"));
-
- assertThat(underTest.getMethod()).isEqualTo(Method.EXTERNAL);
- assertThat(underTest.getProvider()).isEqualTo(Provider.EXTERNAL);
- assertThat(underTest.getProviderName()).isEqualTo("some name");
- }
-
- @Test
- public void source_is_serializable() {
- assertThat(Serializable.class.isAssignableFrom(Source.class)).isTrue();
- }
-
- @Test
- public void toString_displays_all_fields() {
- assertThat(Source.sso().toString())
- .isEqualTo("Source{method=SSO, provider=SSO, providerName='sso'}");
- assertThat(Source.oauth2(newOauth2IdentityProvider("bou")).toString())
- .isEqualTo("Source{method=OAUTH2, provider=EXTERNAL, providerName='bou'}");
- }
-
- @Test
- public void source_implements_equals_on_all_fields() {
- assertThat(Source.sso()).isEqualTo(Source.sso());
- assertThat(Source.sso()).isNotEqualTo(Source.jwt());
- assertThat(Source.jwt()).isEqualTo(Source.jwt());
- assertThat(Source.local(Method.BASIC)).isEqualTo(Source.local(Method.BASIC));
- assertThat(Source.local(Method.BASIC)).isNotEqualTo(Source.local(Method.BASIC_TOKEN));
- assertThat(Source.local(Method.BASIC)).isNotEqualTo(Source.sso());
- assertThat(Source.local(Method.BASIC)).isNotEqualTo(Source.jwt());
- assertThat(Source.local(Method.BASIC)).isNotEqualTo(Source.oauth2(newOauth2IdentityProvider("voo")));
- assertThat(Source.oauth2(newOauth2IdentityProvider("foo")))
- .isEqualTo(Source.oauth2(newOauth2IdentityProvider("foo")));
- assertThat(Source.oauth2(newOauth2IdentityProvider("foo")))
- .isNotEqualTo(Source.oauth2(newOauth2IdentityProvider("bar")));
- }
-
- private static OAuth2IdentityProvider newOauth2IdentityProvider(String name) {
- OAuth2IdentityProvider mock = mock(OAuth2IdentityProvider.class);
- when(mock.getName()).thenReturn(name);
- return mock;
- }
-
- private static BaseIdentityProvider newBasicIdentityProvider(String name) {
- BaseIdentityProvider mock = mock(BaseIdentityProvider.class);
- when(mock.getName()).thenReturn(name);
- return mock;
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationExceptionMatcher.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationExceptionMatcher.java
deleted file mode 100644
index 8ad3da0070a..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationExceptionMatcher.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication.event;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-/**
- * Matcher for {@link AuthenticationException} to be used with {@link org.junit.rules.ExpectedException} JUnit Rule.
- *
- * <p>
- * Usage:
- * <pre>
- * expectedException.expect(authenticationException().from(Source.local(Method.BASIC_TOKEN)).withLogin("foo").andNoPublicMessage());
- * </pre>
- * </p>
- */
-public class AuthenticationExceptionMatcher extends TypeSafeMatcher<Throwable> {
- private final Source source;
- @CheckForNull
- private final String login;
- @CheckForNull
- private final String publicMessage;
-
- private AuthenticationExceptionMatcher(Source source, @Nullable String login, @Nullable String publicMessage) {
- this.source = requireNonNull(source, "source can't be null");
- this.login = login;
- this.publicMessage = publicMessage;
- }
-
- public static Builder authenticationException() {
- return new Builder();
- }
-
- public static class Builder {
- private Source source;
- private String login;
-
- public Builder from(Source source) {
- this.source = checkSource(source);
- return this;
- }
-
- public Builder withLogin(String login) {
- this.login = requireNonNull(login, "expected login can't be null");
- return this;
- }
-
- public Builder withoutLogin() {
- this.login = null;
- return this;
- }
-
- public AuthenticationExceptionMatcher andNoPublicMessage() {
- return new AuthenticationExceptionMatcher(this.source, this.login, null);
- }
-
- public AuthenticationExceptionMatcher andPublicMessage(String publicMessage){
- return new AuthenticationExceptionMatcher(this.source, this.login, requireNonNull(publicMessage));
- }
-
- private static Source checkSource(Source source) {
- return requireNonNull(source, "expected source can't be null");
- }
- }
-
- @Override
- protected boolean matchesSafely(Throwable throwable) {
- return check(throwable) == null;
- }
-
- private String check(Throwable throwable) {
- if (!throwable.getClass().isAssignableFrom(AuthenticationException.class)) {
- return "exception is not a AuthenticationException";
- }
- AuthenticationException authenticationException = (AuthenticationException) throwable;
- if (!this.source.equals(authenticationException.getSource())) {
- return "source is \"" + authenticationException.getSource() + "\"";
- }
-
- String login = authenticationException.getLogin();
- if (this.login == null) {
- if (login != null) {
- return "login is \"" + login + "\"";
- }
- } else if (login == null) {
- return "login is null";
- } else if (!this.login.equals(login)) {
- return "login is \"" + login + "\"";
- }
-
- String publicMessage = authenticationException.getPublicMessage();
- if (this.publicMessage == null) {
- if (publicMessage != null) {
- return "publicMessage is \"" + publicMessage + "\"";
- }
- } else if (publicMessage == null) {
- return "publicMessage is null";
- } else if (!this.publicMessage.equals(publicMessage)) {
- return "publicMessage is \"" + publicMessage + "\"";
- }
-
- return null;
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText("AuthenticationException with source ").appendText(source.toString());
- if (login == null) {
- description.appendText(", no login");
- } else {
- description.appendText(", login \"").appendText(login).appendText("\"");
- }
- if (publicMessage == null) {
- description.appendText(" and no publicMessage");
- } else {
- description.appendText(" and publicMessage \"").appendText(publicMessage).appendText("\"");
- }
- }
-
- @Override
- protected void describeMismatchSafely(Throwable item, Description mismatchDescription) {
- mismatchDescription.appendText(check(item));
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationExceptionTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationExceptionTest.java
deleted file mode 100644
index 1472a4da905..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/authentication/event/AuthenticationExceptionTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication.event;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.server.authentication.event.AuthenticationEvent.Source;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class AuthenticationExceptionTest {
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Test
- public void build_fails_with_NPE_if_source_is_null() {
- AuthenticationException.Builder builder = AuthenticationException.newBuilder()
- .setLogin("login")
- .setMessage("message");
-
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("source can't be null");
-
- builder.build();
- }
-
- @Test
- public void build_does_not_fail_if_login_is_null() {
- AuthenticationException exception = AuthenticationException.newBuilder()
- .setSource(Source.sso())
- .setMessage("message")
- .build();
-
- assertThat(exception.getSource()).isEqualTo(Source.sso());
- assertThat(exception.getMessage()).isEqualTo("message");
- assertThat(exception.getLogin()).isNull();
- }
-
- @Test
- public void build_does_not_fail_if_message_is_null() {
- AuthenticationException exception = AuthenticationException.newBuilder()
- .setSource(Source.sso())
- .setLogin("login")
- .build();
-
- assertThat(exception.getSource()).isEqualTo(Source.sso());
- assertThat(exception.getMessage()).isNull();
- assertThat(exception.getLogin()).isEqualTo("login");
- }
-
- @Test
- public void builder_set_methods_do_not_fail_if_login_is_null() {
- AuthenticationException.newBuilder().setSource(null).setLogin(null).setMessage(null);
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java b/server/sonar-server/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java
deleted file mode 100644
index 0dc82c559f0..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.exceptions;
-
-import java.util.Collections;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class BadRequestExceptionTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Test
- public void text_error() {
- BadRequestException exception = BadRequestException.create("error");
- assertThat(exception.getMessage()).isEqualTo("error");
- }
-
- @Test
- public void create_exception_from_list() {
- BadRequestException underTest = BadRequestException.create(asList("error1", "error2"));
-
- assertThat(underTest.errors()).containsOnly("error1", "error2");
- }
-
- @Test
- public void create_exception_from_var_args() {
- BadRequestException underTest = BadRequestException.create("error1", "error2");
-
- assertThat(underTest.errors()).containsOnly("error1", "error2");
- }
-
- @Test
- public void getMessage_return_first_error() {
- BadRequestException underTest = BadRequestException.create(asList("error1", "error2"));
-
- assertThat(underTest.getMessage()).isEqualTo("error1");
- }
-
- @Test
- public void fail_when_creating_exception_with_empty_list() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("At least one error message is required");
-
- BadRequestException.create(Collections.emptyList());
- }
-
- @Test
- public void fail_when_creating_exception_with_one_empty_element() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Message cannot be empty");
-
- BadRequestException.create(asList("error", ""));
- }
-
- @Test
- public void fail_when_creating_exception_with_one_null_element() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Message cannot be empty");
-
- BadRequestException.create(asList("error", null));
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/exceptions/MessageTest.java b/server/sonar-server/src/test/java/org/sonar/server/exceptions/MessageTest.java
deleted file mode 100644
index f05bb55058a..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/exceptions/MessageTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.exceptions;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class MessageTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Test
- public void create_message() {
- Message message = Message.of("key1 %s", "param1");
- assertThat(message.getMessage()).isEqualTo("key1 param1");
- }
-
- @Test
- public void create_message_without_params() {
- Message message = Message.of("key1");
- assertThat(message.getMessage()).isEqualTo("key1");
- }
-
- @Test
- public void fail_when_message_is_null() {
- expectedException.expect(IllegalArgumentException.class);
-
- Message.of(null);
- }
-
- @Test
- public void fail_when_message_is_empty() {
- expectedException.expect(IllegalArgumentException.class);
-
- Message.of("");
- }
-
- @Test
- public void test_equals_and_hashcode() {
- Message message1 = Message.of("key1%s", "param1");
- Message message2 = Message.of("key2%s", "param2");
- Message message3 = Message.of("key1");
- Message message4 = Message.of("key1%s", "param2");
- Message sameAsMessage1 = Message.of("key1%s", "param1");
-
- assertThat(message1).isEqualTo(message1);
- assertThat(message1).isNotEqualTo(message2);
- assertThat(message1).isNotEqualTo(message3);
- assertThat(message1).isNotEqualTo(message4);
- assertThat(message1).isEqualTo(sameAsMessage1);
- assertThat(message1).isNotEqualTo(null);
- assertThat(message1).isNotEqualTo(new Object());
-
- assertThat(message1.hashCode()).isEqualTo(message1.hashCode());
- assertThat(message1.hashCode()).isNotEqualTo(message2.hashCode());
- assertThat(message1.hashCode()).isNotEqualTo(message3.hashCode());
- assertThat(message1.hashCode()).isNotEqualTo(message4.hashCode());
- assertThat(message1.hashCode()).isEqualTo(sameAsMessage1.hashCode());
- }
-
- @Test
- public void to_string() {
- assertThat(Message.of("key1 %s", "param1").toString()).isEqualTo("key1 param1");
- assertThat(Message.of("key1").toString()).isEqualTo("key1");
- assertThat(Message.of("key1", (Object[])null).toString()).isEqualTo("key1");
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java b/server/sonar-server/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java
deleted file mode 100644
index ae2ce7846db..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.exceptions;
-
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ServerExceptionTest {
-
- @Test
- public void should_create_exception_with_status() {
- ServerException exception = new ServerException(400, "error!");
- assertThat(exception.httpCode()).isEqualTo(400);
- }
-
- @Test
- public void should_create_exception_with_status_and_message() {
- ServerException exception = new ServerException(404, "Not found");
- assertThat(exception.httpCode()).isEqualTo(404);
- assertThat(exception.getMessage()).isEqualTo("Not found");
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/language/LanguageTesting.java b/server/sonar-server/src/test/java/org/sonar/server/language/LanguageTesting.java
deleted file mode 100644
index 644419c6c37..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/language/LanguageTesting.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.language;
-
-import com.google.common.collect.Collections2;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.resources.AbstractLanguage;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.core.util.NonNullInputFunction;
-
-import java.util.Arrays;
-
-public class LanguageTesting {
-
- public static Language newLanguage(String key, String name, final String... prefixes) {
- return new AbstractLanguage(key, name) {
- @Override
- public String[] getFileSuffixes() {
- return prefixes;
- }
- };
- }
-
- public static Language newLanguage(String key) {
- return newLanguage(key, StringUtils.capitalize(key));
- }
-
- public static Languages newLanguages(String... languageKeys) {
- return new Languages(Collections2.transform(Arrays.asList(languageKeys), new NonNullInputFunction<String, Language>() {
- @Override
- protected Language doApply(String languageKey) {
- return newLanguage(languageKey);
- }
-
- }).toArray(new Language[0]));
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/DefaultOrganizationEnforcerTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/DefaultOrganizationEnforcerTest.java
deleted file mode 100644
index 3f145630f5f..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/organization/DefaultOrganizationEnforcerTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import org.junit.Test;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-public class DefaultOrganizationEnforcerTest {
- private DefaultOrganizationProvider defaultOrganizationProvider = mock(DefaultOrganizationProvider.class);
- private DefaultOrganizationEnforcer underTest = new DefaultOrganizationEnforcer(defaultOrganizationProvider);
-
- @Test
- public void start_calls_provider_get_method() {
- underTest.start();
-
- verify(defaultOrganizationProvider).get();
- verifyNoMoreInteractions(defaultOrganizationProvider);
- }
-
- @Test
- public void stop_does_nothing() {
- underTest.stop();
-
- verifyNoMoreInteractions(defaultOrganizationProvider);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/MemberUpdaterTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/MemberUpdaterTest.java
deleted file mode 100644
index 309698e3c49..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/organization/MemberUpdaterTest.java
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import com.google.common.collect.ImmutableSet;
-import java.util.HashSet;
-import javax.annotation.Nullable;
-import org.assertj.core.groups.Tuple;
-import org.elasticsearch.action.search.SearchRequestBuilder;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbTester;
-import org.sonar.db.alm.AlmAppInstallDto;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.permission.template.PermissionTemplateDto;
-import org.sonar.db.permission.template.PermissionTemplateUserDto;
-import org.sonar.db.property.PropertyDto;
-import org.sonar.db.property.PropertyQuery;
-import org.sonar.db.qualityprofile.QProfileDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
-import org.sonar.server.user.index.UserIndexDefinition;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.user.index.UserQuery;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static java.lang.String.format;
-import static java.util.Arrays.asList;
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
-import static org.elasticsearch.index.query.QueryBuilders.termQuery;
-import static org.sonar.api.CoreProperties.DEFAULT_ISSUE_ASSIGNEE;
-import static org.sonar.api.web.UserRole.CODEVIEWER;
-import static org.sonar.api.web.UserRole.USER;
-import static org.sonar.db.alm.ALM.GITHUB;
-import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
-import static org.sonar.db.permission.OrganizationPermission.SCAN;
-import static org.sonar.server.user.index.UserIndexDefinition.FIELD_ORGANIZATION_UUIDS;
-import static org.sonar.server.user.index.UserIndexDefinition.FIELD_UUID;
-
-public class MemberUpdaterTest {
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- @Rule
- public EsTester es = EsTester.create();
- @Rule
- public DbTester db = DbTester.create();
-
- private DbClient dbClient = db.getDbClient();
- private UserIndex userIndex = new UserIndex(es.client(), System2.INSTANCE);
- private UserIndexer userIndexer = new UserIndexer(dbClient, es.client());
-
- private MemberUpdater underTest = new MemberUpdater(dbClient, new DefaultGroupFinder(dbClient), userIndexer);
-
- @Test
- public void add_member_in_db_and_user_index() {
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- UserDto user = db.users().insertUser();
-
- underTest.addMember(db.getSession(), organization, user);
-
- db.organizations().assertUserIsMemberOfOrganization(organization, user);
- assertThat(userIndex.search(UserQuery.builder().build(), new SearchOptions()).getDocs())
- .extracting(UserDoc::login, UserDoc::organizationUuids)
- .containsExactlyInAnyOrder(tuple(user.getLogin(), singletonList(organization.getUuid())));
- }
-
- @Test
- public void does_not_fail_to_add_member_if_user_already_added_in_organization() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto user = db.users().insertUser();
- db.organizations().addMember(organization, user);
- db.users().insertMember(defaultGroup, user);
- db.organizations().assertUserIsMemberOfOrganization(organization, user);
-
- underTest.addMember(db.getSession(), organization, user);
-
- db.organizations().assertUserIsMemberOfOrganization(organization, user);
- }
-
- @Test
- public void add_member_fails_when_organization_has_no_default_group() {
- OrganizationDto organization = db.organizations().insert();
- UserDto user = db.users().insertUser();
-
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage(format("Default group cannot be found on organization '%s'", organization.getUuid()));
-
- underTest.addMember(db.getSession(), organization, user);
- }
-
- @Test
- public void add_members_in_db_and_user_index() {
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- UserDto user1 = db.users().insertUser();
- UserDto user2 = db.users().insertUser();
- UserDto disableUser = db.users().insertDisabledUser();
-
- underTest.addMembers(db.getSession(), organization, asList(user1, user2, disableUser));
-
- db.organizations().assertUserIsMemberOfOrganization(organization, user1);
- db.organizations().assertUserIsMemberOfOrganization(organization, user2);
- assertUserIsNotMember(organization, disableUser);
- assertThat(userIndex.search(UserQuery.builder().build(), new SearchOptions()).getDocs())
- .extracting(UserDoc::login, UserDoc::organizationUuids)
- .containsExactlyInAnyOrder(
- tuple(user1.getLogin(), singletonList(organization.getUuid())),
- tuple(user2.getLogin(), singletonList(organization.getUuid())));
- }
-
- @Test
- public void add_members_does_not_fail_when_one_user_is_already_member_of_organization() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto userAlreadyMember = db.users().insertUser();
- db.organizations().addMember(organization, userAlreadyMember);
- db.users().insertMember(defaultGroup, userAlreadyMember);
- UserDto userNotMember = db.users().insertUser();
- userIndexer.indexOnStartup(new HashSet<>());
-
- underTest.addMembers(db.getSession(), organization, asList(userAlreadyMember, userNotMember));
-
- db.organizations().assertUserIsMemberOfOrganization(organization, userAlreadyMember);
- db.organizations().assertUserIsMemberOfOrganization(organization, userNotMember);
- assertThat(userIndex.search(UserQuery.builder().build(), new SearchOptions()).getDocs())
- .extracting(UserDoc::login, UserDoc::organizationUuids)
- .containsExactlyInAnyOrder(
- tuple(userAlreadyMember.getLogin(), singletonList(organization.getUuid())),
- tuple(userNotMember.getLogin(), singletonList(organization.getUuid())));
- }
-
- @Test
- public void remove_member_from_db_and_user_index() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto user = db.users().insertUser();
- UserDto adminUser = db.users().insertAdminByUserPermission(organization);
- db.organizations().addMember(organization, user, adminUser);
- db.users().insertMember(defaultGroup, user);
- userIndexer.indexOnStartup(new HashSet<>());
-
- underTest.removeMember(db.getSession(), organization, user);
-
- assertUserIsNotMember(organization, user);
- }
-
- @Test
- public void remove_members_from_db_and_user_index() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto user1 = db.users().insertUser();
- UserDto user2 = db.users().insertUser();
- UserDto adminUser = db.users().insertAdminByUserPermission(organization);
- db.organizations().addMember(organization, user1, user2, adminUser);
- db.users().insertMember(defaultGroup, user1);
- db.users().insertMember(defaultGroup, user2);
- db.users().insertMember(defaultGroup, adminUser);
- userIndexer.indexOnStartup(new HashSet<>());
-
- underTest.removeMembers(db.getSession(), organization, asList(user1, user2));
-
- assertUserIsNotMember(organization, user1);
- assertUserIsNotMember(organization, user2);
- db.organizations().assertUserIsMemberOfOrganization(organization, adminUser);
- }
-
- @Test
- public void remove_member_removes_permissions() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto project = db.components().insertPrivateProject(organization);
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto user = db.users().insertUser();
- UserDto adminUser = db.users().insertAdminByUserPermission(organization);
- db.organizations().addMember(organization, user, adminUser);
- db.users().insertMember(defaultGroup, user);
- UserDto anotherUser = db.users().insertUser();
- OrganizationDto anotherOrganization = db.organizations().insert();
- ComponentDto anotherProject = db.components().insertPrivateProject(anotherOrganization);
- userIndexer.indexOnStartup(new HashSet<>());
-
- db.users().insertPermissionOnUser(organization, user, ADMINISTER);
- db.users().insertPermissionOnUser(organization, user, SCAN);
- db.users().insertPermissionOnUser(anotherOrganization, user, ADMINISTER);
- db.users().insertPermissionOnUser(anotherOrganization, user, SCAN);
- db.users().insertPermissionOnUser(organization, anotherUser, ADMINISTER);
- db.users().insertPermissionOnUser(organization, anotherUser, SCAN);
- db.users().insertProjectPermissionOnUser(user, CODEVIEWER, project);
- db.users().insertProjectPermissionOnUser(user, USER, project);
- db.users().insertProjectPermissionOnUser(user, CODEVIEWER, anotherProject);
- db.users().insertProjectPermissionOnUser(user, USER, anotherProject);
- db.users().insertProjectPermissionOnUser(anotherUser, CODEVIEWER, project);
- db.users().insertProjectPermissionOnUser(anotherUser, USER, project);
-
- underTest.removeMember(db.getSession(), organization, user);
-
- assertUserIsNotMember(organization, user);
- assertOrgPermissionsOfUser(user, organization);
- assertOrgPermissionsOfUser(user, anotherOrganization, ADMINISTER, SCAN);
- assertOrgPermissionsOfUser(anotherUser, organization, ADMINISTER, SCAN);
- assertProjectPermissionsOfUser(user, project);
- assertProjectPermissionsOfUser(user, anotherProject, CODEVIEWER, USER);
- assertProjectPermissionsOfUser(anotherUser, project, CODEVIEWER, USER);
- }
-
- @Test
- public void remove_member_removes_template_permissions() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto user = db.users().insertUser();
- UserDto adminUser = db.users().insertAdminByUserPermission(organization);
- db.organizations().addMember(organization, user, adminUser);
- db.users().insertMember(defaultGroup, user);
- userIndexer.indexOnStartup(new HashSet<>());
-
- OrganizationDto anotherOrganization = db.organizations().insert();
- UserDto anotherUser = db.users().insertUser();
- PermissionTemplateDto template = db.permissionTemplates().insertTemplate(organization);
- PermissionTemplateDto anotherTemplate = db.permissionTemplates().insertTemplate(anotherOrganization);
- String permission = "browse";
- db.permissionTemplates().addUserToTemplate(template.getId(), user.getId(), permission);
- db.permissionTemplates().addUserToTemplate(template.getId(), anotherUser.getId(), permission);
- db.permissionTemplates().addUserToTemplate(anotherTemplate.getId(), user.getId(), permission);
-
- underTest.removeMember(db.getSession(), organization, user);
-
- assertThat(dbClient.permissionTemplateDao().selectUserPermissionsByTemplateId(db.getSession(), template.getId())).extracting(PermissionTemplateUserDto::getUserId)
- .containsOnly(anotherUser.getId());
- assertThat(dbClient.permissionTemplateDao().selectUserPermissionsByTemplateId(db.getSession(), anotherTemplate.getId())).extracting(PermissionTemplateUserDto::getUserId)
- .containsOnly(user.getId());
- }
-
- @Test
- public void remove_member_removes_qprofiles_user_permission() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto user = db.users().insertUser();
- UserDto adminUser = db.users().insertAdminByUserPermission(organization);
- db.organizations().addMember(organization, user, adminUser);
- db.users().insertMember(defaultGroup, user);
- userIndexer.indexOnStartup(new HashSet<>());
-
- OrganizationDto anotherOrganization = db.organizations().insert();
- db.organizations().addMember(anotherOrganization, user);
- QProfileDto profile = db.qualityProfiles().insert(organization);
- QProfileDto anotherProfile = db.qualityProfiles().insert(anotherOrganization);
- db.qualityProfiles().addUserPermission(profile, user);
- db.qualityProfiles().addUserPermission(anotherProfile, user);
-
- underTest.removeMember(db.getSession(), organization, user);
-
- assertThat(db.getDbClient().qProfileEditUsersDao().exists(db.getSession(), profile, user)).isFalse();
- assertThat(db.getDbClient().qProfileEditUsersDao().exists(db.getSession(), anotherProfile, user)).isTrue();
- }
-
- @Test
- public void remove_member_removes_user_from_organization_groups() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto user = db.users().insertUser();
- UserDto adminUser = db.users().insertAdminByUserPermission(organization);
- db.organizations().addMember(organization, user, adminUser);
- db.users().insertMember(defaultGroup, user);
- userIndexer.indexOnStartup(new HashSet<>());
-
- OrganizationDto anotherOrganization = db.organizations().insert();
- UserDto anotherUser = db.users().insertUser();
- GroupDto group = db.users().insertGroup(organization);
- GroupDto anotherGroup = db.users().insertGroup(anotherOrganization);
- db.users().insertMembers(group, user, anotherUser);
- db.users().insertMembers(anotherGroup, user, anotherUser);
-
- underTest.removeMember(db.getSession(), organization, user);
-
- assertThat(dbClient.groupMembershipDao().selectGroupIdsByUserId(db.getSession(), user.getId()))
- .containsOnly(anotherGroup.getId());
- assertThat(dbClient.groupMembershipDao().selectGroupIdsByUserId(db.getSession(), anotherUser.getId()))
- .containsOnly(group.getId(), anotherGroup.getId());
- }
-
- @Test
- public void remove_member_removes_user_from_default_organization_group() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto user = db.users().insertUser();
- UserDto adminUser = db.users().insertAdminByUserPermission(organization);
- db.organizations().addMember(organization, user, adminUser);
- db.users().insertMember(defaultGroup, user);
- userIndexer.indexOnStartup(new HashSet<>());
-
- underTest.removeMember(db.getSession(), organization, user);
-
- assertThat(dbClient.groupMembershipDao().selectGroupIdsByUserId(db.getSession(), user.getId())).isEmpty();
- }
-
- @Test
- public void remove_member_removes_user_from_org_properties() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto project = db.components().insertPrivateProject(organization);
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto user = db.users().insertUser();
- UserDto adminUser = db.users().insertAdminByUserPermission(organization);
- db.organizations().addMember(organization, user, adminUser);
- db.users().insertMember(defaultGroup, user);
- userIndexer.indexOnStartup(new HashSet<>());
-
- OrganizationDto anotherOrganization = db.organizations().insert();
- ComponentDto anotherProject = db.components().insertPrivateProject(anotherOrganization);
- UserDto anotherUser = db.users().insertUser();
- insertProperty("KEY_11", "VALUE", project.getId(), user.getId());
- insertProperty("KEY_12", "VALUE", project.getId(), user.getId());
- insertProperty("KEY_11", "VALUE", project.getId(), anotherUser.getId());
- insertProperty("KEY_11", "VALUE", anotherProject.getId(), user.getId());
-
- underTest.removeMember(db.getSession(), organization, user);
-
- assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentId(project.getId()).build(), db.getSession()))
- .hasSize(1).extracting(PropertyDto::getUserId).containsOnly(anotherUser.getId());
- assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentId(anotherProject.getId()).build(), db.getSession())).extracting(PropertyDto::getUserId)
- .hasSize(1).containsOnly(user.getId());
- }
-
- @Test
- public void remove_member_removes_user_from_default_assignee_properties() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto project = db.components().insertPrivateProject(organization);
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- UserDto user = db.users().insertUser();
- UserDto adminUser = db.users().insertAdminByUserPermission(organization);
- db.organizations().addMember(organization, user, adminUser);
- db.users().insertMember(defaultGroup, user);
- userIndexer.indexOnStartup(new HashSet<>());
-
- OrganizationDto anotherOrganization = db.organizations().insert();
- ComponentDto anotherProject = db.components().insertPrivateProject(anotherOrganization);
- UserDto anotherUser = db.users().insertUser();
- insertProperty(DEFAULT_ISSUE_ASSIGNEE, user.getLogin(), project.getId(), null);
- insertProperty("ANOTHER_KEY", user.getLogin(), project.getId(), null);
- insertProperty(DEFAULT_ISSUE_ASSIGNEE, anotherUser.getLogin(), project.getId(), null);
- insertProperty(DEFAULT_ISSUE_ASSIGNEE, user.getLogin(), anotherProject.getId(), null);
-
- underTest.removeMember(db.getSession(), organization, user);
-
- assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentId(project.getId()).build(), db.getSession()))
- .hasSize(2).extracting(PropertyDto::getKey, PropertyDto::getValue)
- .containsOnly(Tuple.tuple("ANOTHER_KEY", user.getLogin()), Tuple.tuple(DEFAULT_ISSUE_ASSIGNEE, anotherUser.getLogin()));
- assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentId(anotherProject.getId()).build(), db.getSession())).extracting(PropertyDto::getValue)
- .hasSize(1).containsOnly(user.getLogin());
- }
-
- @Test
- public void fail_to_remove_members_when_no_more_admin() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- GroupDto adminGroup = db.users().insertGroup(organization);
- db.users().insertPermissionOnGroup(adminGroup, ADMINISTER);
- UserDto user1 = db.users().insertUser();
- UserDto admin1 = db.users().insertAdminByUserPermission(organization);
- UserDto admin2 = db.users().insertUser();
- db.organizations().addMember(organization, user1, admin1, admin2);
- db.users().insertMember(defaultGroup, user1);
- db.users().insertMember(defaultGroup, admin1);
- db.users().insertMember(defaultGroup, admin2);
- db.users().insertMember(adminGroup, admin2);
- userIndexer.indexOnStartup(new HashSet<>());
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("The last administrator member cannot be removed");
-
- underTest.removeMembers(db.getSession(), organization, asList(admin1, admin2));
- }
-
- @Test
- public void synchronize_user_organization_membership() {
- OrganizationDto organization1 = db.organizations().insert();
- GroupDto org1defaultGroup = db.users().insertDefaultGroup(organization1, "Members");
- AlmAppInstallDto gitHubInstall1 = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization1, gitHubInstall1, true);
- OrganizationDto organization2 = db.organizations().insert();
- db.users().insertDefaultGroup(organization2, "Members");
- AlmAppInstallDto gitHubInstall2 = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization2, gitHubInstall2, true);
- OrganizationDto organization3 = db.organizations().insert();
- GroupDto org3defaultGroup = db.users().insertDefaultGroup(organization3, "Members");
- AlmAppInstallDto gitHubInstall3 = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization3, gitHubInstall3, true);
- // User is member of organization1 and organization3, but organization3 membership will be removed and organization2 membership will be
- // added
- UserDto user = db.users().insertUser();
- db.organizations().addMember(organization1, user);
- db.users().insertMember(org1defaultGroup, user);
- db.organizations().addMember(organization3, user);
- db.users().insertMember(org3defaultGroup, user);
-
- underTest.synchronizeUserOrganizationMembership(db.getSession(), user, GITHUB, ImmutableSet.of(gitHubInstall1.getOrganizationAlmId(), gitHubInstall2.getOrganizationAlmId()));
-
- db.organizations().assertUserIsMemberOfOrganization(organization1, user);
- db.organizations().assertUserIsMemberOfOrganization(organization2, user);
- assertUserIsNotMember(organization3, user);
- }
-
- @Test
- public void synchronize_user_organization_membership_does_not_update_es_index() {
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- AlmAppInstallDto gitHubInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization, gitHubInstall, true);
- UserDto user = db.users().insertUser();
-
- underTest.synchronizeUserOrganizationMembership(db.getSession(), user, GITHUB, ImmutableSet.of(gitHubInstall.getOrganizationAlmId()));
-
- assertThat(userIndex.search(UserQuery.builder().build(), new SearchOptions()).getDocs()).isEmpty();
- }
-
- @Test
- public void synchronize_user_organization_membership_ignores_organization_alm_ids_match_no_existing_organizations() {
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- AlmAppInstallDto gitHubInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization, gitHubInstall, true);
- UserDto user = db.users().insertUser();
-
- underTest.synchronizeUserOrganizationMembership(db.getSession(), user, GITHUB, ImmutableSet.of("unknown"));
-
- // User is member of no organization
- assertThat(db.getDbClient().organizationMemberDao().selectOrganizationUuidsByUser(db.getSession(), user.getId())).isEmpty();
- }
-
- @Test
- public void synchronize_user_organization_membership_ignores_organization_with_member_sync_disabled() {
- OrganizationDto organization = db.organizations().insert();
- db.users().insertDefaultGroup(organization, "Members");
- AlmAppInstallDto gitHubInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization, gitHubInstall, false);
- UserDto user = db.users().insertUser();
-
- underTest.synchronizeUserOrganizationMembership(db.getSession(), user, GITHUB, ImmutableSet.of(gitHubInstall.getOrganizationAlmId()));
-
- db.organizations().assertUserIsNotMemberOfOrganization(organization, user);
- }
-
- @Test
- public void synchronize_user_organization_membership_does_not_remove_existing_membership_on_organization_with_member_sync_disabled() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto org1defaultGroup = db.users().insertDefaultGroup(organization, "Members");
- AlmAppInstallDto gitHubInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
- db.alm().insertOrganizationAlmBinding(organization, gitHubInstall, false);
- UserDto user = db.users().insertUser();
- db.users().insertMember(org1defaultGroup, user);
- db.organizations().addMember(organization, user);
- // User is member of a organization on which member sync is disabled
- db.organizations().assertUserIsMemberOfOrganization(organization, user);
-
- // The organization is not in the list, but membership should not be removed
- underTest.synchronizeUserOrganizationMembership(db.getSession(), user, GITHUB, ImmutableSet.of("other"));
-
- db.organizations().assertUserIsMemberOfOrganization(organization, user);
- }
-
- private void assertUserIsNotMember(OrganizationDto organization, UserDto user) {
- db.organizations().assertUserIsNotMemberOfOrganization(organization, user);
- SearchRequestBuilder request = es.client().prepareSearch(UserIndexDefinition.TYPE_USER)
- .setQuery(boolQuery()
- .must(termQuery(FIELD_ORGANIZATION_UUIDS, organization.getUuid()))
- .must(termQuery(FIELD_UUID, user.getUuid())));
- assertThat(request.get().getHits().getHits()).isEmpty();
- }
-
- private void assertOrgPermissionsOfUser(UserDto user, OrganizationDto organization, OrganizationPermission... permissions) {
- assertThat(dbClient.userPermissionDao().selectGlobalPermissionsOfUser(db.getSession(), user.getId(), organization.getUuid()).stream()
- .map(OrganizationPermission::fromKey))
- .containsOnly(permissions);
- }
-
- private void assertProjectPermissionsOfUser(UserDto user, ComponentDto project, String... permissions) {
- assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(db.getSession(), user.getId(), project.getId())).containsOnly(permissions);
- }
-
- private void insertProperty(String key, @Nullable String value, @Nullable Long resourceId, @Nullable Integer userId) {
- PropertyDto dto = new PropertyDto().setKey(key)
- .setResourceId(resourceId)
- .setUserId(userId)
- .setValue(value);
- db.properties().insertProperty(dto);
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganisationSupportTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganisationSupportTest.java
deleted file mode 100644
index fc4e4ea60ee..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganisationSupportTest.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.GroupPermissionDto;
-import org.sonar.db.permission.template.PermissionTemplateDto;
-import org.sonar.db.permission.template.PermissionTemplateGroupDto;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.rule.index.RuleIndexer;
-import org.sonar.server.usergroups.DefaultGroupCreatorImpl;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-public class OrganisationSupportTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- @Rule
- public DbTester dbTester = DbTester.create();
- @Rule
- public EsTester es = EsTester.create();
-
- private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester);
- private OrganizationFlags organizationFlags = new OrganizationFlagsImpl(dbTester.getDbClient());
- private RuleIndexer ruleIndexer = spy(new RuleIndexer(es.client(), dbTester.getDbClient()));
- private OrganisationSupport underTest = new OrganisationSupport(dbTester.getDbClient(), defaultOrganizationProvider, organizationFlags,
- new DefaultGroupCreatorImpl(dbTester.getDbClient()), new DefaultGroupFinder(dbTester.getDbClient()), ruleIndexer);
-
- @Test
- public void enabling_support_saves_internal_property_and_flags_caller_as_root() {
- UserDto user = dbTester.users().insertUser();
- UserDto otherUser = dbTester.users().insertUser();
- dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users");
- verifyFeatureEnabled(false);
- verifyRoot(user, false);
- verifyRoot(otherUser, false);
-
- call(user.getLogin());
-
- verifyFeatureEnabled(true);
- verifyRoot(user, true);
- verifyRoot(otherUser, false);
- }
-
- @Test
- public void enabling_support_creates_default_members_group_and_associate_org_members() {
- OrganizationDto defaultOrganization = dbTester.getDefaultOrganization();
- OrganizationDto anotherOrganization = dbTester.organizations().insert();
- UserDto user1 = dbTester.users().insertUser();
- UserDto user2 = dbTester.users().insertUser();
- UserDto userInAnotherOrganization = dbTester.users().insertUser();
- dbTester.organizations().addMember(defaultOrganization, user1);
- dbTester.organizations().addMember(defaultOrganization, user2);
- dbTester.organizations().addMember(anotherOrganization, userInAnotherOrganization);
- dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users");
-
- call(user1.getLogin());
-
- Optional<Integer> defaultGroupId = dbTester.getDbClient().organizationDao().getDefaultGroupId(dbTester.getSession(), defaultOrganization.getUuid());
- assertThat(defaultGroupId).isPresent();
- GroupDto membersGroup = dbTester.getDbClient().groupDao().selectById(dbTester.getSession(), defaultGroupId.get());
- assertThat(membersGroup).isNotNull();
- assertThat(membersGroup.getName()).isEqualTo("Members");
- assertThat(dbTester.getDbClient().groupMembershipDao().selectGroupIdsByUserId(dbTester.getSession(), user1.getId())).containsOnly(defaultGroupId.get());
- assertThat(dbTester.getDbClient().groupMembershipDao().selectGroupIdsByUserId(dbTester.getSession(), user2.getId())).containsOnly(defaultGroupId.get());
- assertThat(dbTester.getDbClient().groupMembershipDao().selectGroupIdsByUserId(dbTester.getSession(), userInAnotherOrganization.getId())).isEmpty();
- }
-
- @Test
- public void enabling_support_copy_sonar_users_permissions_to_members_group() {
- OrganizationDto defaultOrganization = dbTester.getDefaultOrganization();
- UserDto user = dbTester.users().insertUser();
- GroupDto sonarUsersGroup = dbTester.users().insertDefaultGroup(defaultOrganization, "sonar-users");
- ComponentDto project = dbTester.components().insertPrivateProject(defaultOrganization);
- dbTester.users().insertPermissionOnGroup(sonarUsersGroup, "user");
- dbTester.users().insertProjectPermissionOnGroup(sonarUsersGroup, "codeviewer", project);
- // Should be ignored
- GroupDto anotherGroup = dbTester.users().insertGroup();
- dbTester.users().insertPermissionOnGroup(anotherGroup, "admin");
-
- call(user.getLogin());
-
- int defaultGroupId = dbTester.getDbClient().organizationDao().getDefaultGroupId(dbTester.getSession(), defaultOrganization.getUuid()).get();
- assertThat(defaultGroupId).isNotEqualTo(sonarUsersGroup.getId());
- List<GroupPermissionDto> result = new ArrayList<>();
- dbTester.getDbClient().groupPermissionDao().selectAllPermissionsByGroupId(dbTester.getSession(), defaultOrganization.getUuid(), defaultGroupId,
- context -> result.add((GroupPermissionDto) context.getResultObject()));
- assertThat(result).extracting(GroupPermissionDto::getResourceId, GroupPermissionDto::getRole).containsOnly(
- tuple(null, "user"), tuple(project.getId(), "codeviewer"));
- }
-
- @Test
- public void enabling_support_copy_sonar_users_permission_templates_to_members_group() {
- OrganizationDto defaultOrganization = dbTester.getDefaultOrganization();
- UserDto user = dbTester.users().insertUser();
- GroupDto sonarUsersGroup = dbTester.users().insertDefaultGroup(defaultOrganization, "sonar-users");
- PermissionTemplateDto permissionTemplate = dbTester.permissionTemplates().insertTemplate(dbTester.getDefaultOrganization());
- dbTester.permissionTemplates().addGroupToTemplate(permissionTemplate, sonarUsersGroup, "user");
- dbTester.permissionTemplates().addGroupToTemplate(permissionTemplate, sonarUsersGroup, "admin");
- // Should be ignored
- GroupDto otherGroup = dbTester.users().insertGroup();
- dbTester.permissionTemplates().addGroupToTemplate(permissionTemplate, otherGroup, "user");
-
- call(user.getLogin());
-
- int defaultGroupId = dbTester.getDbClient().organizationDao().getDefaultGroupId(dbTester.getSession(), defaultOrganization.getUuid()).get();
- assertThat(dbTester.getDbClient().permissionTemplateDao().selectAllGroupPermissionTemplatesByGroupId(dbTester.getSession(), defaultGroupId))
- .extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getPermission)
- .containsOnly(tuple(defaultGroupId, "user"), tuple(defaultGroupId, "admin"));
- }
-
- @Test
- public void enabling_organizations_should_remove_template_rule_and_custom_rule() {
- RuleDefinitionDto normal = dbTester.rules().insert();
- RuleDefinitionDto template = dbTester.rules().insert(r -> r.setIsTemplate(true));
- RuleDefinitionDto custom = dbTester.rules().insert(r -> r.setTemplateId(template.getId()));
-
- UserDto user = dbTester.users().insertUser();
- dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users");
-
- assertThat(dbTester.getDbClient().ruleDao().selectAllDefinitions(dbTester.getSession()))
- .extracting(RuleDefinitionDto::getKey, RuleDefinitionDto::getStatus)
- .containsExactlyInAnyOrder(
- tuple(normal.getKey(), RuleStatus.READY),
- tuple(template.getKey(), RuleStatus.READY),
- tuple(custom.getKey(), RuleStatus.READY));
-
- call(user.getLogin());
-
- assertThat(dbTester.getDbClient().ruleDao().selectAllDefinitions(dbTester.getSession()))
- .extracting(RuleDefinitionDto::getKey, RuleDefinitionDto::getStatus)
- .containsExactlyInAnyOrder(
- tuple(normal.getKey(), RuleStatus.READY),
- tuple(template.getKey(), RuleStatus.REMOVED),
- tuple(custom.getKey(), RuleStatus.REMOVED));
-
- @SuppressWarnings("unchecked")
- Class<ArrayList<Integer>> listClass = (Class<ArrayList<Integer>>) (Class) ArrayList.class;
- ArgumentCaptor<ArrayList<Integer>> indexedRuleKeys = ArgumentCaptor.forClass(listClass);
- verify(ruleIndexer).commitAndIndex(any(), indexedRuleKeys.capture());
- assertThat(indexedRuleKeys.getValue()).containsExactlyInAnyOrder(template.getId(), custom.getId());
- }
-
- @Test
- public void throw_IAE_when_members_group_already_exists() {
- UserDto user = dbTester.users().insertUser();
- dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users");
- dbTester.users().insertGroup(dbTester.getDefaultOrganization(), "Members");
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("The group 'Members' already exist");
-
- call(user.getLogin());
- }
-
- @Test
- public void do_nothing_if_support_is_already_enabled() {
- dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users");
-
- call("foo");
- verifyFeatureEnabled(true);
-
- // the test could be improved to verify that
- // the caller user is not flagged as root
- // if he was not already root
- call("foo");
- verifyFeatureEnabled(true);
- }
-
- private void call(String login) {
- underTest.enable(login);
- }
-
- private void verifyFeatureEnabled(boolean enabled) {
- assertThat(organizationFlags.isEnabled(dbTester.getSession())).isEqualTo(enabled);
- }
-
- private void verifyRoot(UserDto user, boolean root) {
- dbTester.rootFlag().verify(user.getLogin(), root);
- }
-
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java
deleted file mode 100644
index 9eb1ed9f23b..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Consumer;
-import org.apache.commons.lang.RandomStringUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.utils.System2;
-import org.sonar.api.impl.utils.TestSystem2;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.util.SequenceUuidFactory;
-import org.sonar.core.util.UuidFactory;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ResourceTypesRule;
-import org.sonar.db.organization.DefaultTemplates;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.organization.OrganizationDto.Subscription;
-import org.sonar.db.permission.template.PermissionTemplateDto;
-import org.sonar.db.permission.template.PermissionTemplateGroupDto;
-import org.sonar.db.qualitygate.QualityGateDto;
-import org.sonar.db.qualityprofile.QProfileDto;
-import org.sonar.db.qualityprofile.RulesProfileDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserMembershipDto;
-import org.sonar.db.user.UserMembershipQuery;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.permission.PermissionService;
-import org.sonar.server.permission.PermissionServiceImpl;
-import org.sonar.server.qualityprofile.BuiltInQProfile;
-import org.sonar.server.qualityprofile.BuiltInQProfileRepositoryRule;
-import org.sonar.server.qualityprofile.QProfileName;
-import org.sonar.server.user.index.UserIndex;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.user.index.UserQuery;
-import org.sonar.server.usergroups.DefaultGroupCreator;
-import org.sonar.server.usergroups.DefaultGroupCreatorImpl;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.language.LanguageTesting.newLanguage;
-import static org.sonar.server.organization.OrganizationUpdater.NewOrganization.newOrganizationBuilder;
-
-public class OrganizationUpdaterImplTest {
- private static final long A_DATE = 12893434L;
-
- private OrganizationUpdater.NewOrganization FULL_POPULATED_NEW_ORGANIZATION = newOrganizationBuilder()
- .setName("a-name")
- .setKey("a-key")
- .setDescription("a-description")
- .setUrl("a-url")
- .setAvatarUrl("a-avatar")
- .build();
-
- private System2 system2 = new TestSystem2().setNow(A_DATE);
-
- private static Consumer<OrganizationDto> EMPTY_ORGANIZATION_CONSUMER = o -> {
- };
-
- @Rule
- public DbTester db = DbTester.create(system2);
- @Rule
- public EsTester es = EsTester.create();
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- @Rule
- public BuiltInQProfileRepositoryRule builtInQProfileRepositoryRule = new BuiltInQProfileRepositoryRule();
-
- private DbSession dbSession = db.getSession();
-
- private IllegalArgumentException exceptionThrownByOrganizationValidation = new IllegalArgumentException("simulate IAE thrown by OrganizationValidation");
- private DbClient dbClient = db.getDbClient();
- private UuidFactory uuidFactory = new SequenceUuidFactory();
- private OrganizationValidation organizationValidation = mock(OrganizationValidation.class);
- private UserIndexer userIndexer = new UserIndexer(dbClient, es.client());
- private UserIndex userIndex = new UserIndex(es.client(), system2);
- private DefaultGroupCreator defaultGroupCreator = new DefaultGroupCreatorImpl(dbClient);
-
- private ResourceTypes resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT);
- private PermissionService permissionService = new PermissionServiceImpl(resourceTypes);
-
- private OrganizationUpdaterImpl underTest = new OrganizationUpdaterImpl(dbClient, system2, uuidFactory, organizationValidation, userIndexer,
- builtInQProfileRepositoryRule, defaultGroupCreator, permissionService);
-
- @Test
- public void create_creates_organization_with_properties_from_NewOrganization_arg() throws OrganizationUpdater.KeyConflictException {
- builtInQProfileRepositoryRule.initialize();
- UserDto user = db.users().insertUser();
- db.qualityGates().insertBuiltInQualityGate();
-
- underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER);
-
- OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, FULL_POPULATED_NEW_ORGANIZATION.getKey()).get();
- assertThat(organization.getUuid()).isNotEmpty();
- assertThat(organization.getKey()).isEqualTo(FULL_POPULATED_NEW_ORGANIZATION.getKey());
- assertThat(organization.getName()).isEqualTo(FULL_POPULATED_NEW_ORGANIZATION.getName());
- assertThat(organization.getDescription()).isEqualTo(FULL_POPULATED_NEW_ORGANIZATION.getDescription());
- assertThat(organization.getUrl()).isEqualTo(FULL_POPULATED_NEW_ORGANIZATION.getUrl());
- assertThat(organization.getAvatarUrl()).isEqualTo(FULL_POPULATED_NEW_ORGANIZATION.getAvatar());
- assertThat(organization.getSubscription()).isEqualTo(Subscription.FREE);
- assertThat(organization.getCreatedAt()).isEqualTo(A_DATE);
- assertThat(organization.getUpdatedAt()).isEqualTo(A_DATE);
- }
-
- @Test
- public void create_creates_owners_group_with_all_permissions_for_new_organization_and_add_current_user_to_it() throws OrganizationUpdater.KeyConflictException {
- UserDto user = db.users().insertUser();
- builtInQProfileRepositoryRule.initialize();
- db.qualityGates().insertBuiltInQualityGate();
-
- underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER);
-
- verifyGroupOwners(user, FULL_POPULATED_NEW_ORGANIZATION.getKey(), FULL_POPULATED_NEW_ORGANIZATION.getName());
- }
-
- @Test
- public void create_creates_members_group_and_add_current_user_to_it() throws OrganizationUpdater.KeyConflictException {
- UserDto user = db.users().insertUser();
- builtInQProfileRepositoryRule.initialize();
- db.qualityGates().insertBuiltInQualityGate();
-
- underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER);
-
- verifyMembersGroup(user, FULL_POPULATED_NEW_ORGANIZATION.getKey());
- }
-
- @Test
- public void create_does_not_require_description_url_and_avatar_to_be_non_null() throws OrganizationUpdater.KeyConflictException {
- builtInQProfileRepositoryRule.initialize();
- UserDto user = db.users().insertUser();
- db.qualityGates().insertBuiltInQualityGate();
-
- underTest.create(dbSession, user, newOrganizationBuilder()
- .setKey("key")
- .setName("name")
- .build(), EMPTY_ORGANIZATION_CONSUMER);
-
- OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, "key").get();
- assertThat(organization.getKey()).isEqualTo("key");
- assertThat(organization.getName()).isEqualTo("name");
- assertThat(organization.getDescription()).isNull();
- assertThat(organization.getUrl()).isNull();
- assertThat(organization.getAvatarUrl()).isNull();
- }
-
- @Test
- public void create_creates_default_template_for_new_organization() throws OrganizationUpdater.KeyConflictException {
- builtInQProfileRepositoryRule.initialize();
- UserDto user = db.users().insertUser();
- db.qualityGates().insertBuiltInQualityGate();
-
- underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER);
-
- OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, FULL_POPULATED_NEW_ORGANIZATION.getKey()).get();
- GroupDto ownersGroup = dbClient.groupDao().selectByName(dbSession, organization.getUuid(), "Owners").get();
- int defaultGroupId = dbClient.organizationDao().getDefaultGroupId(dbSession, organization.getUuid()).get();
- PermissionTemplateDto defaultTemplate = dbClient.permissionTemplateDao().selectByName(dbSession, organization.getUuid(), "default template");
- assertThat(defaultTemplate.getName()).isEqualTo("Default template");
- assertThat(defaultTemplate.getDescription()).isEqualTo("Default permission template of organization " + FULL_POPULATED_NEW_ORGANIZATION.getName());
- DefaultTemplates defaultTemplates = dbClient.organizationDao().getDefaultTemplates(dbSession, organization.getUuid()).get();
- assertThat(defaultTemplates.getProjectUuid()).isEqualTo(defaultTemplate.getUuid());
- assertThat(defaultTemplates.getApplicationsUuid()).isNull();
- assertThat(dbClient.permissionTemplateDao().selectGroupPermissionsByTemplateId(dbSession, defaultTemplate.getId()))
- .extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getPermission)
- .containsOnly(
- tuple(ownersGroup.getId(), UserRole.ADMIN),
- tuple(ownersGroup.getId(), GlobalPermissions.SCAN_EXECUTION),
- tuple(defaultGroupId, UserRole.USER),
- tuple(defaultGroupId, UserRole.CODEVIEWER),
- tuple(defaultGroupId, UserRole.ISSUE_ADMIN),
- tuple(defaultGroupId, UserRole.SECURITYHOTSPOT_ADMIN));
- }
-
- @Test
- public void create_add_current_user_as_member_of_organization() throws OrganizationUpdater.KeyConflictException {
- UserDto user = db.users().insertUser();
- builtInQProfileRepositoryRule.initialize();
- db.qualityGates().insertBuiltInQualityGate();
-
- OrganizationDto result = underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER);
-
- assertThat(dbClient.organizationMemberDao().select(dbSession, result.getUuid(), user.getId())).isPresent();
- assertThat(userIndex.search(UserQuery.builder().setOrganizationUuid(result.getUuid()).setTextQuery(user.getLogin()).build(), new SearchOptions()).getTotal()).isEqualTo(1L);
- }
-
- @Test
- public void create_associates_to_built_in_quality_profiles() throws OrganizationUpdater.KeyConflictException {
- BuiltInQProfile builtIn1 = builtInQProfileRepositoryRule.add(newLanguage("foo"), "qp1", true);
- BuiltInQProfile builtIn2 = builtInQProfileRepositoryRule.add(newLanguage("foo"), "qp2");
- builtInQProfileRepositoryRule.initialize();
- insertRulesProfile(builtIn1);
- insertRulesProfile(builtIn2);
- UserDto user = db.users().insertUser();
- db.qualityGates().insertBuiltInQualityGate();
-
- underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER);
-
- OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, FULL_POPULATED_NEW_ORGANIZATION.getKey()).get();
- List<QProfileDto> profiles = dbClient.qualityProfileDao().selectOrderedByOrganizationUuid(dbSession, organization);
- assertThat(profiles).extracting(p -> new QProfileName(p.getLanguage(), p.getName())).containsExactlyInAnyOrder(
- builtIn1.getQProfileName(), builtIn2.getQProfileName());
- assertThat(dbClient.qualityProfileDao().selectDefaultProfile(dbSession, organization, "foo").getName())
- .isEqualTo("qp1");
- }
-
- private void insertRulesProfile(BuiltInQProfile builtIn) {
- RulesProfileDto dto = new RulesProfileDto()
- .setIsBuiltIn(true)
- .setKee(RandomStringUtils.randomAlphabetic(40))
- .setLanguage(builtIn.getLanguage())
- .setName(builtIn.getName());
- dbClient.qualityProfileDao().insert(db.getSession(), dto);
- db.commit();
- }
-
- @Test
- public void create_associates_to_built_in_quality_gate() throws OrganizationUpdater.KeyConflictException {
- QualityGateDto builtInQualityGate = db.qualityGates().insertBuiltInQualityGate();
- builtInQProfileRepositoryRule.initialize();
- UserDto user = db.users().insertUser();
-
- underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, o -> {
- });
-
- OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, FULL_POPULATED_NEW_ORGANIZATION.getKey()).get();
- assertThat(dbClient.qualityGateDao().selectDefault(dbSession, organization).getUuid()).isEqualTo(builtInQualityGate.getUuid());
- }
-
- @Test
- public void create_calls_consumer() throws OrganizationUpdater.KeyConflictException {
- UserDto user = db.users().insertUser();
- builtInQProfileRepositoryRule.initialize();
- db.qualityGates().insertBuiltInQualityGate();
- Boolean[] isConsumerCalled = new Boolean[]{false};
-
- underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, o -> {
- isConsumerCalled[0] = true;
- });
-
- assertThat(isConsumerCalled[0]).isEqualTo(true);
- }
-
- @Test
- public void create_throws_NPE_if_NewOrganization_arg_is_null() throws OrganizationUpdater.KeyConflictException {
- UserDto user = db.users().insertUser();
-
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("newOrganization can't be null");
-
- underTest.create(dbSession, user, null, EMPTY_ORGANIZATION_CONSUMER);
- }
-
- @Test
- public void create_throws_exception_thrown_by_checkValidKey() throws OrganizationUpdater.KeyConflictException {
- UserDto user = db.users().insertUser();
-
- when(organizationValidation.checkKey(FULL_POPULATED_NEW_ORGANIZATION.getKey()))
- .thenThrow(exceptionThrownByOrganizationValidation);
-
- createThrowsExceptionThrownByOrganizationValidation(user);
- }
-
- @Test
- public void create_throws_exception_thrown_by_checkValidDescription() throws OrganizationUpdater.KeyConflictException {
- UserDto user = db.users().insertUser();
-
- when(organizationValidation.checkDescription(FULL_POPULATED_NEW_ORGANIZATION.getDescription())).thenThrow(exceptionThrownByOrganizationValidation);
-
- createThrowsExceptionThrownByOrganizationValidation(user);
- }
-
- @Test
- public void create_throws_exception_thrown_by_checkValidUrl() throws OrganizationUpdater.KeyConflictException {
- UserDto user = db.users().insertUser();
-
- when(organizationValidation.checkUrl(FULL_POPULATED_NEW_ORGANIZATION.getUrl())).thenThrow(exceptionThrownByOrganizationValidation);
-
- createThrowsExceptionThrownByOrganizationValidation(user);
- }
-
- @Test
- public void create_throws_exception_thrown_by_checkValidAvatar() throws OrganizationUpdater.KeyConflictException {
- UserDto user = db.users().insertUser();
-
- when(organizationValidation.checkAvatar(FULL_POPULATED_NEW_ORGANIZATION.getAvatar())).thenThrow(exceptionThrownByOrganizationValidation);
-
- createThrowsExceptionThrownByOrganizationValidation(user);
- }
-
- private void createThrowsExceptionThrownByOrganizationValidation(UserDto user) throws OrganizationUpdater.KeyConflictException {
- try {
- underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER);
- fail(exceptionThrownByOrganizationValidation + " should have been thrown");
- } catch (IllegalArgumentException e) {
- assertThat(e).isSameAs(exceptionThrownByOrganizationValidation);
- }
- }
-
- @Test
- public void create_fails_with_KeyConflictException_if_org_with_key_in_NewOrganization_arg_already_exists_in_db() throws OrganizationUpdater.KeyConflictException {
- db.organizations().insertForKey(FULL_POPULATED_NEW_ORGANIZATION.getKey());
- UserDto user = db.users().insertUser();
-
- expectedException.expect(OrganizationUpdater.KeyConflictException.class);
- expectedException.expectMessage("Organization key '" + FULL_POPULATED_NEW_ORGANIZATION.getKey() + "' is already used");
-
- underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER);
- }
-
- @Test
- public void update_personal_organization() {
- OrganizationDto organization = db.organizations().insert(o -> o.setKey("old login"));
- when(organizationValidation.generateKeyFrom("new_login")).thenReturn("new_login");
-
- underTest.updateOrganizationKey(dbSession, organization, "new_login");
-
- OrganizationDto organizationReloaded = dbClient.organizationDao().selectByUuid(dbSession, organization.getUuid()).get();
- assertThat(organizationReloaded.getKey()).isEqualTo("new_login");
- }
-
- @Test
- public void does_not_update_personal_organization_when_generated_organization_key_does_not_change() {
- OrganizationDto organization = db.organizations().insert(o -> o.setKey("login"));
- when(organizationValidation.generateKeyFrom("Login")).thenReturn("login");
-
- underTest.updateOrganizationKey(dbSession, organization, "Login");
-
- OrganizationDto organizationReloaded = dbClient.organizationDao().selectByUuid(dbSession, organization.getUuid()).get();
- assertThat(organizationReloaded.getKey()).isEqualTo("login");
- }
-
- @Test
- public void fail_to_update_personal_organization_when_new_key_already_exist() {
- OrganizationDto organization = db.organizations().insert();
- db.organizations().insert(o -> o.setKey("new_login"));
- when(organizationValidation.generateKeyFrom("new_login")).thenReturn("new_login");
-
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Can't create organization with key 'new_login' because an organization with this key already exists");
-
- underTest.updateOrganizationKey(dbSession, organization, "new_login");
- }
-
- private void verifyGroupOwners(UserDto user, String organizationKey, String organizationName) {
- OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, organizationKey).get();
- Optional<GroupDto> groupOpt = dbClient.groupDao().selectByName(dbSession, organization.getUuid(), "Owners");
- assertThat(groupOpt).isPresent();
- GroupDto groupDto = groupOpt.get();
- assertThat(groupDto.getDescription()).isEqualTo("Owners of organization");
-
- assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, groupDto.getOrganizationUuid(), groupDto.getId()))
- .containsOnly(GlobalPermissions.ALL.toArray(new String[GlobalPermissions.ALL.size()]));
- List<UserMembershipDto> members = dbClient.groupMembershipDao().selectMembers(
- dbSession,
- UserMembershipQuery.builder()
- .organizationUuid(organization.getUuid())
- .groupId(groupDto.getId())
- .membership(UserMembershipQuery.IN).build(),
- 0, Integer.MAX_VALUE);
- assertThat(members)
- .extracting(UserMembershipDto::getLogin)
- .containsOnly(user.getLogin());
- }
-
- private void verifyMembersGroup(UserDto user, String organizationKey) {
- OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, organizationKey).get();
- Optional<GroupDto> groupOpt = dbClient.groupDao().selectByName(dbSession, organization.getUuid(), "Members");
- assertThat(groupOpt).isPresent();
- GroupDto groupDto = groupOpt.get();
- assertThat(groupDto.getDescription()).isEqualTo("All members of the organization");
-
- assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, groupDto.getOrganizationUuid(), groupDto.getId())).isEmpty();
- List<UserMembershipDto> members = dbClient.groupMembershipDao().selectMembers(
- dbSession,
- UserMembershipQuery.builder()
- .organizationUuid(organization.getUuid())
- .groupId(groupDto.getId())
- .membership(UserMembershipQuery.IN).build(),
- 0, Integer.MAX_VALUE);
- assertThat(members)
- .extracting(UserMembershipDto::getLogin)
- .containsOnly(user.getLogin());
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java
deleted file mode 100644
index 1f9cfe7ce1f..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import com.google.common.base.Strings;
-import java.util.Random;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-
-public class OrganizationValidationImplTest {
- private static final String STRING_32_CHARS = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
- private static final String STRING_64_CHARS = STRING_32_CHARS + STRING_32_CHARS;
- private static final String STRING_256_CHARS = STRING_64_CHARS + STRING_64_CHARS + STRING_64_CHARS + STRING_64_CHARS;
-
- private static final String STRING_255_CHARS = Strings.repeat("a", 255);
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- private OrganizationValidationImpl underTest = new OrganizationValidationImpl();
-
- @Test
- public void checkValidKey_throws_NPE_if_arg_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("key can't be null");
-
- underTest.checkKey(null);
- }
-
- @Test
- public void checkValidKey_throws_IAE_if_arg_is_empty() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Key must not be empty");
-
- underTest.checkKey("");
- }
-
- @Test
- public void checkValidKey_throws_IAE_if_key_is_empty() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Key must not be empty");
-
- underTest.checkKey("");
- }
-
- @Test
- public void checkValidKey_does_not_fail_if_arg_is_1_to_255_chars_long() {
- String str = "a";
- for (int i = 0; i < 254; i++) {
- underTest.checkKey(str);
- str += "a";
- }
- }
-
- @Test
- public void checkValidKey_throws_IAE_when_more_than_300_characters() {
- String key = STRING_255_CHARS + "b";
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Key '" + key + "' must be at most 255 chars long");
-
- underTest.checkKey(key);
- }
-
- @Test
- public void checkValidKey_throws_IAE_if_arg_contains_invalid_chars() {
- char[] invalidChars = {'é', '<', '@'};
-
- for (char invalidChar : invalidChars) {
- String str = "aa" + invalidChar;
- try {
- underTest.checkKey(str);
- fail("A IllegalArgumentException should have been thrown");
- } catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("Key '" + str + "' contains at least one invalid char");
- }
- }
- }
-
- @Test
- public void checkValidName_throws_NPE_if_arg_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("name can't be null");
-
- underTest.checkName(null);
- }
-
- @Test
- public void checkValidName_throws_IAE_if_empty() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Name must not be empty");
-
- underTest.checkName("");
- }
-
- @Test
- public void checkValidName_does_not_fail_if_arg_is_1_to_255_chars_long() {
- String str = "a";
- for (int i = 0; i < 254; i++) {
- underTest.checkName(str);
- str += "a";
- }
- }
-
- @Test
- public void checkValidName_throws_IAE_when_more_than_255_characters() {
- String str = STRING_255_CHARS + "b";
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Name '" + str + "' must be at most 255 chars long");
-
- underTest.checkName(str);
- }
-
- @Test
- public void checkValidDescription_does_not_fail_if_arg_is_null() {
- underTest.checkDescription(null);
- }
-
- @Test
- public void checkValidDescription_does_not_fail_if_arg_is_empty() {
- underTest.checkDescription("");
- }
-
- @Test
- public void checkValidDescription_does_not_fail_if_arg_is_1_to_256_chars_long() {
- String str = "1";
- for (int i = 0; i < 256; i++) {
- underTest.checkDescription(str);
- str += "a";
- }
- }
-
- @Test
- public void checkValidDescription_throws_IAE_if_arg_is_more_than_256_chars_long() {
- String str = STRING_256_CHARS;
- underTest.checkDescription(str);
- for (int i = 0; i < 5 + Math.abs(new Random().nextInt(10)); i++) {
- str += "c";
- try {
- underTest.checkDescription(str);
- fail("A IllegalArgumentException should have been thrown");
- } catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("Description '" + str + "' must be at most 256 chars long");
- }
- }
- }
-
- @Test
- public void checkValidUrl_does_not_fail_if_arg_is_null() {
- underTest.checkUrl(null);
- }
-
- @Test
- public void checkValidUrl_does_not_fail_if_arg_is_1_to_256_chars_long() {
- String str = "1";
- for (int i = 0; i < 256; i++) {
- underTest.checkUrl(str);
- str += "a";
- }
- }
-
- @Test
- public void checkValidUrl_throws_IAE_if_arg_is_more_than_256_chars_long() {
- String str = STRING_256_CHARS;
- underTest.checkUrl(str);
- for (int i = 0; i < 5 + Math.abs(new Random().nextInt(10)); i++) {
- str += "c";
- try {
- underTest.checkUrl(str);
- fail("A IllegalArgumentException should have been thrown");
- } catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("Url '" + str + "' must be at most 256 chars long");
- }
- }
- }
-
- @Test
- public void checkValidAvatar_does_not_fail_if_arg_is_null() {
- underTest.checkAvatar(null);
- }
-
- @Test
- public void checkValidAvatar_does_not_fail_if_arg_is_1_to_256_chars_long() {
- String str = "1";
- for (int i = 0; i < 256; i++) {
- underTest.checkAvatar(str);
- str += "a";
- }
- }
-
- @Test
- public void checkValidAvatar_throws_IAE_if_arg_is_more_than_256_chars_long() {
- String str = STRING_256_CHARS;
- underTest.checkAvatar(str);
- for (int i = 0; i < 5 + Math.abs(new Random().nextInt(10)); i++) {
- str += "c";
- try {
- underTest.checkAvatar(str);
- fail("A IllegalArgumentException should have been thrown");
- } catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("Avatar '" + str + "' must be at most 256 chars long");
- }
- }
- }
-
- @Test
- public void generateKeyFrom_returns_slug_of_arg() {
- assertThat(underTest.generateKeyFrom("foo")).isEqualTo("foo");
- assertThat(underTest.generateKeyFrom(" FOO ")).isEqualTo("foo");
- assertThat(underTest.generateKeyFrom("he's here")).isEqualTo("he-s-here");
- assertThat(underTest.generateKeyFrom("foo-bar")).isEqualTo("foo-bar");
- assertThat(underTest.generateKeyFrom("foo_bar")).isEqualTo("foo_bar");
- assertThat(underTest.generateKeyFrom("accents éà")).isEqualTo("accents-ea");
- assertThat(underTest.generateKeyFrom("<foo>")).isEqualTo("foo");
- assertThat(underTest.generateKeyFrom("<\"foo:\">")).isEqualTo("foo");
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionServiceImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionServiceImplTest.java
deleted file mode 100644
index e6abb50487f..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionServiceImplTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.permission;
-
-import org.junit.Test;
-import org.sonar.db.component.ResourceTypesRule;
-import org.sonar.db.permission.OrganizationPermission;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class PermissionServiceImplTest {
-
- private ResourceTypesRule resourceTypesRule = new ResourceTypesRule().setRootQualifiers("APP", "VW");
- private PermissionServiceImpl underTest = new PermissionServiceImpl(resourceTypesRule);
-
- @Test
- public void organizationPermissions_must_be_ordered() {
- assertThat(underTest.getAllOrganizationPermissions())
- .extracting(OrganizationPermission::getKey)
- .containsExactly("admin", "gateadmin", "profileadmin", "provisioning", "scan", "applicationcreator", "portfoliocreator");
- }
-
- @Test
- public void projectPermissions_must_be_ordered() {
- assertThat(underTest.getAllProjectPermissions())
- .containsExactly("admin", "codeviewer", "issueadmin", "securityhotspotadmin", "scan", "user");
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationHandlerTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationHandlerTest.java
deleted file mode 100644
index 361f291edb4..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationHandlerTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.Random;
-import java.util.Set;
-import java.util.stream.IntStream;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.EmailSubscriberDto;
-import org.sonar.db.permission.AuthorizationDao;
-import org.sonar.server.notification.email.EmailNotificationChannel;
-
-import static java.util.Collections.emptySet;
-import static java.util.stream.Collectors.toSet;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-public class BuiltInQPChangeNotificationHandlerTest {
- private DbClient dbClient = mock(DbClient.class);
- private DbSession dbSession = mock(DbSession.class);
- private AuthorizationDao authorizationDao = mock(AuthorizationDao.class);
- private EmailNotificationChannel emailNotificationChannel = mock(EmailNotificationChannel.class);
-
- private BuiltInQPChangeNotificationHandler underTest = new BuiltInQPChangeNotificationHandler(dbClient, emailNotificationChannel);
-
- @Before
- public void wire_mocks() {
- when(dbClient.openSession(false)).thenReturn(dbSession);
- when(dbClient.authorizationDao()).thenReturn(authorizationDao);
- }
-
- @Test
- public void getMetadata_returns_empty() {
- assertThat(underTest.getMetadata()).isEmpty();
- }
-
- @Test
- public void getNotificationClass_is_BuiltInQPChangeNotification() {
- assertThat(underTest.getNotificationClass()).isEqualTo(BuiltInQPChangeNotification.class);
- }
-
- @Test
- public void deliver_has_no_effect_if_emailNotificationChannel_is_disabled() {
- when(emailNotificationChannel.isActivated()).thenReturn(false);
- Set<BuiltInQPChangeNotification> notifications = IntStream.range(0, 1 + new Random().nextInt(10))
- .mapToObj(i -> mock(BuiltInQPChangeNotification.class))
- .collect(toSet());
-
- int deliver = underTest.deliver(notifications);
-
- assertThat(deliver).isZero();
- verify(emailNotificationChannel).isActivated();
- verifyNoMoreInteractions(emailNotificationChannel);
- verifyZeroInteractions(dbClient);
- notifications.forEach(Mockito::verifyZeroInteractions);
- }
-
- @Test
- public void deliver_has_no_effect_if_there_is_no_global_administer_email_subscriber() {
- when(emailNotificationChannel.isActivated()).thenReturn(true);
- Set<BuiltInQPChangeNotification> notifications = IntStream.range(0, 1 + new Random().nextInt(10))
- .mapToObj(i -> mock(BuiltInQPChangeNotification.class))
- .collect(toSet());
- when(authorizationDao.selectQualityProfileAdministratorLogins(dbSession))
- .thenReturn(emptySet());
-
- int deliver = underTest.deliver(notifications);
-
- assertThat(deliver).isZero();
- verify(emailNotificationChannel).isActivated();
- verifyNoMoreInteractions(emailNotificationChannel);
- verify(dbClient).openSession(false);
- verify(dbClient).authorizationDao();
- verifyNoMoreInteractions(dbClient);
- verify(authorizationDao).selectQualityProfileAdministratorLogins(dbSession);
- verifyNoMoreInteractions(authorizationDao);
- notifications.forEach(Mockito::verifyZeroInteractions);
- }
-
- @Test
- public void deliver_create_emailRequest_for_each_notification_and_for_each_global_administer_email_subscriber() {
- when(emailNotificationChannel.isActivated()).thenReturn(true);
- Set<BuiltInQPChangeNotification> notifications = IntStream.range(0, 1 + new Random().nextInt(10))
- .mapToObj(i -> mock(BuiltInQPChangeNotification.class))
- .collect(toSet());
- Set<EmailSubscriberDto> emailSubscribers = IntStream.range(0, 1 + new Random().nextInt(10))
- .mapToObj(i -> EmailSubscriberDto.create("login_" + i, true, "login_" + i + "@foo"))
- .collect(toSet());
- when(authorizationDao.selectQualityProfileAdministratorLogins(dbSession))
- .thenReturn(emailSubscribers);
- Set<EmailNotificationChannel.EmailDeliveryRequest> expectedRequests = notifications.stream()
- .flatMap(notification -> emailSubscribers.stream().map(subscriber -> new EmailNotificationChannel.EmailDeliveryRequest(subscriber.getEmail(), notification)))
- .collect(toSet());
- int deliveries = new Random().nextInt(expectedRequests.size());
- when(emailNotificationChannel.deliverAll(expectedRequests)).thenReturn(deliveries);
-
- int deliver = underTest.deliver(notifications);
-
- assertThat(deliver).isEqualTo(deliveries);
- verify(emailNotificationChannel).isActivated();
- verify(emailNotificationChannel).deliverAll(expectedRequests);
- verifyNoMoreInteractions(emailNotificationChannel);
- verify(dbClient).openSession(false);
- verify(dbClient).authorizationDao();
- verifyNoMoreInteractions(dbClient);
- verify(authorizationDao).selectQualityProfileAdministratorLogins(dbSession);
- verifyNoMoreInteractions(authorizationDao);
- notifications.forEach(Mockito::verifyZeroInteractions);
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTemplateTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTemplateTest.java
deleted file mode 100644
index 3324486882b..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTemplateTest.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.platform.Server;
-import org.sonar.server.issue.notification.EmailMessage;
-import org.sonar.server.qualityprofile.BuiltInQPChangeNotificationBuilder.Profile;
-
-import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.utils.DateUtils.formatDate;
-
-public class BuiltInQPChangeNotificationTemplateTest {
-
- private Server server = mock(Server.class);
-
- private BuiltInQPChangeNotificationTemplate underTest = new BuiltInQPChangeNotificationTemplate(server);
-
- @Before
- public void setUp() throws Exception {
- when(server.getPublicRootUrl()).thenReturn("http://" + randomAlphanumeric(10));
- }
-
- @Test
- public void notification_contains_a_subject() {
- String profileName = newProfileName();
- String languageKey = newLanguageKey();
- String languageName = newLanguageName();
- BuiltInQPChangeNotificationBuilder notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName)
- .setLanguageKey(languageKey)
- .setLanguageName(languageName)
- .setNewRules(2)
- .build());
-
- EmailMessage emailMessage = underTest.format(notification.build());
-
- assertThat(emailMessage.getSubject()).isEqualTo("Built-in quality profiles have been updated");
- }
-
- @Test
- public void notification_contains_count_of_new_rules() {
- String profileName = newProfileName();
- String languageKey = newLanguageKey();
- String languageName = newLanguageName();
- BuiltInQPChangeNotificationBuilder notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName)
- .setLanguageKey(languageKey)
- .setLanguageName(languageName)
- .setNewRules(2)
- .build());
-
- EmailMessage emailMessage = underTest.format(notification.build());
-
- assertMessage(emailMessage, "\n 2 new rules\n");
- }
-
- @Test
- public void notification_contains_count_of_updated_rules() {
- String profileName = newProfileName();
- String languageKey = newLanguageKey();
- String languageName = newLanguageName();
- BuiltInQPChangeNotificationBuilder notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName)
- .setLanguageKey(languageKey)
- .setLanguageName(languageName)
- .setUpdatedRules(2)
- .build());
-
- EmailMessage emailMessage = underTest.format(notification.build());
-
- assertMessage(emailMessage, "\n 2 rules have been updated\n");
- }
-
- @Test
- public void notification_contains_count_of_removed_rules() {
- String profileName = newProfileName();
- String languageKey = newLanguageKey();
- String languageName = newLanguageName();
- BuiltInQPChangeNotificationBuilder notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName)
- .setLanguageKey(languageKey)
- .setLanguageName(languageName)
- .setRemovedRules(2)
- .build());
-
- EmailMessage emailMessage = underTest.format(notification.build());
-
- assertMessage(emailMessage, "\n 2 rules removed\n");
- }
-
- @Test
- public void notification_supports_grammar_for_single_rule_added_removed_or_updated() {
- String profileName = newProfileName();
- String languageKey = newLanguageKey();
- String languageName = newLanguageName();
- BuiltInQPChangeNotificationBuilder notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName)
- .setLanguageKey(languageKey)
- .setLanguageName(languageName)
- .setNewRules(1)
- .setUpdatedRules(1)
- .setRemovedRules(1)
- .build());
-
- EmailMessage emailMessage = underTest.format(notification.build());
-
- assertThat(emailMessage.getMessage())
- .contains("\n 1 new rule\n")
- .contains("\n 1 rule has been updated\n")
- .contains("\n 1 rule removed\n");
- }
-
- @Test
- public void notification_contains_list_of_new_updated_and_removed_rules() {
- String profileName = newProfileName();
- String languageKey = newLanguageKey();
- String languageName = newLanguageName();
- BuiltInQPChangeNotificationBuilder notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName)
- .setLanguageKey(languageKey)
- .setLanguageName(languageName)
- .setNewRules(2)
- .setUpdatedRules(3)
- .setRemovedRules(4)
- .build());
-
- EmailMessage emailMessage = underTest.format(notification.build());
-
- assertMessage(emailMessage,
- "\n" +
- " 2 new rules\n" +
- " 3 rules have been updated\n" +
- " 4 rules removed\n");
- }
-
- @Test
- public void notification_contains_many_profiles() {
- String profileName1 = "profile1_" + randomAlphanumeric(20);
- String languageKey1 = "langkey1_" + randomAlphanumeric(20);
- String languageName1 = "langName1_" + randomAlphanumeric(20);
- String profileName2 = "profile2_" + randomAlphanumeric(20);
- String languageKey2 = "langkey2_" + randomAlphanumeric(20);
- String languageName2 = "langName2_" + randomAlphanumeric(20);
- BuiltInQPChangeNotificationBuilder notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName1)
- .setLanguageKey(languageKey1)
- .setLanguageName(languageName1)
- .setNewRules(2)
- .build())
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName2)
- .setLanguageKey(languageKey2)
- .setLanguageName(languageName2)
- .setNewRules(13)
- .build());
-
- EmailMessage emailMessage = underTest.format(notification.build());
-
- assertThat(emailMessage.getMessage()).containsSubsequence("The following built-in profiles have been updated:\n",
- profileTitleText(profileName1, languageKey1, languageName1),
- " 2 new rules\n",
- profileTitleText(profileName2, languageKey2, languageName2),
- " 13 new rules\n",
- "This is a good time to review your quality profiles and update them to benefit from the latest evolutions: " + server.getPublicRootUrl() + "/profiles");
- }
-
- @Test
- public void notification_contains_profiles_sorted_by_language_then_by_profile_name() {
- String languageKey1 = "langkey1_" + randomAlphanumeric(20);
- String languageName1 = "langName1_" + randomAlphanumeric(20);
- String languageKey2 = "langKey2_" + randomAlphanumeric(20);
- String languageName2 = "langName2_" + randomAlphanumeric(20);
- String profileName1 = "profile1_" + randomAlphanumeric(20);
- String profileName2 = "profile2_" + randomAlphanumeric(20);
- String profileName3 = "profile3_" + randomAlphanumeric(20);
- BuiltInQPChangeNotificationBuilder notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder().setProfileName(profileName3).setLanguageKey(languageKey2).setLanguageName(languageName2).build())
- .addProfile(Profile.newBuilder().setProfileName(profileName2).setLanguageKey(languageKey1).setLanguageName(languageName1).build())
- .addProfile(Profile.newBuilder().setProfileName(profileName1).setLanguageKey(languageKey2).setLanguageName(languageName2).build());
-
- EmailMessage emailMessage = underTest.format(notification.build());
-
- assertThat(emailMessage.getMessage()).containsSubsequence(
- "\"" + profileName2 + "\" - " + languageName1,
- "\"" + profileName1 + "\" - " + languageName2,
- "\"" + profileName3 + "\" - " + languageName2);
- }
-
- @Test
- public void notification_contains_encoded_profile_name() {
- BuiltInQPChangeNotificationBuilder notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName("Sonar Way")
- .setLanguageKey("java")
- .setLanguageName(newLanguageName())
- .build());
-
- EmailMessage emailMessage = underTest.format(notification.build());
-
- assertThat(emailMessage.getMessage()).contains(server.getPublicRootUrl() + "/profiles/changelog?language=java&name=Sonar+Way");
- }
-
- @Test
- public void notification_contains_from_and_to_date() {
- String profileName = newProfileName();
- String languageKey = newLanguageKey();
- String languageName = newLanguageName();
- long startDate = 1_000_000_000_000L;
- long endDate = startDate + 1_100_000_000_000L;
- BuiltInQPChangeNotificationBuilder notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName)
- .setLanguageKey(languageKey)
- .setLanguageName(languageName)
- .setStartDate(startDate)
- .setEndDate(endDate)
- .build());
-
- EmailMessage emailMessage = underTest.format(notification.build());
-
- assertMessage(emailMessage,
- profileTitleText(profileName, languageKey, languageName, formatDate(new Date(startDate)), formatDate(new Date(endDate))));
- }
-
- private void assertMessage(EmailMessage emailMessage, String expectedProfileDetails) {
- assertThat(emailMessage.getMessage())
- .containsSubsequence(
- "The following built-in profiles have been updated:\n\n",
- expectedProfileDetails,
- "\nThis is a good time to review your quality profiles and update them to benefit from the latest evolutions: " + server.getPublicRootUrl() + "/profiles");
- }
-
- private String profileTitleText(String profileName, String languageKey, String languageName) {
- return "\"" + profileName + "\" - " + languageName + ": " + server.getPublicRootUrl() + "/profiles/changelog?language=" + languageKey + "&name=" + profileName;
- }
-
- private String profileTitleText(String profileName, String languageKey, String languageName, String startDate, String endDate) {
- return "\"" + profileName + "\" - " + languageName + ": " + server.getPublicRootUrl() + "/profiles/changelog?language=" + languageKey + "&name=" + profileName +
- "&since=" + startDate + "&to=" + endDate + "\n";
- }
-
- private static String newProfileName() {
- return "profileName_" + randomAlphanumeric(20);
- }
-
- private static String newLanguageName() {
- return "languageName_" + randomAlphanumeric(20);
- }
-
- private static String newLanguageKey() {
- return "languageKey_" + randomAlphanumeric(20);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTest.java
deleted file mode 100644
index d3cd519bb2a..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQPChangeNotificationTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.Random;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.notifications.Notification;
-import org.sonar.server.qualityprofile.BuiltInQPChangeNotificationBuilder.Profile;
-
-import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
-
-public class BuiltInQPChangeNotificationTest {
-
- private static final Random RANDOM = new Random();
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Test
- public void serialize_and_parse_no_profile() {
- Notification notification = new BuiltInQPChangeNotificationBuilder().build();
-
- BuiltInQPChangeNotificationBuilder result = BuiltInQPChangeNotificationBuilder.parse(notification);
-
- assertThat(result.getProfiles()).isEmpty();
- }
-
- @Test
- public void serialize_and_parse_single_profile() {
- String profileName = randomAlphanumeric(20);
- String languageKey = randomAlphanumeric(20);
- String languageName = randomAlphanumeric(20);
- int newRules = RANDOM.nextInt(5000);
- int updatedRules = RANDOM.nextInt(5000);
- int removedRules = RANDOM.nextInt(5000);
- long startDate = RANDOM.nextInt(5000);
- long endDate = startDate + RANDOM.nextInt(5000);
-
- BuiltInQPChangeNotification notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName)
- .setLanguageKey(languageKey)
- .setLanguageName(languageName)
- .setNewRules(newRules)
- .setUpdatedRules(updatedRules)
- .setRemovedRules(removedRules)
- .setStartDate(startDate)
- .setEndDate(endDate)
- .build())
- .build();
- BuiltInQPChangeNotificationBuilder result = BuiltInQPChangeNotificationBuilder.parse(notification);
-
- assertThat(result.getProfiles())
- .extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName, Profile::getNewRules, Profile::getUpdatedRules, Profile::getRemovedRules,
- Profile::getStartDate, Profile::getEndDate)
- .containsExactlyInAnyOrder(tuple(profileName, languageKey, languageName, newRules, updatedRules, removedRules, startDate, endDate));
- }
-
- @Test
- public void serialize_and_parse_multiple_profiles() {
- String profileName1 = randomAlphanumeric(20);
- String languageKey1 = randomAlphanumeric(20);
- String languageName1 = randomAlphanumeric(20);
- String profileName2 = randomAlphanumeric(20);
- String languageKey2 = randomAlphanumeric(20);
- String languageName2 = randomAlphanumeric(20);
-
- BuiltInQPChangeNotification notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName1)
- .setLanguageKey(languageKey1)
- .setLanguageName(languageName1)
- .build())
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName2)
- .setLanguageKey(languageKey2)
- .setLanguageName(languageName2)
- .build())
- .build();
- BuiltInQPChangeNotificationBuilder result = BuiltInQPChangeNotificationBuilder.parse(notification);
-
- assertThat(result.getProfiles()).extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName)
- .containsExactlyInAnyOrder(tuple(profileName1, languageKey1, languageName1), tuple(profileName2, languageKey2, languageName2));
- }
-
- @Test
- public void serialize_and_parse_max_values() {
- String profileName = randomAlphanumeric(20);
- String languageKey = randomAlphanumeric(20);
- String languageName = randomAlphanumeric(20);
- int newRules = Integer.MAX_VALUE;
- int updatedRules = Integer.MAX_VALUE;
- int removedRules = Integer.MAX_VALUE;
- long startDate = Long.MAX_VALUE;
- long endDate = Long.MAX_VALUE;
-
- BuiltInQPChangeNotification notification = new BuiltInQPChangeNotificationBuilder()
- .addProfile(Profile.newBuilder()
- .setProfileName(profileName)
- .setLanguageKey(languageKey)
- .setLanguageName(languageName)
- .setNewRules(newRules)
- .setUpdatedRules(updatedRules)
- .setRemovedRules(removedRules)
- .setStartDate(startDate)
- .setEndDate(endDate)
- .build())
- .build();
- BuiltInQPChangeNotificationBuilder result = BuiltInQPChangeNotificationBuilder.parse(notification);
-
- assertThat(result.getProfiles())
- .extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName, Profile::getNewRules, Profile::getUpdatedRules, Profile::getRemovedRules,
- Profile::getStartDate, Profile::getEndDate)
- .containsExactlyInAnyOrder(tuple(profileName, languageKey, languageName, newRules, updatedRules, removedRules, startDate, endDate));
- }
-
- @Test
- public void fail_with_ISE_when_parsing_empty_notification() {
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Could not read the built-in quality profile notification");
-
- BuiltInQPChangeNotificationBuilder.parse(new Notification(BuiltInQPChangeNotification.TYPE));
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileDefinitionsBridgeTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileDefinitionsBridgeTest.java
deleted file mode 100644
index 7d0791b2007..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileDefinitionsBridgeTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.Arrays;
-import org.junit.Test;
-import org.sonar.api.profiles.ProfileDefinition;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.rules.ActiveRule;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleParam;
-import org.sonar.api.rules.RulePriority;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInActiveRule;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInQualityProfile;
-import org.sonar.api.utils.ValidationMessages;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.groups.Tuple.tuple;
-
-public class BuiltInQProfileDefinitionsBridgeTest {
-
- @Test
- public void noProfileDefinitions() {
- BuiltInQProfileDefinitionsBridge bridge = new BuiltInQProfileDefinitionsBridge();
-
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- bridge.define(context);
-
- assertThat(context.profilesByLanguageAndName()).isEmpty();
- }
-
- @Test
- public void bridgeProfileDefinitions() {
- BuiltInQProfileDefinitionsBridge bridge = new BuiltInQProfileDefinitionsBridge(new Profile1(), new NullProfile(), new ProfileWithError());
-
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- bridge.define(context);
-
- assertThat(context.profilesByLanguageAndName()).hasSize(1);
- assertThat(context.profilesByLanguageAndName().get("xoo")).hasSize(1);
-
- BuiltInQualityProfile profile1 = context.profile("xoo", "Profile 1");
- assertThat(profile1).isNotNull();
- assertThat(profile1.rules()).hasSize(3);
- BuiltInActiveRule defaultSeverity = profile1.rule(RuleKey.of("repo1", "defaultSeverity"));
- assertThat(defaultSeverity).isNotNull();
- assertThat(defaultSeverity.overriddenSeverity()).isNull();
- assertThat(defaultSeverity.overriddenParams()).isEmpty();
-
- assertThat(profile1.rule(RuleKey.of("repo1", "overrideSeverity")).overriddenSeverity()).isEqualTo(Severity.CRITICAL);
-
- assertThat(profile1.rule(RuleKey.of("repo1", "overrideParam")).overriddenParams())
- .extracting(BuiltInQualityProfilesDefinition.OverriddenParam::key, BuiltInQualityProfilesDefinition.OverriddenParam::overriddenValue).containsOnly(tuple("param", "value"));
- }
-
- private class Profile1 extends ProfileDefinition {
- @Override
- public RulesProfile createProfile(ValidationMessages validation) {
- RulesProfile profile1 = RulesProfile.create("Profile 1", "xoo");
-
- profile1.activateRule(Rule.create("repo1", "defaultSeverity"), null);
- profile1.activateRule(Rule.create("repo1", "overrideSeverity"), RulePriority.CRITICAL);
- Rule ruleWithParam = Rule.create("repo1", "overrideParam");
- ruleWithParam.setParams(Arrays.asList(new RuleParam(ruleWithParam, "param", "", "")));
- ActiveRule arWithParam = profile1.activateRule(ruleWithParam, null);
- arWithParam.setParameter("param", "value");
-
- return profile1;
- }
- }
-
- private class NullProfile extends ProfileDefinition {
- @Override
- public RulesProfile createProfile(ValidationMessages validation) {
- return null;
- }
- }
-
- private class ProfileWithError extends ProfileDefinition {
- @Override
- public RulesProfile createProfile(ValidationMessages validation) {
- validation.addErrorText("Foo");
- return RulesProfile.create("Profile with errors", "xoo");
- }
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImplTest.java
deleted file mode 100644
index c5e0685517c..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImplTest.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.List;
-import org.junit.After;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.SequenceUuidFactory;
-import org.sonar.core.util.UuidFactory;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.qualityprofile.ActiveRuleDto;
-import org.sonar.db.qualityprofile.ActiveRuleKey;
-import org.sonar.db.qualityprofile.ActiveRuleParamDto;
-import org.sonar.db.qualityprofile.QProfileChangeDto;
-import org.sonar.db.qualityprofile.QProfileChangeQuery;
-import org.sonar.db.qualityprofile.QProfileDto;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
-import org.sonar.server.util.TypeValidations;
-
-import static java.util.Collections.emptyList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class BuiltInQProfileInsertImplTest {
-
- @Rule
- public BuiltInQProfileRepositoryRule builtInQProfileRepository = new BuiltInQProfileRepositoryRule();
- @Rule
- public DbTester db = DbTester.create().setDisableDefaultOrganization(true);
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- private System2 system2 = new AlwaysIncreasingSystem2();
- private UuidFactory uuidFactory = new SequenceUuidFactory();
- private TypeValidations typeValidations = new TypeValidations(emptyList());
- private DbSession dbSession = db.getSession();
- private DbSession batchDbSession = db.getDbClient().openSession(true);
- private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class);
- private BuiltInQProfileInsertImpl underTest = new BuiltInQProfileInsertImpl(db.getDbClient(), system2, uuidFactory, typeValidations, activeRuleIndexer);
-
- @After
- public void tearDown() {
- batchDbSession.close();
- }
-
- @Test
- public void insert_single_row_in_RULES_PROFILES_and_reference_it_in_ORG_QPROFILES() {
- OrganizationDto org1 = db.organizations().insert();
- OrganizationDto org2 = db.organizations().insert();
- BuiltInQProfile builtIn = builtInQProfileRepository.create(LanguageTesting.newLanguage("xoo"), "the name", false);
-
- call(builtIn);
-
- verifyTableSize("org_qprofiles", 2);
- verifyTableSize("rules_profiles", 1);
- verifyTableSize("active_rules", 0);
- verifyTableSize("active_rule_parameters", 0);
- verifyTableSize("qprofile_changes", 0);
- verifyTableSize("project_qprofiles", 0);
-
- QProfileDto profileOnOrg1 = verifyProfileInDb(org1, builtIn);
- QProfileDto profileOnOrg2 = verifyProfileInDb(org2, builtIn);
-
- // same row in table rules_profiles is used
- assertThat(profileOnOrg1.getKee()).isNotEqualTo(profileOnOrg2.getKee());
- assertThat(profileOnOrg1.getRulesProfileUuid()).isEqualTo(profileOnOrg2.getRulesProfileUuid());
- assertThat(profileOnOrg1.getId()).isEqualTo(profileOnOrg2.getId());
- }
-
- @Test
- public void insert_active_rules_and_changelog() {
- OrganizationDto org = db.organizations().insert();
- RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
- RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
-
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("the name", "xoo");
-
- newQp.activateRule(rule1.getRepositoryKey(), rule1.getRuleKey()).overrideSeverity(Severity.CRITICAL);
- newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR);
- newQp.done();
-
- BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"), rule1, rule2);
- call(builtIn);
-
- verifyTableSize("rules_profiles", 1);
- verifyTableSize("active_rules", 2);
- verifyTableSize("active_rule_parameters", 0);
- verifyTableSize("qprofile_changes", 2);
-
- QProfileDto profile = verifyProfileInDb(org, builtIn);
- verifyActiveRuleInDb(profile, rule1, Severity.CRITICAL);
- verifyActiveRuleInDb(profile, rule2, Severity.MAJOR);
- }
-
- @Test
- public void flag_profile_as_default_on_organization_if_declared_as_default_by_api() {
- OrganizationDto org = db.organizations().insert();
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("the name", "xoo").setDefault(true);
- newQp.done();
-
- BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"));
-
- call(builtIn);
-
- QProfileDto profile = verifyProfileInDb(org, builtIn);
- QProfileDto defaultProfile = db.getDbClient().qualityProfileDao().selectDefaultProfile(dbSession, org, "xoo");
- assertThat(defaultProfile.getKee()).isEqualTo(profile.getKee());
- }
-
- @Test
- public void existing_default_profile_in_organization_must_not_be_changed() {
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("the name", "xoo").setDefault(true);
- newQp.done();
- BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"));
-
- OrganizationDto org = db.organizations().insert();
- QProfileDto currentDefault = db.qualityProfiles().insert(org, p -> p.setLanguage("xoo"));
- db.qualityProfiles().setAsDefault(currentDefault);
-
- call(builtIn);
-
- QProfileDto defaultProfile = db.getDbClient().qualityProfileDao().selectDefaultProfile(dbSession, org, "xoo");
- assertThat(defaultProfile.getKee()).isEqualTo(currentDefault.getKee());
- }
-
- @Test
- public void dont_flag_profile_as_default_on_organization_if_not_declared_as_default_by_api() {
- OrganizationDto org = db.organizations().insert();
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("the name", "xoo").setDefault(false);
- newQp.done();
- BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"));
-
- call(builtIn);
-
- QProfileDto defaultProfile = db.getDbClient().qualityProfileDao().selectDefaultProfile(dbSession, org, "xoo");
- assertThat(defaultProfile).isNull();
- }
-
- // TODO test params
- // TODO test lot of active_rules, params, orgas
-
- private void verifyActiveRuleInDb(QProfileDto profile, RuleDefinitionDto rule, String expectedSeverity) {
- ActiveRuleDto activeRule = db.getDbClient().activeRuleDao().selectByKey(dbSession, ActiveRuleKey.of(profile, rule.getKey())).get();
- assertThat(activeRule.getId()).isPositive();
- assertThat(activeRule.getInheritance()).isNull();
- assertThat(activeRule.doesOverride()).isFalse();
- assertThat(activeRule.getRuleId()).isEqualTo(rule.getId());
- assertThat(activeRule.getProfileId()).isEqualTo(profile.getId());
- assertThat(activeRule.getSeverityString()).isEqualTo(expectedSeverity);
- assertThat(activeRule.getCreatedAt()).isPositive();
- assertThat(activeRule.getUpdatedAt()).isPositive();
-
- List<ActiveRuleParamDto> params = db.getDbClient().activeRuleDao().selectParamsByActiveRuleId(dbSession, activeRule.getId());
- assertThat(params).isEmpty();
-
- QProfileChangeQuery changeQuery = new QProfileChangeQuery(profile.getKee());
- QProfileChangeDto change = db.getDbClient().qProfileChangeDao().selectByQuery(dbSession, changeQuery).stream()
- .filter(c -> c.getDataAsMap().get("ruleId").equals(String.valueOf(rule.getId())))
- .findFirst()
- .get();
- assertThat(change.getChangeType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED.name());
- assertThat(change.getCreatedAt()).isPositive();
- assertThat(change.getUuid()).isNotEmpty();
- assertThat(change.getUserUuid()).isNull();
- assertThat(change.getRulesProfileUuid()).isEqualTo(profile.getRulesProfileUuid());
- assertThat(change.getDataAsMap().get("severity")).isEqualTo(expectedSeverity);
- }
-
- private QProfileDto verifyProfileInDb(OrganizationDto organization, BuiltInQProfile builtIn) {
- QProfileDto profileOnOrg1 = db.getDbClient().qualityProfileDao().selectByNameAndLanguage(dbSession, organization, builtIn.getName(), builtIn.getLanguage());
- assertThat(profileOnOrg1.getLanguage()).isEqualTo(builtIn.getLanguage());
- assertThat(profileOnOrg1.getName()).isEqualTo(builtIn.getName());
- assertThat(profileOnOrg1.getOrganizationUuid()).isEqualTo(organization.getUuid());
- assertThat(profileOnOrg1.getParentKee()).isNull();
- assertThat(profileOnOrg1.getLastUsed()).isNull();
- assertThat(profileOnOrg1.getUserUpdatedAt()).isNull();
- assertThat(profileOnOrg1.getRulesUpdatedAt()).isNotEmpty();
- assertThat(profileOnOrg1.getKee()).isNotEqualTo(profileOnOrg1.getRulesProfileUuid());
- assertThat(profileOnOrg1.getId()).isNotNull();
- return profileOnOrg1;
- }
-
- private void verifyTableSize(String table, int expectedSize) {
- assertThat(db.countRowsOfTable(dbSession, table)).as("table " + table).isEqualTo(expectedSize);
- }
-
- private void call(BuiltInQProfile builtIn) {
- underTest.create(dbSession, batchDbSession, builtIn);
- dbSession.commit();
- batchDbSession.commit();
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileLoaderTest.java
deleted file mode 100644
index 5643fada891..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileLoaderTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import org.junit.Rule;
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class BuiltInQProfileLoaderTest {
- @Rule
- public BuiltInQProfileRepositoryRule builtInQProfileRepositoryRule = new BuiltInQProfileRepositoryRule();
-
- private BuiltInQProfileLoader underTest = new BuiltInQProfileLoader(builtInQProfileRepositoryRule);
-
- @Test
- public void start_initializes_DefinedQProfileRepository() {
- underTest.start();
-
- assertThat(builtInQProfileRepositoryRule.isInitialized()).isTrue();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImplTest.java
deleted file mode 100644
index 7a7d1a9373e..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImplTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbTester;
-import org.sonar.server.language.LanguageTesting;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.groups.Tuple.tuple;
-import static org.mockito.Mockito.mock;
-
-public class BuiltInQProfileRepositoryImplTest {
- private static final Language FOO_LANGUAGE = LanguageTesting.newLanguage("foo", "foo", "foo");
- private static final String SONAR_WAY_QP_NAME = "Sonar way";
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- private DbClient dbClient = dbTester.getDbClient();
-
- @Test
- public void get_throws_ISE_if_called_before_initialize() {
- BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages());
-
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("initialize must be called first");
-
- underTest.get();
- }
-
- @Test
- public void initialize_throws_ISE_if_called_twice() {
- BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages());
- underTest.initialize();
-
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("initialize must be called only once");
-
- underTest.initialize();
- }
-
- @Test
- public void initialize_throws_ISE_if_language_has_no_builtin_qp() {
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages(FOO_LANGUAGE));
-
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("The following languages have no built-in quality profiles: foo");
-
- underTest.initialize();
- }
-
- @Test
- public void initialize_creates_no_BuiltInQProfile_when_all_definitions_apply_to_non_defined_languages() {
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages(), new DummyProfileDefinition("foo", "P1", false));
-
- underTest.initialize();
-
- assertThat(underTest.get()).isEmpty();
- }
-
- @Test
- public void initialize_makes_single_profile_of_a_language_default_even_if_not_flagged_as_so() {
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", false));
-
- underTest.initialize();
-
- assertThat(underTest.get())
- .extracting(BuiltInQProfile::getLanguage, BuiltInQProfile::isDefault)
- .containsExactly(tuple(FOO_LANGUAGE.getKey(), true));
- }
-
- @Test
- public void initialize_makes_single_profile_of_a_language_default_even_if_flagged_as_so() {
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", true));
-
- underTest.initialize();
-
- assertThat(underTest.get())
- .extracting(BuiltInQProfile::getLanguage, BuiltInQProfile::isDefault)
- .containsExactly(tuple(FOO_LANGUAGE.getKey(), true));
- }
-
- @Test
- public void initialize_makes_first_profile_of_a_language_default_when_none_flagged_as_so() {
- List<DummyProfileDefinition> definitions = new ArrayList<>(
- asList(new DummyProfileDefinition("foo", "foo1", false), new DummyProfileDefinition("foo", "foo2", false)));
- Collections.shuffle(definitions);
- String firstName = definitions.get(0).getName();
- String secondName = definitions.get(1).getName();
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), definitions.toArray(new BuiltInQualityProfilesDefinition[0]));
-
- underTest.initialize();
-
- assertThat(underTest.get())
- .extracting(BuiltInQProfile::getName, BuiltInQProfile::isDefault)
- .containsExactlyInAnyOrder(tuple(firstName, true), tuple(secondName, false));
- }
-
- @Test
- public void initialize_fails_with_ISE_when_two_profiles_with_different_name_are_default_for_the_same_language() {
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE),
- new DummyProfileDefinition("foo", "foo1", true), new DummyProfileDefinition("foo", "foo2", true));
-
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Several Quality profiles are flagged as default for the language foo: [foo1, foo2]");
-
- underTest.initialize();
- }
-
- @Test
- public void initialize_creates_profile_Sonar_Way_as_default_if_none_other_is_defined_default_for_a_given_language() {
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
- dbClient, new Languages(FOO_LANGUAGE),
- new DummyProfileDefinition("foo", "doh", false), new DummyProfileDefinition("foo", "boo", false),
- new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", false));
-
- underTest.initialize();
-
- assertThat(underTest.get())
- .filteredOn(b -> FOO_LANGUAGE.getKey().equals(b.getLanguage()))
- .filteredOn(BuiltInQProfile::isDefault)
- .extracting(BuiltInQProfile::getName)
- .containsExactly(SONAR_WAY_QP_NAME);
- }
-
- @Test
- public void initialize_does_not_create_Sonar_Way_as_default_if_other_profile_is_defined_as_default() {
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
- dbClient, new Languages(FOO_LANGUAGE),
- new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", true));
-
- underTest.initialize();
-
- assertThat(underTest.get())
- .filteredOn(b -> FOO_LANGUAGE.getKey().equals(b.getLanguage()))
- .filteredOn(BuiltInQProfile::isDefault)
- .extracting(BuiltInQProfile::getName)
- .containsExactly("goo");
- }
-
- @Test
- public void initialize_matches_Sonar_Way_default_with_case_sensitivity() {
- String sonarWayInOtherCase = SONAR_WAY_QP_NAME.toUpperCase();
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
- dbClient, new Languages(FOO_LANGUAGE),
- new DummyProfileDefinition("foo", "goo", false), new DummyProfileDefinition("foo", sonarWayInOtherCase, false));
-
- underTest.initialize();
-
- assertThat(underTest.get())
- .filteredOn(b -> FOO_LANGUAGE.getKey().equals(b.getLanguage()))
- .filteredOn(BuiltInQProfile::isDefault)
- .extracting(BuiltInQProfile::getName)
- .containsExactly("goo");
- }
-
- private static final class DummyProfileDefinition implements BuiltInQualityProfilesDefinition {
- private final String language;
- private final String name;
- private final boolean defaultProfile;
-
- private DummyProfileDefinition(String language, String name, boolean defaultProfile) {
- this.language = language;
- this.name = name;
- this.defaultProfile = defaultProfile;
- }
-
- @Override
- public void define(Context context) {
- context.createBuiltInQualityProfile(name, language)
- .setDefault(defaultProfile).done();
- }
-
- String getName() {
- return name;
- }
-
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryRule.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryRule.java
deleted file mode 100644
index f0f481c55e2..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryRule.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import org.junit.rules.ExternalResource;
-import org.sonar.api.resources.Language;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.rule.RuleDefinitionDto;
-
-import static com.google.common.base.Preconditions.checkState;
-
-public class BuiltInQProfileRepositoryRule extends ExternalResource implements BuiltInQProfileRepository {
- private boolean initializeCalled = false;
- private List<BuiltInQProfile> profiles = new ArrayList<>();
-
- @Override
- protected void before() {
- this.initializeCalled = false;
- this.profiles.clear();
- }
-
- @Override
- public void initialize() {
- checkState(!initializeCalled, "initialize must be called only once");
- this.initializeCalled = true;
- }
-
- @Override
- public List<BuiltInQProfile> get() {
- checkState(initializeCalled, "initialize must be called first");
-
- return ImmutableList.copyOf(profiles);
- }
-
- public boolean isInitialized() {
- return initializeCalled;
- }
-
- public BuiltInQProfile add(Language language, String profileName) {
- return add(language, profileName, false);
- }
-
- public BuiltInQProfile add(Language language, String profileName, boolean isDefault) {
- return add(language, profileName, isDefault, new BuiltInQProfile.ActiveRule[0]);
- }
-
- public BuiltInQProfile add(Language language, String profileName, boolean isDefault, BuiltInQProfile.ActiveRule... rules) {
- BuiltInQProfile builtIn = create(language, profileName, isDefault, rules);
- profiles.add(builtIn);
- return builtIn;
- }
-
- public BuiltInQProfile create(Language language, String profileName, boolean isDefault, BuiltInQProfile.ActiveRule... rules) {
- BuiltInQProfile.Builder builder = new BuiltInQProfile.Builder()
- .setLanguage(language.getKey())
- .setName(profileName)
- .setDeclaredDefault(isDefault);
- Arrays.stream(rules).forEach(builder::addRule);
- return builder.build();
- }
-
- public BuiltInQProfile create(BuiltInQualityProfilesDefinition.BuiltInQualityProfile api, RuleDefinitionDto... rules) {
- BuiltInQProfile.Builder builder = new BuiltInQProfile.Builder()
- .setLanguage(api.language())
- .setName(api.name())
- .setDeclaredDefault(api.isDefault());
- Map<RuleKey, RuleDefinitionDto> rulesByRuleKey = Arrays.stream(rules)
- .collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getKey));
- api.rules().forEach(rule -> {
- RuleKey ruleKey = RuleKey.of(rule.repoKey(), rule.ruleKey());
- RuleDefinitionDto ruleDefinition = rulesByRuleKey.get(ruleKey);
- Preconditions.checkState(ruleDefinition != null, "Rule '%s' not found", ruleKey);
- builder.addRule(rule, ruleDefinition.getId());
- });
- return builder
- .build();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java
deleted file mode 100644
index ee0f3fbfae8..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import org.assertj.core.groups.Tuple;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.rules.RulePriority;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
-import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile;
-import org.sonar.api.utils.System2;
-import org.sonar.api.impl.utils.TestSystem2;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.qualityprofile.ActiveRuleDto;
-import org.sonar.db.qualityprofile.ActiveRuleParamDto;
-import org.sonar.db.qualityprofile.OrgActiveRuleDto;
-import org.sonar.db.qualityprofile.QProfileDto;
-import org.sonar.db.qualityprofile.RulesProfileDto;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.rule.RuleParamDto;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.util.IntegerTypeValidation;
-import org.sonar.server.util.StringTypeValidation;
-import org.sonar.server.util.TypeValidations;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyMap;
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.groups.Tuple.tuple;
-import static org.mockito.Mockito.mock;
-import static org.sonar.api.rules.RulePriority.BLOCKER;
-import static org.sonar.api.rules.RulePriority.CRITICAL;
-import static org.sonar.api.rules.RulePriority.MAJOR;
-import static org.sonar.api.rules.RulePriority.MINOR;
-import static org.sonar.db.qualityprofile.QualityProfileTesting.newRuleProfileDto;
-import static org.sonar.server.qualityprofile.ActiveRuleInheritance.INHERITED;
-
-public class BuiltInQProfileUpdateImplTest {
-
- private static final long NOW = 1_000;
- private static final long PAST = NOW - 100;
-
- @Rule
- public BuiltInQProfileRepositoryRule builtInProfileRepository = new BuiltInQProfileRepositoryRule();
- @Rule
- public DbTester db = DbTester.create();
- @Rule
- public UserSessionRule userSession = UserSessionRule.standalone();
- private System2 system2 = new TestSystem2().setNow(NOW);
- private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class);
- private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation()));
- private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession);
-
- private BuiltInQProfileUpdateImpl underTest = new BuiltInQProfileUpdateImpl(db.getDbClient(), ruleActivator, activeRuleIndexer);
-
- private RulesProfileDto persistedProfile;
-
- @Before
- public void setUp() {
- persistedProfile = newRuleProfileDto(rp -> rp
- .setIsBuiltIn(true)
- .setLanguage("xoo")
- .setRulesUpdatedAt(null));
- db.getDbClient().qualityProfileDao().insert(db.getSession(), persistedProfile);
- db.commit();
- }
-
- @Test
- public void activate_new_rules() {
- RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
- RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
- newQp.activateRule(rule1.getRepositoryKey(), rule1.getRuleKey()).overrideSeverity(Severity.CRITICAL);
- newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR);
- newQp.done();
- BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule1, rule2);
-
- underTest.update(db.getSession(), builtIn, persistedProfile);
-
- List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
- assertThat(activeRules).hasSize(2);
- assertThatRuleIsNewlyActivated(activeRules, rule1, CRITICAL);
- assertThatRuleIsNewlyActivated(activeRules, rule2, MAJOR);
- assertThatProfileIsMarkedAsUpdated(persistedProfile);
- }
-
- @Test
- public void already_activated_rule_is_updated_in_case_of_differences() {
- RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo"));
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
- newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()).overrideSeverity(Severity.CRITICAL);
- newQp.done();
- BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule);
-
- activateRuleInDb(persistedProfile, rule, BLOCKER);
-
- underTest.update(db.getSession(), builtIn, persistedProfile);
-
- List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
- assertThat(activeRules).hasSize(1);
- assertThatRuleIsUpdated(activeRules, rule, CRITICAL);
- assertThatProfileIsMarkedAsUpdated(persistedProfile);
- }
-
- @Test
- public void already_activated_rule_is_not_touched_if_no_differences() {
- RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo"));
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
- newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()).overrideSeverity(Severity.CRITICAL);
- newQp.done();
- BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule);
-
- activateRuleInDb(persistedProfile, rule, CRITICAL);
-
- underTest.update(db.getSession(), builtIn, persistedProfile);
-
- List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
- assertThat(activeRules).hasSize(1);
- assertThatRuleIsUntouched(activeRules, rule, CRITICAL);
- assertThatProfileIsNotMarkedAsUpdated(persistedProfile);
- }
-
- @Test
- public void deactivate_rule_that_is_not_in_built_in_definition_anymore() {
- RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
- RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
- newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR);
- newQp.done();
- BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule1, rule2);
-
- // built-in definition contains only rule2
- // so rule1 must be deactivated
- activateRuleInDb(persistedProfile, rule1, CRITICAL);
-
- underTest.update(db.getSession(), builtIn, persistedProfile);
-
- List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
- assertThat(activeRules).hasSize(1);
- assertThatRuleIsDeactivated(activeRules, rule1);
- assertThatProfileIsMarkedAsUpdated(persistedProfile);
- }
-
- @Test
- public void activate_deactivate_and_update_three_rules_at_the_same_time() {
- RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
- RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
- RuleDefinitionDto rule3 = db.rules().insert(r -> r.setLanguage("xoo"));
-
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
- newQp.activateRule(rule1.getRepositoryKey(), rule1.getRuleKey()).overrideSeverity(Severity.CRITICAL);
- newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR);
- newQp.done();
- BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule1, rule2);
-
- // rule1 must be updated (blocker to critical)
- // rule2 must be activated
- // rule3 must be deactivated
- activateRuleInDb(persistedProfile, rule1, BLOCKER);
- activateRuleInDb(persistedProfile, rule3, BLOCKER);
-
- underTest.update(db.getSession(), builtIn, persistedProfile);
-
- List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
- assertThat(activeRules).hasSize(2);
- assertThatRuleIsUpdated(activeRules, rule1, CRITICAL);
- assertThatRuleIsNewlyActivated(activeRules, rule2, MAJOR);
- assertThatRuleIsDeactivated(activeRules, rule3);
- assertThatProfileIsMarkedAsUpdated(persistedProfile);
- }
-
- // SONAR-10473
- @Test
- public void activate_rule_on_built_in_profile_resets_severity_to_default_if_not_overridden() {
- RuleDefinitionDto rule = db.rules().insert(r -> r.setSeverity(Severity.MAJOR).setLanguage("xoo"));
-
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
- newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey());
- newQp.done();
- BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule);
- underTest.update(db.getSession(), builtIn, persistedProfile);
-
- List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
- assertThatRuleIsNewlyActivated(activeRules, rule, MAJOR);
-
- // emulate an upgrade of analyzer that changes the default severity of the rule
- rule.setSeverity(Severity.MINOR);
- db.rules().update(rule);
-
- underTest.update(db.getSession(), builtIn, persistedProfile);
- activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
- assertThatRuleIsNewlyActivated(activeRules, rule, MINOR);
- }
-
- @Test
- public void activate_rule_on_built_in_profile_resets_params_to_default_if_not_overridden() {
- RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo"));
- RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10"));
-
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", rule.getLanguage());
- newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey());
- newQp.done();
- BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile(newQp.language(), newQp.name()), rule);
- underTest.update(db.getSession(), builtIn, persistedProfile);
-
- List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
- assertThat(activeRules).hasSize(1);
- assertThatRuleHasParams(db, activeRules.get(0), tuple("min", "10"));
-
- // emulate an upgrade of analyzer that changes the default value of parameter min
- ruleParam.setDefaultValue("20");
- db.getDbClient().ruleDao().updateRuleParam(db.getSession(), rule, ruleParam);
-
- underTest.update(db.getSession(), builtIn, persistedProfile);
- activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
- assertThat(activeRules).hasSize(1);
- assertThatRuleHasParams(db, activeRules.get(0), tuple("min", "20"));
- }
-
- @Test
- public void propagate_activation_to_descendant_profiles() {
- RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo"));
-
- QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(),
- p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true));
- QProfileDto childProfile = createChildProfile(profile);
- QProfileDto grandchildProfile = createChildProfile(childProfile);
-
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile(profile.getName(), profile.getLanguage());
- newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey());
- newQp.done();
- BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile(profile.getLanguage(), profile.getName()), rule);
- List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, RulesProfileDto.from(profile));
-
- assertThat(changes).hasSize(3);
- assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap());
- assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
- assertThatRuleIsActivated(grandchildProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
- }
-
- @Test
- public void do_not_load_descendants_if_no_changes() {
- RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo"));
-
- QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(),
- p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true));
- QProfileDto childProfile = createChildProfile(profile);
-
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile(profile.getName(), profile.getLanguage());
- newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey());
- newQp.done();
-
- // first run
- BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile(profile.getLanguage(), profile.getName()), rule);
- List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, RulesProfileDto.from(profile));
- assertThat(changes).hasSize(2).extracting(ActiveRuleChange::getType).containsOnly(ActiveRuleChange.Type.ACTIVATED);
-
- // second run, without any input changes
- RuleActivator ruleActivatorWithoutDescendants = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession) {
- @Override
- DescendantProfilesSupplier createDescendantProfilesSupplier(DbSession dbSession) {
- return (profiles, ruleIds) -> {
- throw new IllegalStateException("BOOM - descendants should not be loaded");
- };
- }
- };
- changes = new BuiltInQProfileUpdateImpl(db.getDbClient(), ruleActivatorWithoutDescendants, activeRuleIndexer).update(db.getSession(), builtIn, RulesProfileDto.from(profile));
- assertThat(changes).isEmpty();
- }
-
- @Test
- public void propagate_deactivation_to_descendant_profiles() {
- RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo"));
-
- QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(),
- p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true));
- QProfileDto childProfile = createChildProfile(profile);
- QProfileDto grandChildProfile = createChildProfile(childProfile);
-
- BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile(profile.getName(), profile.getLanguage());
- newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey());
- newQp.done();
-
- // first run to activate the rule
- BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile(profile.getLanguage(), profile.getName()), rule);
- List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, RulesProfileDto.from(profile));
- assertThat(changes).hasSize(3).extracting(ActiveRuleChange::getType).containsOnly(ActiveRuleChange.Type.ACTIVATED);
-
- // second run to deactivate the rule
- context = new BuiltInQualityProfilesDefinition.Context();
- NewBuiltInQualityProfile updatedQp = context.createBuiltInQualityProfile(profile.getName(), profile.getLanguage());
- updatedQp.done();
- builtIn = builtInProfileRepository.create(context.profile(profile.getLanguage(), profile.getName()), rule);
- changes = underTest.update(db.getSession(), builtIn, RulesProfileDto.from(profile));
- assertThat(changes).hasSize(3).extracting(ActiveRuleChange::getType).containsOnly(ActiveRuleChange.Type.DEACTIVATED);
-
- assertThatRuleIsDeactivated(profile, rule);
- assertThatRuleIsDeactivated(childProfile, rule);
- assertThatRuleIsDeactivated(grandChildProfile, rule);
- }
-
- private QProfileDto createChildProfile(QProfileDto parent) {
- return db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p
- .setLanguage(parent.getLanguage())
- .setParentKee(parent.getKee())
- .setName("Child of " + parent.getName()))
- .setIsBuiltIn(false);
- }
-
- private void assertThatRuleIsActivated(QProfileDto profile, RuleDefinitionDto rule, @Nullable List<ActiveRuleChange> changes,
- String expectedSeverity, @Nullable ActiveRuleInheritance expectedInheritance, Map<String, String> expectedParams) {
- OrgActiveRuleDto activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)
- .stream()
- .filter(ar -> ar.getRuleKey().equals(rule.getKey()))
- .findFirst()
- .orElseThrow(IllegalStateException::new);
-
- assertThat(activeRule.getSeverityString()).isEqualTo(expectedSeverity);
- assertThat(activeRule.getInheritance()).isEqualTo(expectedInheritance != null ? expectedInheritance.name() : null);
- assertThat(activeRule.getCreatedAt()).isNotNull();
- assertThat(activeRule.getUpdatedAt()).isNotNull();
-
- List<ActiveRuleParamDto> params = db.getDbClient().activeRuleDao().selectParamsByActiveRuleId(db.getSession(), activeRule.getId());
- assertThat(params).hasSize(expectedParams.size());
-
- if (changes != null) {
- ActiveRuleChange change = changes.stream()
- .filter(c -> c.getActiveRule().getId().equals(activeRule.getId()))
- .findFirst().orElseThrow(IllegalStateException::new);
- assertThat(change.getInheritance()).isEqualTo(expectedInheritance);
- assertThat(change.getSeverity()).isEqualTo(expectedSeverity);
- assertThat(change.getType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED);
- }
- }
-
- private static void assertThatRuleHasParams(DbTester db, ActiveRuleDto activeRule, Tuple... expectedParams) {
- assertThat(db.getDbClient().activeRuleDao().selectParamsByActiveRuleId(db.getSession(), activeRule.getId()))
- .extracting(ActiveRuleParamDto::getKey, ActiveRuleParamDto::getValue)
- .containsExactlyInAnyOrder(expectedParams);
- }
-
- private static void assertThatRuleIsNewlyActivated(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule, RulePriority severity) {
- ActiveRuleDto activeRule = findRule(activeRules, rule).get();
-
- assertThat(activeRule.getInheritance()).isNull();
- assertThat(activeRule.getSeverityString()).isEqualTo(severity.name());
- assertThat(activeRule.getCreatedAt()).isEqualTo(NOW);
- assertThat(activeRule.getUpdatedAt()).isEqualTo(NOW);
- }
-
- private static void assertThatRuleIsUpdated(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule, RulePriority severity) {
- ActiveRuleDto activeRule = findRule(activeRules, rule).get();
-
- assertThat(activeRule.getInheritance()).isNull();
- assertThat(activeRule.getSeverityString()).isEqualTo(severity.name());
- assertThat(activeRule.getCreatedAt()).isEqualTo(PAST);
- assertThat(activeRule.getUpdatedAt()).isEqualTo(NOW);
- }
-
- private static void assertThatRuleIsUntouched(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule, RulePriority severity) {
- ActiveRuleDto activeRule = findRule(activeRules, rule).get();
-
- assertThat(activeRule.getInheritance()).isNull();
- assertThat(activeRule.getSeverityString()).isEqualTo(severity.name());
- assertThat(activeRule.getCreatedAt()).isEqualTo(PAST);
- assertThat(activeRule.getUpdatedAt()).isEqualTo(PAST);
- }
-
- private void assertThatRuleIsDeactivated(QProfileDto profile, RuleDefinitionDto rule) {
- Collection<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRulesAndRuleProfileUuids(db.getSession(), singletonList(rule.getId()), singletonList(profile.getRulesProfileUuid()));
- assertThat(activeRules).isEmpty();
- }
-
- private static void assertThatRuleIsDeactivated(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule) {
- assertThat(findRule(activeRules, rule)).isEmpty();
- }
-
- private void assertThatProfileIsMarkedAsUpdated(RulesProfileDto dto) {
- RulesProfileDto reloaded = db.getDbClient().qualityProfileDao().selectBuiltInRuleProfiles(db.getSession())
- .stream()
- .filter(p -> p.getKee().equals(dto.getKee()))
- .findFirst()
- .get();
- assertThat(reloaded.getRulesUpdatedAt()).isNotEmpty();
- }
-
- private void assertThatProfileIsNotMarkedAsUpdated(RulesProfileDto dto) {
- RulesProfileDto reloaded = db.getDbClient().qualityProfileDao().selectBuiltInRuleProfiles(db.getSession())
- .stream()
- .filter(p -> p.getKee().equals(dto.getKee()))
- .findFirst()
- .get();
- assertThat(reloaded.getRulesUpdatedAt()).isNull();
- }
-
- private static Optional<ActiveRuleDto> findRule(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule) {
- return activeRules.stream()
- .filter(ar -> ar.getRuleKey().equals(rule.getKey()))
- .findFirst();
- }
-
- private void activateRuleInDb(RulesProfileDto profile, RuleDefinitionDto rule, RulePriority severity) {
- ActiveRuleDto dto = new ActiveRuleDto()
- .setProfileId(profile.getId())
- .setSeverity(severity.name())
- .setRuleId(rule.getId())
- .setCreatedAt(PAST)
- .setUpdatedAt(PAST);
- db.getDbClient().activeRuleDao().insert(db.getSession(), dto);
- db.commit();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesUpdateListenerTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesUpdateListenerTest.java
deleted file mode 100644
index d796ff9e6fd..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesUpdateListenerTest.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Multimap;
-import java.util.Random;
-import org.assertj.core.groups.Tuple;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.notifications.Notification;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.db.qualityprofile.ActiveRuleKey;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.server.notification.NotificationManager;
-import org.sonar.server.qualityprofile.BuiltInQPChangeNotificationBuilder.Profile;
-
-import static java.util.Arrays.asList;
-import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.sonar.core.config.CorePropertyDefinitions.DISABLE_NOTIFICATION_ON_BUILT_IN_QPROFILES;
-import static org.sonar.server.language.LanguageTesting.newLanguage;
-import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
-import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
-import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.UPDATED;
-
-public class BuiltInQualityProfilesUpdateListenerTest {
-
- private NotificationManager notificationManager = mock(NotificationManager.class);
- private MapSettings settings = new MapSettings();
-
- @Test
- public void add_profile_to_notification_for_added_rules() {
- enableNotificationInGlobalSettings();
- Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
- Languages languages = new Languages();
- Tuple expectedTuple = addProfile(profiles, languages, ACTIVATED);
-
- BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
- underTest.onChange(profiles, 0, 1);
-
- ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
- verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
- verifyNoMoreInteractions(notificationManager);
- assertThat(BuiltInQPChangeNotificationBuilder.parse(notificationArgumentCaptor.getValue()).getProfiles())
- .extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName, Profile::getNewRules)
- .containsExactlyInAnyOrder(expectedTuple);
- }
-
- @Test
- public void add_profile_to_notification_for_updated_rules() {
- enableNotificationInGlobalSettings();
- Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
- Languages languages = new Languages();
- Tuple expectedTuple = addProfile(profiles, languages, UPDATED);
-
- BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
- underTest.onChange(profiles, 0, 1);
-
- ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
- verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
- verifyNoMoreInteractions(notificationManager);
- assertThat(BuiltInQPChangeNotificationBuilder.parse(notificationArgumentCaptor.getValue()).getProfiles())
- .extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName, Profile::getUpdatedRules)
- .containsExactlyInAnyOrder(expectedTuple);
- }
-
- @Test
- public void add_profile_to_notification_for_removed_rules() {
- enableNotificationInGlobalSettings();
- Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
- Languages languages = new Languages();
- Tuple expectedTuple = addProfile(profiles, languages, DEACTIVATED);
-
- BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
- underTest.onChange(profiles, 0, 1);
-
- ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
- verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
- verifyNoMoreInteractions(notificationManager);
- assertThat(BuiltInQPChangeNotificationBuilder.parse(notificationArgumentCaptor.getValue()).getProfiles())
- .extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName, Profile::getRemovedRules)
- .containsExactlyInAnyOrder(expectedTuple);
- }
-
- @Test
- public void add_multiple_profiles_to_notification() {
- enableNotificationInGlobalSettings();
- Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
- Languages languages = new Languages();
- Tuple expectedTuple1 = addProfile(profiles, languages, ACTIVATED);
- Tuple expectedTuple2 = addProfile(profiles, languages, ACTIVATED);
-
- BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
- underTest.onChange(profiles, 0, 1);
-
- ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
- verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
- verifyNoMoreInteractions(notificationManager);
- assertThat(BuiltInQPChangeNotificationBuilder.parse(notificationArgumentCaptor.getValue()).getProfiles())
- .extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName, Profile::getNewRules)
- .containsExactlyInAnyOrder(expectedTuple1, expectedTuple2);
- }
-
- @Test
- public void add_start_and_end_dates_to_notification() {
- enableNotificationInGlobalSettings();
- Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
- Languages languages = new Languages();
- addProfile(profiles, languages, ACTIVATED);
- long startDate = 10_000_000_000L;
- long endDate = 15_000_000_000L;
-
- BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
- underTest.onChange(profiles, startDate, endDate);
-
- ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
- verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
- verifyNoMoreInteractions(notificationManager);
- assertThat(BuiltInQPChangeNotificationBuilder.parse(notificationArgumentCaptor.getValue()).getProfiles())
- .extracting(Profile::getStartDate, Profile::getEndDate)
- .containsExactlyInAnyOrder(tuple(startDate, endDate));
- }
-
- @Test
- public void avoid_notification_if_configured_in_settings() {
- settings.setProperty(DISABLE_NOTIFICATION_ON_BUILT_IN_QPROFILES, true);
- Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
- Languages languages = new Languages();
- addProfile(profiles, languages, ACTIVATED);
-
- BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
- underTest.onChange(profiles, 0, 1);
-
- verifyZeroInteractions(notificationManager);
- }
-
- private Tuple addProfile(Multimap<QProfileName, ActiveRuleChange> profiles, Languages languages, ActiveRuleChange.Type type) {
- String profileName = randomLowerCaseText();
- int ruleId1 = new Random().nextInt(952);
- int ruleId2 = new Random().nextInt(952);
- Language language = newLanguage(randomLowerCaseText(), randomLowerCaseText());
- languages.add(language);
- profiles.putAll(new QProfileName(language.getKey(), profileName),
- asList(new ActiveRuleChange(
- type,
- ActiveRuleKey.parse("qp:repo:rule1"), new RuleDefinitionDto().setId(ruleId1)),
- new ActiveRuleChange(type, ActiveRuleKey.parse("qp:repo:rule2"), new RuleDefinitionDto().setId(ruleId2))));
- return tuple(profileName, language.getKey(), language.getName(), 2);
- }
-
- private static String randomLowerCaseText() {
- return randomAlphanumeric(20).toLowerCase();
- }
-
- private void enableNotificationInGlobalSettings() {
- settings.setProperty(DISABLE_NOTIFICATION_ON_BUILT_IN_QPROFILES, false);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/AbstractMockUserSession.java b/server/sonar-server/src/test/java/org/sonar/server/tester/AbstractMockUserSession.java
deleted file mode 100644
index 26c8e103942..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/tester/AbstractMockUserSession.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.tester;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableSet;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.server.user.AbstractUserSession;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Maps.newHashMap;
-
-public abstract class AbstractMockUserSession<T extends AbstractMockUserSession> extends AbstractUserSession {
- private static final Set<String> PUBLIC_PERMISSIONS = ImmutableSet.of(UserRole.USER, UserRole.CODEVIEWER); // FIXME to check with Simon
-
- private final Class<T> clazz;
- private HashMultimap<String, String> projectUuidByPermission = HashMultimap.create();
- private final HashMultimap<String, OrganizationPermission> permissionsByOrganizationUuid = HashMultimap.create();
- private Map<String, String> projectUuidByComponentUuid = newHashMap();
- private Set<String> projectPermissions = new HashSet<>();
- private Set<String> organizationMembership = new HashSet<>();
- private boolean systemAdministrator = false;
-
- protected AbstractMockUserSession(Class<T> clazz) {
- this.clazz = clazz;
- }
-
- public T addPermission(OrganizationPermission permission, String organizationUuid) {
- permissionsByOrganizationUuid.put(organizationUuid, permission);
- return clazz.cast(this);
- }
-
- @Override
- protected boolean hasPermissionImpl(OrganizationPermission permission, String organizationUuid) {
- return permissionsByOrganizationUuid.get(organizationUuid).contains(permission);
- }
-
- /**
- * Use this method to register public root component and non root components the UserSession must be aware of.
- * (ie. this method can be used to emulate the content of the DB)
- */
- public T registerComponents(ComponentDto... components) {
- Arrays.stream(components)
- .forEach(component -> {
- if (component.projectUuid().equals(component.uuid()) && !component.isPrivate()) {
- this.projectUuidByPermission.put(UserRole.USER, component.uuid());
- this.projectUuidByPermission.put(UserRole.CODEVIEWER, component.uuid());
- this.projectPermissions.add(UserRole.USER);
- this.projectPermissions.add(UserRole.CODEVIEWER);
- }
- this.projectUuidByComponentUuid.put(component.uuid(), component.projectUuid());
- });
- return clazz.cast(this);
- }
-
- public T addProjectPermission(String permission, ComponentDto... components) {
- Arrays.stream(components).forEach(component -> {
- checkArgument(
- component.isPrivate() || !PUBLIC_PERMISSIONS.contains(permission),
- "public component %s can't be granted public permission %s", component.uuid(), permission);
- });
- registerComponents(components);
- this.projectPermissions.add(permission);
- Arrays.stream(components)
- .forEach(component -> this.projectUuidByPermission.put(permission, component.projectUuid()));
- return clazz.cast(this);
- }
-
- @Override
- protected Optional<String> componentUuidToProjectUuid(String componentUuid) {
- return Optional.ofNullable(projectUuidByComponentUuid.get(componentUuid));
- }
-
- @Override
- protected boolean hasProjectUuidPermission(String permission, String projectUuid) {
- return projectPermissions.contains(permission) && projectUuidByPermission.get(permission).contains(projectUuid);
- }
-
- public T setSystemAdministrator(boolean b) {
- this.systemAdministrator = b;
- return clazz.cast(this);
- }
-
- @Override
- public boolean isSystemAdministrator() {
- return isRoot() || systemAdministrator;
- }
-
- @Override
- protected boolean hasMembershipImpl(OrganizationDto organizationDto) {
- return organizationMembership.contains(organizationDto.getUuid());
- }
-
- public void addOrganizationMembership(OrganizationDto organization) {
- this.organizationMembership.add(organization.getUuid());
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/AnonymousMockUserSession.java b/server/sonar-server/src/test/java/org/sonar/server/tester/AnonymousMockUserSession.java
deleted file mode 100644
index 3c5d4068c61..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/tester/AnonymousMockUserSession.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.tester;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Optional;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.user.GroupDto;
-
-public class AnonymousMockUserSession extends AbstractMockUserSession<AnonymousMockUserSession> {
-
- public AnonymousMockUserSession() {
- super(AnonymousMockUserSession.class);
- }
-
- @Override
- public boolean isRoot() {
- return false;
- }
-
- @Override
- public String getLogin() {
- return null;
- }
-
- @Override public String getUuid() {
- return null;
- }
-
- @Override
- public String getName() {
- return null;
- }
-
- @Override
- public Integer getUserId() {
- return null;
- }
-
- @Override
- public boolean isLoggedIn() {
- return false;
- }
-
- @Override
- public Collection<GroupDto> getGroups() {
- return Collections.emptyList();
- }
-
- @Override
- public Optional<IdentityProvider> getIdentityProvider() {
- return Optional.empty();
- }
-
- @Override
- public Optional<ExternalIdentity> getExternalIdentity() {
- return Optional.empty();
- }
-
- @Override
- public boolean hasMembershipImpl(OrganizationDto organizationDto) {
- return false;
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/AttributeHolderServletContext.java b/server/sonar-server/src/test/java/org/sonar/server/tester/AttributeHolderServletContext.java
deleted file mode 100644
index e65c0d35e67..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/tester/AttributeHolderServletContext.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.tester;
-
-import com.google.common.collect.Maps;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.EventListener;
-import java.util.Map;
-import java.util.Set;
-import javax.servlet.Filter;
-import javax.servlet.FilterRegistration;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRegistration;
-import javax.servlet.SessionCookieConfig;
-import javax.servlet.SessionTrackingMode;
-import javax.servlet.descriptor.JspConfigDescriptor;
-
-/**
- * A dummy implementation of {@link ServletContext} which only implements the attribute related methods. All other
- * methods thrown a {@link UnsupportedOperationException} when called.
- */
-class AttributeHolderServletContext implements ServletContext {
- @Override
- public String getContextPath() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ServletContext getContext(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getMajorVersion() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getMinorVersion() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getEffectiveMajorVersion() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getEffectiveMinorVersion() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getMimeType(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Set<String> getResourcePaths(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public URL getResource(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public InputStream getResourceAsStream(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public RequestDispatcher getRequestDispatcher(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public RequestDispatcher getNamedDispatcher(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Servlet getServlet(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Enumeration<Servlet> getServlets() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Enumeration<String> getServletNames() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void log(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void log(Exception e, String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void log(String s, Throwable throwable) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getRealPath(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getServerInfo() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getInitParameter(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Enumeration<String> getInitParameterNames() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean setInitParameter(String s, String s1) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Object getAttribute(String s) {
- return this.attributes.get(s);
- }
-
- @Override
- public Enumeration<String> getAttributeNames() {
- return Collections.enumeration(this.attributes.keySet());
- }
-
- private final Map<String, Object> attributes = Maps.newHashMap();
-
- @Override
- public void setAttribute(String s, Object o) {
- attributes.put(s, o);
- }
-
- @Override
- public void removeAttribute(String s) {
- attributes.remove(s);
- }
-
- @Override
- public String getServletContextName() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ServletRegistration.Dynamic addServlet(String s, String s1) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ServletRegistration.Dynamic addServlet(String s, Servlet servlet) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ServletRegistration.Dynamic addServlet(String s, Class<? extends Servlet> aClass) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public <T extends Servlet> T createServlet(Class<T> aClass) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ServletRegistration getServletRegistration(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Map<String, ? extends ServletRegistration> getServletRegistrations() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public FilterRegistration.Dynamic addFilter(String s, String s1) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public FilterRegistration.Dynamic addFilter(String s, Filter filter) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public FilterRegistration.Dynamic addFilter(String s, Class<? extends Filter> aClass) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public <T extends Filter> T createFilter(Class<T> aClass) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public FilterRegistration getFilterRegistration(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public SessionCookieConfig getSessionCookieConfig() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setSessionTrackingModes(Set<SessionTrackingMode> set) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addListener(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public <T extends EventListener> void addListener(T t) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addListener(Class<? extends EventListener> aClass) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public <T extends EventListener> T createListener(Class<T> aClass) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public JspConfigDescriptor getJspConfigDescriptor() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ClassLoader getClassLoader() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void declareRoles(String... strings) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getVirtualServerName() {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/AttributeHolderServletContextTest.java b/server/sonar-server/src/test/java/org/sonar/server/tester/AttributeHolderServletContextTest.java
deleted file mode 100644
index dc3935c4311..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/tester/AttributeHolderServletContextTest.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.tester;
-
-import com.google.common.collect.ImmutableSet;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.EventListener;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.Servlet;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.SessionTrackingMode;
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class AttributeHolderServletContextTest {
- public static final String SOME_STRING = "SOME_STRING";
- public static final Exception SOME_EXCEPTION = new Exception();
- public static final String SOME_OTHER_STRING = "SOME OTHER STRING";
- AttributeHolderServletContext servletContext = new AttributeHolderServletContext();
- public static final ImmutableSet<SessionTrackingMode> SOME_SET_OF_SESSION_TRACKING_MODE = ImmutableSet.of();
-
- @Test(expected = UnsupportedOperationException.class)
- public void getContextPath_is_not_supported() {
- servletContext.getContextPath();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getContext_is_not_supported() {
- servletContext.getContext(SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getMajorVersion_is_not_supported() {
- servletContext.getMajorVersion();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getMinorVersion_is_not_supported() {
- servletContext.getMinorVersion();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getEffectiveMajorVersion_is_not_supported() {
- servletContext.getEffectiveMajorVersion();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getEffectiveMinorVersion_is_not_supported() {
- servletContext.getEffectiveMinorVersion();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getMimeType_is_not_supported() {
- servletContext.getMimeType(SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getResourcePaths_is_not_supported() {
- servletContext.getResourcePaths(SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getResource_is_not_supported() throws Exception {
- servletContext.getResource(SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getResourceAsStream_is_not_supported() {
- servletContext.getResourceAsStream(SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getRequestDispatcher_is_not_supported() {
- servletContext.getRequestDispatcher(SOME_STRING);
-
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getNamedDispatcher_is_not_supported() {
- servletContext.getNamedDispatcher(SOME_STRING);
-
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getServlet_is_not_supported() throws ServletException {
- servletContext.getServlet(SOME_STRING);
-
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getServlets_is_not_supported() {
- servletContext.getServlets();
-
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getServletNames_is_not_supported() {
- servletContext.getServletNames();
-
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void log_is_not_supported() {
- servletContext.log(SOME_STRING);
-
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void log1_is_not_supported() {
- servletContext.log(SOME_EXCEPTION, SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void log2_is_not_supported() {
- servletContext.log(SOME_STRING, SOME_EXCEPTION);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getRealPath_is_not_supported() {
- servletContext.getRealPath(SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getServerInfo_is_not_supported() {
- servletContext.getServerInfo();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getInitParameter_is_not_supported() {
- servletContext.getInitParameter(SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getInitParameterNames_is_not_supported() {
- servletContext.getInitParameterNames();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void setInitParameter_is_not_supported() {
- servletContext.setInitParameter(SOME_STRING, SOME_STRING);
-
- }
-
- @Test
- public void getAttribute_returns_null_when_attributes_are_empty() {
- assertThat(servletContext.getAttribute(SOME_STRING)).isNull();
- }
-
- @Test
- public void getAttribute_returns_attribute() {
- servletContext.setAttribute(SOME_STRING, SOME_OTHER_STRING);
-
- assertThat(servletContext.getAttribute(SOME_STRING)).isEqualTo(SOME_OTHER_STRING);
- }
-
- @Test
- public void getAttributeNames_returns_empty_enumeration_if_attributes_are_empty() {
- Enumeration<String> attributeNames = servletContext.getAttributeNames();
- assertThat(attributeNames.hasMoreElements()).isFalse();
- }
-
- @Test
- public void getAttributeNames_returns_names_of_attributes() {
- servletContext.setAttribute(SOME_STRING, new Object());
- servletContext.setAttribute(SOME_OTHER_STRING, new Object());
-
- assertThat(Collections.list(servletContext.getAttributeNames())).containsOnly(SOME_STRING, SOME_OTHER_STRING);
- }
-
- @Test
- public void removeAttribute_removes_specified_attribute() {
- servletContext.setAttribute(SOME_STRING, new Object());
- servletContext.setAttribute(SOME_OTHER_STRING, new Object());
-
- servletContext.removeAttribute(SOME_OTHER_STRING);
-
- assertThat(servletContext.getAttribute(SOME_OTHER_STRING)).isNull();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getServletContextName_is_not_supported() {
- servletContext.getServletContextName();
-
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void addServlet_by_class_is_not_supported() {
- servletContext.addServlet(SOME_STRING, Servlet.class);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void addServlet_by_instance_is_not_supported() {
- servletContext.addServlet(SOME_STRING, new Servlet() {
- @Override
- public void init(ServletConfig servletConfig) {
-
- }
-
- @Override
- public ServletConfig getServletConfig() {
- return null;
- }
-
- @Override
- public void service(ServletRequest servletRequest, ServletResponse servletResponse) {
-
- }
-
- @Override
- public String getServletInfo() {
- return null;
- }
-
- @Override
- public void destroy() {
-
- }
- });
-
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void addServlet_by_string_is_not_supported() {
- servletContext.addServlet(SOME_STRING, SOME_OTHER_STRING);
-
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void createServlet_is_not_supported() throws ServletException {
- servletContext.createServlet(Servlet.class);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getServletRegistration_is_not_supported() {
- servletContext.getServletRegistration(SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getServletRegistrations_is_not_supported() {
- servletContext.getServletRegistrations();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void addFilter_by_class_is_not_supported() {
- servletContext.addFilter(SOME_STRING, Filter.class);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void addFilter_by_instance_is_not_supported() {
- servletContext.addFilter(SOME_STRING, new Filter() {
- @Override
- public void init(FilterConfig filterConfig) {
-
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
-
- }
-
- @Override
- public void destroy() {
-
- }
- });
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void addFilter2_by_string_is_not_supported() {
- servletContext.addFilter(SOME_STRING, SOME_OTHER_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void createFilter_is_not_supported() throws ServletException {
- servletContext.createFilter(Filter.class);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getFilterRegistration_is_not_supported() {
- servletContext.getFilterRegistration(SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getFilterRegistrations_is_not_supported() {
- servletContext.getFilterRegistrations();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getSessionCookieConfig_is_not_supported() {
- servletContext.getSessionCookieConfig();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void setSessionTrackingModes_is_not_supported() {
- servletContext.setSessionTrackingModes(SOME_SET_OF_SESSION_TRACKING_MODE);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getDefaultSessionTrackingModes_is_not_supported() {
- servletContext.getDefaultSessionTrackingModes();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getEffectiveSessionTrackingModes_is_not_supported() {
- servletContext.getEffectiveSessionTrackingModes();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void addListener_by_class_is_not_supported() {
- servletContext.addListener(EventListener.class);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void addListener_by_string_is_not_supported() {
- servletContext.addListener(SOME_STRING);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void addListener_by_instance_is_not_supported() {
- servletContext.addListener(new EventListener() {
- });
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void createListener_is_not_supported() throws ServletException {
- servletContext.createListener(EventListener.class);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getJspConfigDescriptor_is_not_supported() {
- servletContext.getJspConfigDescriptor();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getClassLoader_is_not_supported() {
- servletContext.getClassLoader();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void declareRoles_is_not_supported() {
- servletContext.declareRoles();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void getVirtualServerName_is_not_supported() {
- servletContext.getVirtualServerName();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/MockUserSession.java b/server/sonar-server/src/test/java/org/sonar/server/tester/MockUserSession.java
deleted file mode 100644
index e59b0eda6f5..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/tester/MockUserSession.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.tester;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.user.AbstractUserSession;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Arrays.asList;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.server.user.UserSession.IdentityProvider.SONARQUBE;
-
-public class MockUserSession extends AbstractMockUserSession<MockUserSession> {
- private final String login;
- private String uuid;
- private boolean root = false;
- private Integer userId;
- private String name;
- private List<GroupDto> groups = new ArrayList<>();
- private IdentityProvider identityProvider;
- private ExternalIdentity externalIdentity;
-
- public MockUserSession(String login) {
- super(MockUserSession.class);
- checkArgument(!login.isEmpty());
- this.login = login;
- setUuid(login + "uuid");
- setUserId(login.hashCode());
- setName(login + " name");
- setInternalIdentity();
- }
-
- public MockUserSession(UserDto userDto) {
- super(MockUserSession.class);
- checkArgument(!userDto.getLogin().isEmpty());
- this.login = userDto.getLogin();
- setUuid(userDto.getUuid());
- setUserId(userDto.getId());
- setName(userDto.getName());
- AbstractUserSession.Identity identity = computeIdentity(userDto);
- this.identityProvider = identity.getIdentityProvider();
- this.externalIdentity = identity.getExternalIdentity();
- }
-
- @Override
- public boolean isLoggedIn() {
- return true;
- }
-
- @Override
- public boolean isRoot() {
- return root;
- }
-
- public void setRoot(boolean root) {
- this.root = root;
- }
-
- @Override
- public String getLogin() {
- return this.login;
- }
-
- @Override
- public String getUuid() {
- return this.uuid;
- }
-
- public MockUserSession setUuid(String uuid) {
- this.uuid = requireNonNull(uuid);
- return this;
- }
-
- @Override
- public String getName() {
- return this.name;
- }
-
- public MockUserSession setName(String s) {
- this.name = requireNonNull(s);
- return this;
- }
-
- @Override
- public Integer getUserId() {
- return this.userId;
- }
-
- public MockUserSession setUserId(int userId) {
- this.userId = userId;
- return this;
- }
-
- @Override
- public Collection<GroupDto> getGroups() {
- return groups;
- }
-
- public MockUserSession setGroups(GroupDto... groups) {
- this.groups = asList(groups);
- return this;
- }
-
- @Override
- public Optional<IdentityProvider> getIdentityProvider() {
- return Optional.ofNullable(identityProvider);
- }
-
- public void setExternalIdentity(IdentityProvider identityProvider, ExternalIdentity externalIdentity) {
- checkArgument(identityProvider != SONARQUBE);
- this.identityProvider = identityProvider;
- this.externalIdentity = requireNonNull(externalIdentity);
- }
-
- public void setInternalIdentity() {
- this.identityProvider = SONARQUBE;
- this.externalIdentity = null;
- }
-
- @Override
- public Optional<ExternalIdentity> getExternalIdentity() {
- return Optional.ofNullable(externalIdentity);
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/MockUserSessionTest.java b/server/sonar-server/src/test/java/org/sonar/server/tester/MockUserSessionTest.java
deleted file mode 100644
index a57efa676d0..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/tester/MockUserSessionTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.tester;
-
-import org.junit.Test;
-import org.sonar.db.user.GroupDto;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.user.GroupTesting.newGroupDto;
-
-public class MockUserSessionTest {
- @Test
- public void set_mock_session() {
- GroupDto group = newGroupDto();
- MockUserSession mock = new MockUserSession("foo").setGroups(group);
-
- assertThat(mock.getLogin()).isEqualTo("foo");
- assertThat(mock.getUuid()).isEqualTo("foouuid");
- assertThat(mock.getGroups()).extracting(GroupDto::getId).containsOnly(group.getId());
- assertThat(mock.isLoggedIn()).isTrue();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/UserSessionRule.java b/server/sonar-server/src/test/java/org/sonar/server/tester/UserSessionRule.java
deleted file mode 100644
index 5e7cc4147d5..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/tester/UserSessionRule.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.tester;
-
-import com.google.common.base.Preconditions;
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.user.UserSession;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-/**
- * {@code UserSessionRule} is intended to be used as a {@link org.junit.Rule} to easily manage {@link UserSession} in
- * unit tests.
- * <p>
- * It can be used as a {@link org.junit.ClassRule} but be careful not to modify its states from inside tests methods
- * unless you purposely want to have side effects between each tests.
- * </p>
- * <p>
- * One can define user session behavior which should apply on all tests directly on the property, eg.:
- * <pre>
- * {@literal @}Rule
- * public UserSessionRule userSession = UserSessionRule.standalone().login("admin").setOrganizationPermissions(OrganizationPermissions.SYSTEM_ADMIN);
- * </pre>
- * </p>
- * <p>
- * Behavior defined at property-level can obviously be override at test method level. For example, one could define
- * all methods to use an authenticated session such as presented above but can easily overwrite that behavior in a
- * specific test method as follow:
- * <pre>
- * {@literal @}Test
- * public void test_method() {
- * userSession.standalone();
- * {@literal [...]}
- * }
- * </pre>
- * </p>
- * <p>
- * {@code UserSessionRule}, emulates by default an anonymous
- * session. Therefore, call {@code UserSessionRule.standalone()} is equivalent to calling
- * {@code UserSessionRule.standalone().anonymous()}.
- * </p>
- * <p>
- * To emulate an identified user, either use method {@link #logIn(String)} if you want to specify the user's login, or
- * method {@link #logIn()} which will do the same but using the value of {@link #DEFAULT_LOGIN} as the user's login
- * (use the latest override if you don't care about the actual value of the login, it will save noise in your test).
- * </p>
- */
-public class UserSessionRule implements TestRule, UserSession {
- private static final String DEFAULT_LOGIN = "default_login";
-
- private UserSession currentUserSession;
-
- private UserSessionRule() {
- anonymous();
- }
-
- public static UserSessionRule standalone() {
- return new UserSessionRule();
- }
-
- /**
- * Log in with the default login {@link #DEFAULT_LOGIN}
- */
- public UserSessionRule logIn() {
- return logIn(DEFAULT_LOGIN);
- }
-
- /**
- * Log in with the specified login
- */
- public UserSessionRule logIn(String login) {
- setCurrentUserSession(new MockUserSession(login));
- return this;
- }
-
- /**
- * Log in with the specified login
- */
- public UserSessionRule logIn(UserDto userDto) {
- setCurrentUserSession(new MockUserSession(userDto));
- return this;
- }
-
- /**
- * Disconnect/go anonymous
- */
- public UserSessionRule anonymous() {
- setCurrentUserSession(new AnonymousMockUserSession());
- return this;
- }
-
- public UserSessionRule setRoot() {
- ensureMockUserSession().setRoot(true);
- return this;
- }
-
- public UserSessionRule setNonRoot() {
- ensureMockUserSession().setRoot(false);
- return this;
- }
-
- public UserSessionRule setSystemAdministrator() {
- ensureMockUserSession().setSystemAdministrator(true);
- return this;
- }
-
- public UserSessionRule setNonSystemAdministrator() {
- ensureMockUserSession().setSystemAdministrator(false);
- return this;
- }
-
- public UserSessionRule setExternalIdentity(IdentityProvider identityProvider, ExternalIdentity externalIdentity) {
- ensureMockUserSession().setExternalIdentity(identityProvider, externalIdentity);
- return this;
- }
-
- public UserSessionRule setInternalIdentity() {
- ensureMockUserSession().setInternalIdentity();
- return this;
- }
-
- @Override
- public Statement apply(Statement statement, Description description) {
- return this.statement(statement);
- }
-
- private Statement statement(final Statement base) {
- return new Statement() {
- public void evaluate() throws Throwable {
- UserSessionRule.this.before();
-
- try {
- base.evaluate();
- } finally {
- UserSessionRule.this.after();
- }
-
- }
- };
- }
-
- protected void before() {
- setCurrentUserSession(currentUserSession);
- }
-
- protected void after() {
- this.currentUserSession = null;
- }
-
- public void set(UserSession userSession) {
- checkNotNull(userSession);
- setCurrentUserSession(userSession);
- }
-
- public UserSessionRule registerComponents(ComponentDto... componentDtos) {
- ensureAbstractMockUserSession().registerComponents(componentDtos);
- return this;
- }
-
- public UserSessionRule addProjectPermission(String projectPermission, ComponentDto... components) {
- ensureAbstractMockUserSession().addProjectPermission(projectPermission, components);
- return this;
- }
-
- public UserSessionRule addPermission(OrganizationPermission permission, String organizationUuid) {
- ensureAbstractMockUserSession().addPermission(permission, organizationUuid);
- return this;
- }
-
- public UserSessionRule addPermission(OrganizationPermission permission, OrganizationDto organization) {
- ensureAbstractMockUserSession().addPermission(permission, organization.getUuid());
- return this;
- }
-
- public UserSessionRule setUserId(@Nullable Integer userId) {
- ensureMockUserSession().setUserId(userId);
- return this;
- }
-
- /**
- * Groups that user is member of. User must be logged in. An exception
- * is thrown if session is anonymous.
- */
- public UserSessionRule setGroups(GroupDto... groups) {
- ensureMockUserSession().setGroups(groups);
- return this;
- }
-
- public UserSessionRule setName(@Nullable String s) {
- ensureMockUserSession().setName(s);
- return this;
- }
-
- private AbstractMockUserSession ensureAbstractMockUserSession() {
- checkState(currentUserSession instanceof AbstractMockUserSession, "rule state can not be changed if a UserSession has explicitly been provided");
- return (AbstractMockUserSession) currentUserSession;
- }
-
- private MockUserSession ensureMockUserSession() {
- checkState(currentUserSession instanceof MockUserSession, "rule state can not be changed if a UserSession has explicitly been provided");
- return (MockUserSession) currentUserSession;
- }
-
- private void setCurrentUserSession(UserSession userSession) {
- this.currentUserSession = Preconditions.checkNotNull(userSession);
- }
-
- @Override
- public boolean hasComponentPermission(String permission, ComponentDto component) {
- return currentUserSession.hasComponentPermission(permission, component);
- }
-
- @Override
- public boolean hasComponentUuidPermission(String permission, String componentUuid) {
- return currentUserSession.hasComponentUuidPermission(permission, componentUuid);
- }
-
- @Override
- public List<ComponentDto> keepAuthorizedComponents(String permission, Collection<ComponentDto> components) {
- return currentUserSession.keepAuthorizedComponents(permission, components);
- }
-
- @Override
- @CheckForNull
- public String getLogin() {
- return currentUserSession.getLogin();
- }
-
- @Override
- @CheckForNull
- public String getUuid() {
- return currentUserSession.getUuid();
- }
-
- @Override
- @CheckForNull
- public String getName() {
- return currentUserSession.getName();
- }
-
- @Override
- @CheckForNull
- public Integer getUserId() {
- return currentUserSession.getUserId();
- }
-
- @Override
- public Collection<GroupDto> getGroups() {
- return currentUserSession.getGroups();
- }
-
- @Override
- public Optional<IdentityProvider> getIdentityProvider() {
- return currentUserSession.getIdentityProvider();
- }
-
- @Override
- public Optional<ExternalIdentity> getExternalIdentity() {
- return currentUserSession.getExternalIdentity();
- }
-
- @Override
- public boolean isLoggedIn() {
- return currentUserSession.isLoggedIn();
- }
-
- @Override
- public boolean isRoot() {
- return currentUserSession.isRoot();
- }
-
- @Override
- public UserSession checkIsRoot() {
- return currentUserSession.checkIsRoot();
- }
-
- @Override
- public UserSession checkLoggedIn() {
- currentUserSession.checkLoggedIn();
- return this;
- }
-
- @Override
- public boolean hasPermission(OrganizationPermission permission, OrganizationDto organization) {
- return currentUserSession.hasPermission(permission, organization);
- }
-
- @Override
- public boolean hasPermission(OrganizationPermission permission, String organizationUuid) {
- return currentUserSession.hasPermission(permission, organizationUuid);
- }
-
- @Override
- public UserSession checkPermission(OrganizationPermission permission, OrganizationDto organization) {
- currentUserSession.checkPermission(permission, organization);
- return this;
- }
-
- @Override
- public UserSession checkPermission(OrganizationPermission permission, String organizationUuid) {
- currentUserSession.checkPermission(permission, organizationUuid);
- return this;
- }
-
- @Override
- public UserSession checkComponentPermission(String projectPermission, ComponentDto component) {
- currentUserSession.checkComponentPermission(projectPermission, component);
- return this;
- }
-
- @Override
- public UserSession checkComponentUuidPermission(String permission, String componentUuid) {
- currentUserSession.checkComponentUuidPermission(permission, componentUuid);
- return this;
- }
-
- @Override
- public boolean isSystemAdministrator() {
- return currentUserSession.isSystemAdministrator();
- }
-
- @Override
- public UserSession checkIsSystemAdministrator() {
- currentUserSession.checkIsSystemAdministrator();
- return this;
- }
-
- @Override
- public boolean hasMembership(OrganizationDto organization) {
- return currentUserSession.hasMembership(organization);
- }
-
- @Override
- public UserSession checkMembership(OrganizationDto organization) {
- currentUserSession.checkMembership(organization);
- return this;
- }
-
- public UserSessionRule addMembership(OrganizationDto organization) {
- ensureAbstractMockUserSession().addOrganizationMembership(organization);
- return this;
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/package-info.java b/server/sonar-server/src/test/java/org/sonar/server/tester/package-info.java
deleted file mode 100644
index 27beb989b45..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/tester/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.server.tester;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/CompatibilityRealmTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/CompatibilityRealmTest.java
deleted file mode 100644
index be3f0360ddb..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/CompatibilityRealmTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.junit.Test;
-import org.sonar.api.security.LoginPasswordAuthenticator;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class CompatibilityRealmTest {
-
- @Test
- public void shouldDelegate() {
- LoginPasswordAuthenticator authenticator = mock(LoginPasswordAuthenticator.class);
- CompatibilityRealm realm = new CompatibilityRealm(authenticator);
- realm.init();
- verify(authenticator).init();
- assertThat(realm.getLoginPasswordAuthenticator()).isSameAs(authenticator);
- assertThat(realm.getName()).isEqualTo("CompatibilityRealm[" + authenticator.getClass().getName() + "]");
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/DefaultUserTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/DefaultUserTest.java
deleted file mode 100644
index 5450d38987a..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/DefaultUserTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.junit.Test;
-import org.sonar.core.user.DefaultUser;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultUserTest {
- @Test
- public void test_object_methods() {
- DefaultUser john = new DefaultUser().setLogin("john").setName("John");
- DefaultUser eric = new DefaultUser().setLogin("eric").setName("Eric");
-
- assertThat(john).isEqualTo(john);
- assertThat(john).isNotEqualTo(eric);
- assertThat(john.hashCode()).isEqualTo(john.hashCode());
- assertThat(john.toString()).contains("login=john").contains("name=John");
- }
-
- @Test
- public void test_email() {
- DefaultUser user = new DefaultUser();
- assertThat(user.email()).isNull();
-
- user.setEmail("");
- assertThat(user.email()).isNull();
-
- user.setEmail(" ");
- assertThat(user.email()).isNull();
-
- user.setEmail("s@b.com");
- assertThat(user.email()).isEqualTo("s@b.com");
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/DoPrivilegedTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/DoPrivilegedTest.java
deleted file mode 100644
index cd9f2af3a5a..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/DoPrivilegedTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.server.tester.MockUserSession;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;
-
-public class DoPrivilegedTest {
-
- private static final String LOGIN = "dalailaHidou!";
-
- private ThreadLocalUserSession threadLocalUserSession = new ThreadLocalUserSession();
- private MockUserSession session = new MockUserSession(LOGIN);
-
- @Before
- public void setUp() {
- threadLocalUserSession.set(session);
- }
-
- @Test
- public void allow_everything_in_privileged_block_only() {
- UserSessionCatcherTask catcher = new UserSessionCatcherTask();
-
- DoPrivileged.execute(catcher);
-
- // verify the session used inside Privileged task
- assertThat(catcher.userSession.isLoggedIn()).isFalse();
- assertThat(catcher.userSession.hasComponentPermission("any permission", new ComponentDto())).isTrue();
- assertThat(catcher.userSession.isSystemAdministrator()).isTrue();
- assertThat(catcher.userSession.hasMembership(newOrganizationDto())).isTrue();
-
- // verify session in place after task is done
- assertThat(threadLocalUserSession.get()).isSameAs(session);
- }
-
- @Test
- public void loose_privileges_on_exception() {
- UserSessionCatcherTask catcher = new UserSessionCatcherTask() {
- @Override
- protected void doPrivileged() {
- super.doPrivileged();
- throw new RuntimeException("Test to lose privileges");
- }
- };
-
- try {
- DoPrivileged.execute(catcher);
- fail("An exception should have been raised!");
- } catch (Throwable ignored) {
- // verify session in place after task is done
- assertThat(threadLocalUserSession.get()).isSameAs(session);
-
- // verify the session used inside Privileged task
- assertThat(catcher.userSession.isLoggedIn()).isFalse();
- assertThat(catcher.userSession.hasComponentPermission("any permission", new ComponentDto())).isTrue();
- assertThat(catcher.userSession.hasMembership(newOrganizationDto())).isTrue();
- }
- }
-
- private class UserSessionCatcherTask extends DoPrivileged.Task {
- UserSession userSession;
-
- public UserSessionCatcherTask() {
- super(DoPrivilegedTest.this.threadLocalUserSession);
- }
-
- @Override
- protected void doPrivileged() {
- userSession = threadLocalUserSession.get();
- }
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ExternalIdentityTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ExternalIdentityTest.java
deleted file mode 100644
index b6857add6eb..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/ExternalIdentityTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ExternalIdentityTest {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- @Test
- public void create_external_identity() {
- ExternalIdentity externalIdentity = new ExternalIdentity("github", "login", "ABCD");
- assertThat(externalIdentity.getLogin()).isEqualTo("login");
- assertThat(externalIdentity.getProvider()).isEqualTo("github");
- assertThat(externalIdentity.getId()).isEqualTo("ABCD");
- }
-
- @Test
- public void login_is_used_when_id_is_not_provided() {
- ExternalIdentity externalIdentity = new ExternalIdentity("github", "login", null);
- assertThat(externalIdentity.getLogin()).isEqualTo("login");
- assertThat(externalIdentity.getProvider()).isEqualTo("github");
- assertThat(externalIdentity.getId()).isEqualTo("login");
- }
-
- @Test
- public void fail_with_NPE_when_identity_provider_is_null() {
- thrown.expect(NullPointerException.class);
- thrown.expectMessage("Identity provider cannot be null");
-
- new ExternalIdentity(null, "login", "ABCD");
- }
-
- @Test
- public void fail_with_NPE_when_identity_login_is_null() {
- thrown.expect(NullPointerException.class);
- thrown.expectMessage("Identity login cannot be null");
-
- new ExternalIdentity("github", null, "ABCD");
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/NewUserNotifierTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/NewUserNotifierTest.java
deleted file mode 100644
index 441487aa7ab..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/NewUserNotifierTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.junit.Test;
-import org.sonar.api.platform.NewUserHandler;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class NewUserNotifierTest {
-
- NewUserHandler.Context context = NewUserHandler.Context.builder().setLogin("marius").setName("Marius").build();
-
- @Test
- public void do_not_fail_if_no_handlers() {
- NewUserNotifier notifier = new NewUserNotifier();
-
- notifier.onNewUser(context);
- }
-
- @Test
- public void execute_handlers_on_new_user() {
- NewUserHandler handler1 = mock(NewUserHandler.class);
- NewUserHandler handler2 = mock(NewUserHandler.class);
- NewUserNotifier notifier = new NewUserNotifier(new NewUserHandler[]{handler1, handler2});
-
-
- notifier.onNewUser(context);
-
- verify(handler1).doOnNewUser(context);
- verify(handler2).doOnNewUser(context);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/NewUserTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/NewUserTest.java
deleted file mode 100644
index 9d412b7a519..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/NewUserTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class NewUserTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Test
- public void create_new_user() {
- NewUser newUser = NewUser.builder()
- .setLogin("login")
- .setName("name")
- .setEmail("email")
- .setPassword("password")
- .setScmAccounts(asList("login1", "login2"))
- .build();
-
- assertThat(newUser.login()).isEqualTo("login");
- assertThat(newUser.name()).isEqualTo("name");
- assertThat(newUser.email()).isEqualTo("email");
- assertThat(newUser.password()).isEqualTo("password");
- assertThat(newUser.scmAccounts()).contains("login1", "login2");
- assertThat(newUser.externalIdentity()).isNull();
- }
-
- @Test
- public void create_new_user_with_minimal_fields() {
- NewUser newUser = NewUser.builder().build();
-
- assertThat(newUser.login()).isNull();
- assertThat(newUser.name()).isNull();
- assertThat(newUser.email()).isNull();
- assertThat(newUser.password()).isNull();
- assertThat(newUser.scmAccounts()).isEmpty();
- }
-
- @Test
- public void create_new_user_with_authority() {
- NewUser newUser = NewUser.builder()
- .setLogin("login")
- .setName("name")
- .setEmail("email")
- .setExternalIdentity(new ExternalIdentity("github", "github_login", "ABCD"))
- .build();
-
- assertThat(newUser.externalIdentity().getProvider()).isEqualTo("github");
- assertThat(newUser.externalIdentity().getLogin()).isEqualTo("github_login");
- assertThat(newUser.externalIdentity().getId()).isEqualTo("ABCD");
- }
-
- @Test
- public void fail_to_set_password_when_external_identity_is_set() {
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Password should not be set with an external identity");
-
- NewUser.builder()
- .setLogin("login")
- .setName("name")
- .setEmail("email")
- .setPassword("password")
- .setExternalIdentity(new ExternalIdentity("github", "github_login", "ABCD"))
- .build();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/SecurityRealmFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/SecurityRealmFactoryTest.java
deleted file mode 100644
index d680692abd6..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/SecurityRealmFactoryTest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.junit.Test;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.security.LoginPasswordAuthenticator;
-import org.sonar.api.security.SecurityRealm;
-import org.sonar.api.utils.SonarException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-public class SecurityRealmFactoryTest {
-
- private MapSettings settings = new MapSettings();
-
- /**
- * Typical usage.
- */
- @Test
- public void should_select_realm_and_start() {
- SecurityRealm realm = spy(new FakeRealm());
- settings.setProperty("sonar.security.realm", realm.getName());
-
- SecurityRealmFactory factory = new SecurityRealmFactory(settings.asConfig(), new SecurityRealm[] {realm});
- factory.start();
- assertThat(factory.getRealm()).isSameAs(realm);
- assertThat(factory.hasExternalAuthentication()).isTrue();
- verify(realm).init();
-
- factory.stop();
- }
-
- @Test
- public void do_not_fail_if_no_realms() {
- SecurityRealmFactory factory = new SecurityRealmFactory(settings.asConfig());
- factory.start();
- assertThat(factory.getRealm()).isNull();
- assertThat(factory.hasExternalAuthentication()).isFalse();
- }
-
- @Test
- public void realm_not_found() {
- settings.setProperty("sonar.security.realm", "Fake");
-
- try {
- new SecurityRealmFactory(settings.asConfig());
- fail();
- } catch (SonarException e) {
- assertThat(e.getMessage()).contains("Realm 'Fake' not found.");
- }
- }
-
- @Test
- public void should_provide_compatibility_for_authenticator() {
- settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FakeAuthenticator.class.getName());
- LoginPasswordAuthenticator authenticator = new FakeAuthenticator();
-
- SecurityRealmFactory factory = new SecurityRealmFactory(settings.asConfig(), new LoginPasswordAuthenticator[] {authenticator});
- SecurityRealm realm = factory.getRealm();
- assertThat(realm).isInstanceOf(CompatibilityRealm.class);
- }
-
- @Test
- public void should_take_precedence_over_authenticator() {
- SecurityRealm realm = new FakeRealm();
- settings.setProperty("sonar.security.realm", realm.getName());
- LoginPasswordAuthenticator authenticator = new FakeAuthenticator();
- settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FakeAuthenticator.class.getName());
-
- SecurityRealmFactory factory = new SecurityRealmFactory(settings.asConfig(), new SecurityRealm[] {realm},
- new LoginPasswordAuthenticator[] {authenticator});
- assertThat(factory.getRealm()).isSameAs(realm);
- }
-
- @Test
- public void authenticator_not_found() {
- settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, "Fake");
-
- try {
- new SecurityRealmFactory(settings.asConfig());
- fail();
- } catch (SonarException e) {
- assertThat(e.getMessage()).contains("Authenticator 'Fake' not found.");
- }
- }
-
- @Test
- public void ignore_startup_failure() {
- SecurityRealm realm = spy(new AlwaysFailsRealm());
- settings.setProperty("sonar.security.realm", realm.getName());
- settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE, true);
-
- new SecurityRealmFactory(settings.asConfig(), new SecurityRealm[] {realm}).start();
- verify(realm).init();
- }
-
- @Test
- public void should_fail() {
- SecurityRealm realm = spy(new AlwaysFailsRealm());
- settings.setProperty("sonar.security.realm", realm.getName());
-
- try {
- new SecurityRealmFactory(settings.asConfig(), new SecurityRealm[] {realm}).start();
- fail();
- } catch (SonarException e) {
- assertThat(e.getCause()).isInstanceOf(IllegalStateException.class);
- assertThat(e.getMessage()).contains("Security realm fails to start");
- }
- }
-
- private static class AlwaysFailsRealm extends FakeRealm {
- @Override
- public void init() {
- throw new IllegalStateException();
- }
- }
-
- private static class FakeRealm extends SecurityRealm {
- @Override
- public LoginPasswordAuthenticator getLoginPasswordAuthenticator() {
- return null;
- }
- }
-
- private static class FakeAuthenticator implements LoginPasswordAuthenticator {
- public void init() {
- }
-
- public boolean authenticate(String login, String password) {
- return false;
- }
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ServerUserSessionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ServerUserSessionTest.java
deleted file mode 100644
index af654c54493..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/ServerUserSessionTest.java
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import java.util.Arrays;
-import javax.annotation.Nullable;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.organization.TestDefaultOrganizationProvider;
-import org.sonar.server.organization.TestOrganizationFlags;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
-import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
-import static org.sonar.db.component.ComponentTesting.newChildComponent;
-import static org.sonar.db.component.ComponentTesting.newFileDto;
-import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
-import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS;
-import static org.sonar.db.permission.OrganizationPermission.SCAN;
-
-public class ServerUserSessionTest {
-
- @Rule
- public DbTester db = DbTester.create(System2.INSTANCE);
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- private DbClient dbClient = db.getDbClient();
- private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
- private TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
-
- @Test
- public void anonymous_is_not_logged_in_and_does_not_have_login() {
- UserSession session = newAnonymousSession();
-
- assertThat(session.getLogin()).isNull();
- assertThat(session.getUuid()).isNull();
- assertThat(session.isLoggedIn()).isFalse();
- }
-
- @Test
- public void getGroups_is_empty_on_anonymous() {
- assertThat(newAnonymousSession().getGroups()).isEmpty();
- }
-
- @Test
- public void getGroups_is_empty_if_user_is_not_member_of_any_group() {
- UserDto user = db.users().insertUser();
- assertThat(newUserSession(user).getGroups()).isEmpty();
- }
-
- @Test
- public void getGroups_returns_the_groups_of_logged_in_user() {
- UserDto user = db.users().insertUser();
- GroupDto group1 = db.users().insertGroup();
- GroupDto group2 = db.users().insertGroup();
- db.users().insertMember(group1, user);
- db.users().insertMember(group2, user);
-
- assertThat(newUserSession(user).getGroups()).extracting(GroupDto::getId).containsOnly(group1.getId(), group2.getId());
- }
-
- @Test
- public void getGroups_keeps_groups_in_cache() {
- UserDto user = db.users().insertUser();
- GroupDto group1 = db.users().insertGroup();
- GroupDto group2 = db.users().insertGroup();
- db.users().insertMember(group1, user);
-
- ServerUserSession session = newUserSession(user);
- assertThat(session.getGroups()).extracting(GroupDto::getId).containsOnly(group1.getId());
-
- // membership updated but not cache
- db.users().insertMember(group2, user);
- assertThat(session.getGroups()).extracting(GroupDto::getId).containsOnly(group1.getId());
- }
-
- @Test
- public void isRoot_is_false_is_flag_root_is_false_on_UserDto() {
- UserDto root = db.users().insertUser();
- root = db.users().makeRoot(root);
- assertThat(newUserSession(root).isRoot()).isTrue();
-
- UserDto notRoot = db.users().insertUser();
- assertThat(newUserSession(notRoot).isRoot()).isFalse();
- }
-
- @Test
- public void checkIsRoot_throws_IPFE_if_flag_root_is_false_on_UserDto() {
- UserDto user = db.users().insertUser();
- UserSession underTest = newUserSession(user);
-
- expectInsufficientPrivilegesForbiddenException();
-
- underTest.checkIsRoot();
- }
-
- @Test
- public void checkIsRoot_does_not_fail_if_flag_root_is_true_on_UserDto() {
- UserDto root = db.users().insertUser();
- root = db.users().makeRoot(root);
-
- UserSession underTest = newUserSession(root);
-
- assertThat(underTest.checkIsRoot()).isSameAs(underTest);
- }
-
- @Test
- public void hasComponentUuidPermission_returns_true_when_flag_root_is_true_on_UserDto_no_matter_if_user_has_project_permission_for_given_uuid() {
- UserDto root = db.users().insertUser();
- root = db.users().makeRoot(root);
- OrganizationDto organization = db.organizations().insert();
- ComponentDto project = db.components().insertPrivateProject(organization);
- ComponentDto file = db.components().insertComponent(newFileDto(project));
-
- UserSession underTest = newUserSession(root);
-
- assertThat(underTest.hasComponentUuidPermission(UserRole.USER, file.uuid())).isTrue();
- assertThat(underTest.hasComponentUuidPermission(UserRole.CODEVIEWER, file.uuid())).isTrue();
- assertThat(underTest.hasComponentUuidPermission(UserRole.ADMIN, file.uuid())).isTrue();
- assertThat(underTest.hasComponentUuidPermission("whatever", "who cares?")).isTrue();
- }
-
- @Test
- public void checkComponentUuidPermission_succeeds_if_user_has_permission_for_specified_uuid_in_db() {
- UserDto root = db.users().insertUser();
- root = db.users().makeRoot(root);
- OrganizationDto organization = db.organizations().insert();
- ComponentDto project = db.components().insertPrivateProject(organization);
- ComponentDto file = db.components().insertComponent(newFileDto(project));
-
- UserSession underTest = newUserSession(root);
-
- assertThat(underTest.checkComponentUuidPermission(UserRole.USER, file.uuid())).isSameAs(underTest);
- assertThat(underTest.checkComponentUuidPermission("whatever", "who cares?")).isSameAs(underTest);
- }
-
- @Test
- public void checkComponentUuidPermission_fails_with_FE_when_user_has_not_permission_for_specified_uuid_in_db() {
- UserDto user = db.users().insertUser();
- ComponentDto project = db.components().insertPrivateProject();
- db.users().insertProjectPermissionOnUser(user, UserRole.USER, project);
- UserSession session = newUserSession(user);
-
- expectInsufficientPrivilegesForbiddenException();
-
- session.checkComponentUuidPermission(UserRole.USER, "another-uuid");
- }
-
- @Test
- public void checkPermission_throws_ForbiddenException_when_user_doesnt_have_the_specified_permission_on_organization() {
- OrganizationDto org = db.organizations().insert();
- UserDto user = db.users().insertUser();
-
- expectInsufficientPrivilegesForbiddenException();
-
- newUserSession(user).checkPermission(PROVISION_PROJECTS, org);
- }
-
- @Test
- public void checkPermission_succeeds_when_user_has_the_specified_permission_on_organization() {
- OrganizationDto org = db.organizations().insert();
- UserDto root = db.users().insertUser();
- root = db.users().makeRoot(root);
- db.users().insertPermissionOnUser(org, root, PROVISIONING);
-
- newUserSession(root).checkPermission(PROVISION_PROJECTS, org);
- }
-
- @Test
- public void checkPermission_succeeds_when_user_is_root() {
- OrganizationDto org = db.organizations().insert();
- UserDto root = db.users().insertUser();
- root = db.users().makeRoot(root);
-
- newUserSession(root).checkPermission(PROVISION_PROJECTS, org);
- }
-
- @Test
- public void test_hasPermission_on_organization_for_logged_in_user() {
- OrganizationDto org = db.organizations().insert();
- ComponentDto project = db.components().insertPrivateProject(org);
- UserDto user = db.users().insertUser();
- db.users().insertPermissionOnUser(org, user, PROVISION_PROJECTS);
- db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, project);
-
- UserSession session = newUserSession(user);
- assertThat(session.hasPermission(PROVISION_PROJECTS, org.getUuid())).isTrue();
- assertThat(session.hasPermission(ADMINISTER, org.getUuid())).isFalse();
- assertThat(session.hasPermission(PROVISION_PROJECTS, "another-org")).isFalse();
- }
-
- @Test
- public void test_hasPermission_on_organization_for_anonymous_user() {
- OrganizationDto org = db.organizations().insert();
- db.users().insertPermissionOnAnyone(org, PROVISION_PROJECTS);
-
- UserSession session = newAnonymousSession();
- assertThat(session.hasPermission(PROVISION_PROJECTS, org.getUuid())).isTrue();
- assertThat(session.hasPermission(ADMINISTER, org.getUuid())).isFalse();
- assertThat(session.hasPermission(PROVISION_PROJECTS, "another-org")).isFalse();
- }
-
- @Test
- public void hasPermission_on_organization_keeps_cache_of_permissions_of_logged_in_user() {
- OrganizationDto org = db.organizations().insert();
- UserDto user = db.users().insertUser();
- db.users().insertPermissionOnUser(org, user, PROVISIONING);
-
- UserSession session = newUserSession(user);
-
- // feed the cache
- assertThat(session.hasPermission(PROVISION_PROJECTS, org.getUuid())).isTrue();
-
- // change permissions without updating the cache
- db.users().deletePermissionFromUser(org, user, PROVISION_PROJECTS);
- db.users().insertPermissionOnUser(org, user, SCAN);
- assertThat(session.hasPermission(PROVISION_PROJECTS, org.getUuid())).isTrue();
- assertThat(session.hasPermission(ADMINISTER, org.getUuid())).isFalse();
- assertThat(session.hasPermission(SCAN, org.getUuid())).isFalse();
- }
-
- @Test
- public void hasPermission_on_organization_keeps_cache_of_permissions_of_anonymous_user() {
- OrganizationDto org = db.organizations().insert();
- db.users().insertPermissionOnAnyone(org, PROVISION_PROJECTS);
-
- UserSession session = newAnonymousSession();
-
- // feed the cache
- assertThat(session.hasPermission(PROVISION_PROJECTS, org.getUuid())).isTrue();
-
- // change permissions without updating the cache
- db.users().insertPermissionOnAnyone(org, SCAN);
- assertThat(session.hasPermission(PROVISION_PROJECTS, org.getUuid())).isTrue();
- assertThat(session.hasPermission(SCAN, org.getUuid())).isFalse();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_true_for_anonymous_user_for_permissions_USER_and_CODEVIEWER_on_public_projects_without_permissions() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
-
- ServerUserSession underTest = newAnonymousSession();
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, publicProject)).isTrue();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, publicProject)).isTrue();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_true_for_anonymous_user_for_permissions_USER_and_CODEVIEWER_on_public_projects_with_global_permissions() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- db.users().insertProjectPermissionOnAnyone("p1", publicProject);
-
- ServerUserSession underTest = newAnonymousSession();
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, publicProject)).isTrue();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, publicProject)).isTrue();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_true_for_anonymous_user_for_permissions_USER_and_CODEVIEWER_on_public_projects_with_group_permissions() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- db.users().insertProjectPermissionOnGroup(db.users().insertGroup(organization), "p1", publicProject);
-
- ServerUserSession underTest = newAnonymousSession();
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, publicProject)).isTrue();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, publicProject)).isTrue();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_true_for_anonymous_user_for_permissions_USER_and_CODEVIEWER_on_public_projects_with_user_permissions() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- db.users().insertProjectPermissionOnUser(db.users().insertUser(), "p1", publicProject);
-
- ServerUserSession underTest = newAnonymousSession();
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, publicProject)).isTrue();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, publicProject)).isTrue();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_false_for_authenticated_user_for_permissions_USER_and_CODEVIEWER_on_private_projects_without_permissions() {
- UserDto user = db.users().insertUser();
- ComponentDto privateProject = db.components().insertPrivateProject();
-
- ServerUserSession underTest = newUserSession(user);
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, privateProject)).isFalse();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, privateProject)).isFalse();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_false_for_authenticated_user_for_permissions_USER_and_CODEVIEWER_on_private_projects_with_group_permissions() {
- UserDto user = db.users().insertUser();
- OrganizationDto organization = db.organizations().insert();
- ComponentDto privateProject = db.components().insertPrivateProject(organization);
- db.users().insertProjectPermissionOnGroup(db.users().insertGroup(organization), "p1", privateProject);
-
- ServerUserSession underTest = newUserSession(user);
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, privateProject)).isFalse();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, privateProject)).isFalse();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_false_for_authenticated_user_for_permissions_USER_and_CODEVIEWER_on_private_projects_with_user_permissions() {
- UserDto user = db.users().insertUser();
- ComponentDto privateProject = db.components().insertPrivateProject();
- db.users().insertProjectPermissionOnUser(db.users().insertUser(), "p1", privateProject);
-
- ServerUserSession underTest = newUserSession(user);
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, privateProject)).isFalse();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, privateProject)).isFalse();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_true_for_anonymous_user_for_inserted_permissions_on_group_AnyOne_on_public_projects() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- db.users().insertProjectPermissionOnAnyone("p1", publicProject);
-
- ServerUserSession underTest = newAnonymousSession();
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", publicProject)).isTrue();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_false_for_anonymous_user_for_inserted_permissions_on_group_on_public_projects() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- GroupDto group = db.users().insertGroup(organization);
- db.users().insertProjectPermissionOnGroup(group, "p1", publicProject);
-
- ServerUserSession underTest = newAnonymousSession();
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", publicProject)).isFalse();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_false_for_anonymous_user_for_inserted_permissions_on_group_on_private_projects() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto privateProject = db.components().insertPrivateProject(organization);
- GroupDto group = db.users().insertGroup(organization);
- db.users().insertProjectPermissionOnGroup(group, "p1", privateProject);
-
- ServerUserSession underTest = newAnonymousSession();
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", privateProject)).isFalse();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_false_for_anonymous_user_for_inserted_permissions_on_user_on_public_projects() {
- UserDto user = db.users().insertUser();
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- db.users().insertProjectPermissionOnUser(user, "p1", publicProject);
-
- ServerUserSession underTest = newAnonymousSession();
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", publicProject)).isFalse();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_false_for_anonymous_user_for_inserted_permissions_on_user_on_private_projects() {
- UserDto user = db.users().insertUser();
- ComponentDto project = db.components().insertPrivateProject();
- db.users().insertProjectPermissionOnUser(user, "p1", project);
-
- ServerUserSession underTest = newAnonymousSession();
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", project)).isFalse();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_returns_true_for_any_project_or_permission_for_root_user() {
- UserDto root = db.users().insertUser();
- root = db.users().makeRoot(root);
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
-
- ServerUserSession underTest = newUserSession(root);
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, "does not matter", publicProject)).isTrue();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_keeps_cache_of_permissions_of_logged_in_user() {
- UserDto user = db.users().insertUser();
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, publicProject);
-
- UserSession underTest = newUserSession(user);
-
- // feed the cache
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.ADMIN, publicProject)).isTrue();
-
- // change permissions without updating the cache
- db.users().deletePermissionFromUser(publicProject, user, UserRole.ADMIN);
- db.users().insertProjectPermissionOnUser(user, UserRole.ISSUE_ADMIN, publicProject);
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.ADMIN, publicProject)).isTrue();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.ISSUE_ADMIN, publicProject)).isFalse();
- }
-
- @Test
- public void hasComponentPermissionByDtoOrUuid_keeps_cache_of_permissions_of_anonymous_user() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- db.users().insertProjectPermissionOnAnyone(UserRole.ADMIN, publicProject);
-
- UserSession underTest = newAnonymousSession();
-
- // feed the cache
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.ADMIN, publicProject)).isTrue();
-
- // change permissions without updating the cache
- db.users().deleteProjectPermissionFromAnyone(publicProject, UserRole.ADMIN);
- db.users().insertProjectPermissionOnAnyone(UserRole.ISSUE_ADMIN, publicProject);
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.ADMIN, publicProject)).isTrue();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.ISSUE_ADMIN, publicProject)).isFalse();
- }
-
- private boolean hasComponentPermissionByDtoOrUuid(UserSession underTest, String permission, ComponentDto component) {
- boolean b1 = underTest.hasComponentPermission(permission, component);
- boolean b2 = underTest.hasComponentUuidPermission(permission, component.uuid());
- checkState(b1 == b2, "Different behaviors");
- return b1;
- }
-
- @Test
- public void keepAuthorizedComponents_returns_empty_list_if_no_permissions_are_granted() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- ComponentDto privateProject = db.components().insertPrivateProject(organization);
-
- UserSession underTest = newAnonymousSession();
-
- assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(privateProject, publicProject))).isEmpty();
- }
-
- @Test
- public void keepAuthorizedComponents_filters_components_with_granted_permissions_for_logged_in_user() {
- UserDto user = db.users().insertUser();
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- ComponentDto privateProject = db.components().insertPrivateProject(organization);
- db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, privateProject);
-
- UserSession underTest = newUserSession(user);
-
- assertThat(underTest.keepAuthorizedComponents(UserRole.ISSUE_ADMIN, Arrays.asList(privateProject, publicProject))).isEmpty();
- assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(privateProject, publicProject))).containsExactly(privateProject);
- }
-
- @Test
- public void keepAuthorizedComponents_filters_components_with_granted_permissions_for_anonymous() {
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- ComponentDto privateProject = db.components().insertPrivateProject(organization);
- db.users().insertProjectPermissionOnAnyone(UserRole.ISSUE_ADMIN, publicProject);
-
- UserSession underTest = newAnonymousSession();
-
- assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(privateProject, publicProject))).isEmpty();
- assertThat(underTest.keepAuthorizedComponents(UserRole.ISSUE_ADMIN, Arrays.asList(privateProject, publicProject))).containsExactly(publicProject);
- }
-
- @Test
- public void keepAuthorizedComponents_returns_all_specified_components_if_root() {
- UserDto root = db.users().insertUser();
- root = db.users().makeRoot(root);
- OrganizationDto organization = db.organizations().insert();
- ComponentDto publicProject = db.components().insertPublicProject(organization);
- ComponentDto privateProject = db.components().insertPrivateProject(organization);
-
- UserSession underTest = newUserSession(root);
-
- assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(privateProject, publicProject)))
- .containsExactly(privateProject, publicProject);
- }
-
- @Test
- public void keepAuthorizedComponents_on_branches() {
- UserDto user = db.users().insertUser();
- ComponentDto privateProject = db.components().insertPrivateProject();
- db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, privateProject);
- ComponentDto privateBranchProject = db.components().insertProjectBranch(privateProject);
-
- UserSession underTest = newUserSession(user);
-
- assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, asList(privateProject, privateBranchProject)))
- .containsExactlyInAnyOrder(privateProject, privateBranchProject);
- }
-
- @Test
- public void isSystemAdministrator_returns_true_if_org_feature_is_enabled_and_user_is_root() {
- organizationFlags.setEnabled(true);
- UserDto root = db.users().insertUser();
- root = db.users().makeRoot(root);
-
- UserSession session = newUserSession(root);
-
- assertThat(session.isSystemAdministrator()).isTrue();
- }
-
- @Test
- public void isSystemAdministrator_returns_false_if_org_feature_is_enabled_and_user_is_not_root() {
- organizationFlags.setEnabled(true);
- UserDto user = db.users().insertUser();
-
- UserSession session = newUserSession(user);
-
- assertThat(session.isSystemAdministrator()).isFalse();
- }
-
- @Test
- public void isSystemAdministrator_returns_false_if_org_feature_is_enabled_and_user_is_administrator_of_default_organization() {
- organizationFlags.setEnabled(true);
- UserDto user = db.users().insertUser();
- db.users().insertPermissionOnUser(db.getDefaultOrganization(), user, SYSTEM_ADMIN);
-
- UserSession session = newUserSession(user);
-
- assertThat(session.isSystemAdministrator()).isFalse();
- }
-
- @Test
- public void isSystemAdministrator_returns_true_if_org_feature_is_disabled_and_user_is_administrator_of_default_organization() {
- organizationFlags.setEnabled(false);
- UserDto user = db.users().insertUser();
- db.users().insertPermissionOnUser(db.getDefaultOrganization(), user, SYSTEM_ADMIN);
-
- UserSession session = newUserSession(user);
-
- assertThat(session.isSystemAdministrator()).isTrue();
- }
-
- @Test
- public void isSystemAdministrator_returns_false_if_org_feature_is_disabled_and_user_is_not_administrator_of_default_organization() {
- organizationFlags.setEnabled(true);
- UserDto user = db.users().insertUser();
- db.users().insertPermissionOnUser(db.getDefaultOrganization(), user, PROVISIONING);
-
- UserSession session = newUserSession(user);
-
- assertThat(session.isSystemAdministrator()).isFalse();
- }
-
- @Test
- public void keep_isSystemAdministrator_flag_in_cache() {
- organizationFlags.setEnabled(false);
- UserDto user = db.users().insertUser();
- db.users().insertPermissionOnUser(db.getDefaultOrganization(), user, SYSTEM_ADMIN);
-
- UserSession session = newUserSession(user);
-
- session.checkIsSystemAdministrator();
-
- db.getDbClient().userDao().deactivateUser(db.getSession(), user);
- db.commit();
-
- // should fail but succeeds because flag is kept in cache
- session.checkIsSystemAdministrator();
- }
-
- @Test
- public void checkIsSystemAdministrator_succeeds_if_system_administrator() {
- organizationFlags.setEnabled(true);
- UserDto root = db.users().insertUser();
- root = db.users().makeRoot(root);
-
- UserSession session = newUserSession(root);
-
- session.checkIsSystemAdministrator();
- }
-
- @Test
- public void checkIsSystemAdministrator_throws_ForbiddenException_if_not_system_administrator() {
- organizationFlags.setEnabled(true);
- UserDto user = db.users().insertUser();
-
- UserSession session = newUserSession(user);
-
- expectedException.expect(ForbiddenException.class);
- expectedException.expectMessage("Insufficient privileges");
-
- session.checkIsSystemAdministrator();
- }
-
- @Test
- public void hasComponentPermission_on_branch_checks_permissions_of_its_project() {
- UserDto user = db.users().insertUser();
- ComponentDto privateProject = db.components().insertPrivateProject();
- ComponentDto branch = db.components().insertProjectBranch(privateProject, b -> b.setKey("feature/foo"));
- ComponentDto fileInBranch = db.components().insertComponent(newChildComponent("fileUuid", branch, branch));
-
- // permissions are defined on the project, not on the branch
- db.users().insertProjectPermissionOnUser(user, "p1", privateProject);
-
- UserSession underTest = newUserSession(user);
-
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", privateProject)).isTrue();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", branch)).isTrue();
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", fileInBranch)).isTrue();
- }
-
- @Test
- public void hasMembership() {
- OrganizationDto organization = db.organizations().insert();
- UserDto notMember = db.users().insertUser();
- UserDto member = db.users().insertUser();
- db.organizations().addMember(organization, member);
- UserDto root = db.users().makeRoot(db.users().insertUser());
-
- assertThat(newUserSession(member).hasMembership(organization)).isTrue();
- assertThat(newUserSession(notMember).hasMembership(organization)).isFalse();
- assertThat(newUserSession(root).hasMembership(organization)).isTrue();
- }
-
- @Test
- public void hasMembership_keeps_membership_in_cache() {
- OrganizationDto organization = db.organizations().insert();
- UserDto user = db.users().insertUser();
- db.organizations().addMember(organization, user);
-
- ServerUserSession session = newUserSession(user);
- assertThat(session.hasMembership(organization)).isTrue();
-
- // membership updated but not cache
- db.getDbClient().organizationMemberDao().delete(db.getSession(), organization.getUuid(), user.getId());
- db.commit();
- assertThat(session.hasMembership(organization)).isTrue();
- }
-
- @Test
- public void checkMembership_throws_ForbiddenException_when_user_is_not_member_of_organization() {
- OrganizationDto organization = db.organizations().insert();
- UserDto notMember = db.users().insertUser();
-
- expectedException.expect(ForbiddenException.class);
- expectedException.expectMessage(String.format("You're not member of organization '%s'", organization.getKey()));
-
- newUserSession(notMember).checkMembership(organization);
- }
-
- @Test
- public void checkMembership_succeeds_when_user_is_member_of_organization() {
- OrganizationDto organization = db.organizations().insert();
- UserDto member = db.users().insertUser();
- db.organizations().addMember(organization, member);
-
- newUserSession(member).checkMembership(organization);
- }
-
- @Test
- public void checkMembership_succeeds_when_user_is_not_member_of_organization_but_root() {
- OrganizationDto organization = db.organizations().insert();
- UserDto root = db.users().makeRoot(db.users().insertUser());
-
- newUserSession(root).checkMembership(organization);
- }
-
- private ServerUserSession newUserSession(@Nullable UserDto userDto) {
- return new ServerUserSession(dbClient, organizationFlags, defaultOrganizationProvider, userDto);
- }
-
- private ServerUserSession newAnonymousSession() {
- return newUserSession(null);
- }
-
- private void expectInsufficientPrivilegesForbiddenException() {
- expectedException.expect(ForbiddenException.class);
- expectedException.expectMessage("Insufficient privileges");
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/SystemPasscodeImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/SystemPasscodeImplTest.java
deleted file mode 100644
index 352070eacf3..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/SystemPasscodeImplTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.junit.After;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.server.ws.TestRequest;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class SystemPasscodeImplTest {
-
- @Rule
- public LogTester logTester = new LogTester();
-
- private MapSettings settings = new MapSettings();
- private SystemPasscodeImpl underTest = new SystemPasscodeImpl(settings.asConfig());
-
- @After
- public void tearDown() {
- underTest.stop();
- }
-
- @Test
- public void startup_logs_show_that_feature_is_enabled() {
- configurePasscode("foo");
- underTest.start();
-
- assertThat(logTester.logs(LoggerLevel.INFO)).contains("System authentication by passcode is enabled");
- }
-
- @Test
- public void startup_logs_show_that_feature_is_disabled() {
- underTest.start();
-
- assertThat(logTester.logs(LoggerLevel.INFO)).contains("System authentication by passcode is disabled");
- }
-
- @Test
- public void passcode_is_disabled_if_blank_configuration() {
- configurePasscode("");
- underTest.start();
-
- assertThat(logTester.logs(LoggerLevel.INFO)).contains("System authentication by passcode is disabled");
- }
-
- @Test
- public void isValid_is_true_if_request_header_matches_configured_passcode() {
- verifyIsValid(true, "foo", "foo");
- }
-
- @Test
- public void isValid_is_false_if_request_header_matches_configured_passcode_with_different_case() {
- verifyIsValid(false, "foo", "FOO");
- }
-
- @Test
- public void isValid_is_false_if_request_header_does_not_match_configured_passcode() {
- verifyIsValid(false, "foo", "bar");
- }
-
- @Test
- public void isValid_is_false_if_request_header_is_defined_but_passcode_is_not_configured() {
- verifyIsValid(false, null, "foo");
- }
-
- @Test
- public void isValid_is_false_if_request_header_is_empty() {
- verifyIsValid(false, "foo", "");
- }
-
- private void verifyIsValid(boolean expectedResult, String configuredPasscode, String header) {
- configurePasscode(configuredPasscode);
-
- TestRequest request = new TestRequest();
- request.setHeader("X-Sonar-Passcode", header);
-
- assertThat(underTest.isValid(request)).isEqualTo(expectedResult);
- }
-
- private void configurePasscode(String propertyValue) {
- settings.setProperty("sonar.web.systemPasscode", propertyValue);
- underTest.start();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/TestUserSessionFactory.java b/server/sonar-server/src/test/java/org/sonar/server/user/TestUserSessionFactory.java
deleted file mode 100644
index 2dfa06ab569..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/TestUserSessionFactory.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import java.util.Collection;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * Simple implementation of {@link UserSessionFactory}. It creates
- * instances of {@link UserSession} that don't manage groups nor
- * permissions. Only basic user information like {@link UserSession#isLoggedIn()}
- * and {@link UserSession#getLogin()} are available. The methods
- * relying on groups or permissions throw {@link UnsupportedOperationException}.
- */
-public class TestUserSessionFactory implements UserSessionFactory {
-
- private TestUserSessionFactory() {
- }
-
- @Override
- public UserSession create(UserDto user) {
- return new TestUserSession(requireNonNull(user));
- }
-
- @Override
- public UserSession createAnonymous() {
- return new TestUserSession(null);
- }
-
- public static TestUserSessionFactory standalone() {
- return new TestUserSessionFactory();
- }
-
- private static class TestUserSession extends AbstractUserSession {
- private final UserDto user;
-
- public TestUserSession(@Nullable UserDto user) {
- this.user = user;
- }
-
- @Override
- public String getLogin() {
- return user != null ? user.getLogin() : null;
- }
-
- @Override
- public String getUuid() {
- return user != null ? user.getUuid() : null;
- }
-
- @Override
- public String getName() {
- return user != null ? user.getName() : null;
- }
-
- @Override
- public Integer getUserId() {
- return user != null ? user.getId() : null;
- }
-
- @Override
- public Collection<GroupDto> getGroups() {
- throw notImplemented();
- }
-
- @Override
- public Optional<IdentityProvider> getIdentityProvider() {
- throw notImplemented();
- }
-
- @Override
- public Optional<ExternalIdentity> getExternalIdentity() {
- throw notImplemented();
- }
-
- @Override
- public boolean isLoggedIn() {
- return user != null;
- }
-
- @Override
- public boolean isRoot() {
- throw notImplemented();
- }
-
- @Override
- protected boolean hasPermissionImpl(OrganizationPermission permission, String organizationUuid) {
- throw notImplemented();
- }
-
- @Override
- protected Optional<String> componentUuidToProjectUuid(String componentUuid) {
- throw notImplemented();
- }
-
- @Override
- protected boolean hasProjectUuidPermission(String permission, String projectUuid) {
- throw notImplemented();
- }
-
- @Override
- public boolean isSystemAdministrator() {
- throw notImplemented();
- }
-
- @Override
- public boolean hasMembershipImpl(OrganizationDto organizationDto) {
- throw notImplemented();
- }
-
- private static RuntimeException notImplemented() {
- return new UnsupportedOperationException("not implemented");
- }
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ThreadLocalUserSessionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ThreadLocalUserSessionTest.java
deleted file mode 100644
index ec5face1ba2..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/ThreadLocalUserSessionTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.GroupTesting;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.tester.AnonymousMockUserSession;
-import org.sonar.server.tester.MockUserSession;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ThreadLocalUserSessionTest {
-
- private ThreadLocalUserSession threadLocalUserSession = new ThreadLocalUserSession();
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- @Before
- public void setUp() {
- // for test isolation
- threadLocalUserSession.unload();
- }
-
- @After
- public void tearDown() {
- // clean up for next test
- threadLocalUserSession.unload();
- }
-
- @Test
- public void get_session_for_user() {
- GroupDto group = GroupTesting.newGroupDto();
- MockUserSession expected = new MockUserSession("karadoc")
- .setUuid("karadoc-uuid")
- .setUserId(123)
- .setGroups(group);
- threadLocalUserSession.set(expected);
-
- UserSession session = threadLocalUserSession.get();
- assertThat(session).isSameAs(expected);
- assertThat(threadLocalUserSession.getUserId()).isEqualTo(123);
- assertThat(threadLocalUserSession.getLogin()).isEqualTo("karadoc");
- assertThat(threadLocalUserSession.getUuid()).isEqualTo("karadoc-uuid");
- assertThat(threadLocalUserSession.isLoggedIn()).isTrue();
- assertThat(threadLocalUserSession.getGroups()).extracting(GroupDto::getId).containsOnly(group.getId());
- }
-
- @Test
- public void get_session_for_anonymous() {
- AnonymousMockUserSession expected = new AnonymousMockUserSession();
- threadLocalUserSession.set(expected);
-
- UserSession session = threadLocalUserSession.get();
- assertThat(session).isSameAs(expected);
- assertThat(threadLocalUserSession.getLogin()).isNull();
- assertThat(threadLocalUserSession.getUserId()).isNull();
- assertThat(threadLocalUserSession.isLoggedIn()).isFalse();
- assertThat(threadLocalUserSession.getGroups()).isEmpty();
- }
-
- @Test
- public void throw_UnauthorizedException_when_no_session() {
- thrown.expect(UnauthorizedException.class);
- threadLocalUserSession.get();
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java
deleted file mode 100644
index cfe9b2ac435..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java
+++ /dev/null
@@ -1,665 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Multimap;
-import java.util.List;
-import org.elasticsearch.search.SearchHit;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
-import org.sonar.api.platform.NewUserHandler;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserPropertyDto;
-import org.sonar.server.authentication.CredentialsLocalAuthentication;
-import org.sonar.server.authentication.CredentialsLocalAuthentication.HashMethod;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.organization.TestDefaultOrganizationProvider;
-import org.sonar.server.organization.TestOrganizationFlags;
-import org.sonar.server.user.index.UserIndexDefinition;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.data.MapEntry.entry;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.sonar.db.user.UserTesting.newLocalUser;
-import static org.sonar.process.ProcessProperties.Property.ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS;
-import static org.sonar.server.user.ExternalIdentity.SQ_AUTHORITY;
-
-public class UserUpdaterCreateTest {
-
- private static final String DEFAULT_LOGIN = "marius";
-
- private System2 system2 = new AlwaysIncreasingSystem2();
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Rule
- public EsTester es = EsTester.create();
-
- @Rule
- public DbTester db = DbTester.create(system2);
-
- private DbClient dbClient = db.getDbClient();
- private NewUserNotifier newUserNotifier = mock(NewUserNotifier.class);
- private ArgumentCaptor<NewUserHandler.Context> newUserHandler = ArgumentCaptor.forClass(NewUserHandler.Context.class);
- private DbSession session = db.getSession();
- private UserIndexer userIndexer = new UserIndexer(dbClient, es.client());
- private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
- private MapSettings settings = new MapSettings();
- private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient());
-
- private UserUpdater underTest = new UserUpdater(system2, newUserNotifier, dbClient, userIndexer, organizationFlags, defaultOrganizationProvider,
- new DefaultGroupFinder(dbClient), settings.asConfig(), localAuthentication);
-
- @Test
- public void create_user() {
- createDefaultGroup();
-
- UserDto dto = underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setEmail("user@mail.com")
- .setPassword("PASSWORD")
- .setScmAccounts(ImmutableList.of("u1", "u_1", "User 1"))
- .build(), u -> {
- });
-
- assertThat(dto.getId()).isNotNull();
- assertThat(dto.getLogin()).isEqualTo("user");
- assertThat(dto.getName()).isEqualTo("User");
- assertThat(dto.getEmail()).isEqualTo("user@mail.com");
- assertThat(dto.getScmAccountsAsList()).containsOnly("u1", "u_1", "User 1");
- assertThat(dto.isActive()).isTrue();
- assertThat(dto.isLocal()).isTrue();
-
- assertThat(dto.getSalt()).isNull();
- assertThat(dto.getHashMethod()).isEqualTo(HashMethod.BCRYPT.name());
- assertThat(dto.getCryptedPassword()).isNotNull();
- assertThat(dto.getCreatedAt())
- .isPositive()
- .isEqualTo(dto.getUpdatedAt());
-
- assertThat(dbClient.userDao().selectByLogin(session, "user").getId()).isEqualTo(dto.getId());
- List<SearchHit> indexUsers = es.getDocuments(UserIndexDefinition.TYPE_USER);
- assertThat(indexUsers).hasSize(1);
- assertThat(indexUsers.get(0).getSourceAsMap())
- .contains(
- entry("login", "user"),
- entry("name", "User"),
- entry("email", "user@mail.com"));
- }
-
- @Test
- public void create_user_with_minimum_fields() {
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("us")
- .setName("User")
- .build(), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, "us");
- assertThat(dto.getId()).isNotNull();
- assertThat(dto.getLogin()).isEqualTo("us");
- assertThat(dto.getName()).isEqualTo("User");
- assertThat(dto.getEmail()).isNull();
- assertThat(dto.getScmAccounts()).isNull();
- assertThat(dto.isActive()).isTrue();
- }
-
- @Test
- public void create_user_generates_unique_login_no_login_provided() {
- createDefaultGroup();
-
- UserDto user = underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setName("John Doe")
- .build(), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, user.getLogin());
- assertThat(dto.getLogin()).startsWith("john-doe");
- assertThat(dto.getName()).isEqualTo("John Doe");
- }
-
- @Test
- public void create_user_generates_unique_login_when_login_is_empty() {
- createDefaultGroup();
-
- UserDto user = underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("")
- .setName("John Doe")
- .build(), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, user.getLogin());
- assertThat(dto.getLogin()).startsWith("john-doe");
- assertThat(dto.getName()).isEqualTo("John Doe");
- }
-
- @Test
- public void create_user_with_sq_authority_when_no_authority_set() {
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setPassword("password")
- .build(), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, "user");
- assertThat(dto.getExternalLogin()).isEqualTo("user");
- assertThat(dto.getExternalIdentityProvider()).isEqualTo("sonarqube");
- assertThat(dto.isLocal()).isTrue();
- }
-
- @Test
- public void create_user_with_identity_provider() {
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setExternalIdentity(new ExternalIdentity("github", "github-user", "ABCD"))
- .build(), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, "user");
- assertThat(dto.isLocal()).isFalse();
- assertThat(dto.getExternalId()).isEqualTo("ABCD");
- assertThat(dto.getExternalLogin()).isEqualTo("github-user");
- assertThat(dto.getExternalIdentityProvider()).isEqualTo("github");
- assertThat(dto.getCryptedPassword()).isNull();
- assertThat(dto.getSalt()).isNull();
- }
-
- @Test
- public void create_user_with_sonarqube_external_identity() {
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setExternalIdentity(new ExternalIdentity(SQ_AUTHORITY, "user", "user"))
- .build(), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, "user");
- assertThat(dto.isLocal()).isFalse();
- assertThat(dto.getExternalId()).isEqualTo("user");
- assertThat(dto.getExternalLogin()).isEqualTo("user");
- assertThat(dto.getExternalIdentityProvider()).isEqualTo("sonarqube");
- assertThat(dto.getCryptedPassword()).isNull();
- assertThat(dto.getSalt()).isNull();
- }
-
- @Test
- public void create_user_with_scm_accounts_containing_blank_or_null_entries() {
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setPassword("password")
- .setScmAccounts(asList("u1", "", null))
- .build(), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, "user").getScmAccountsAsList()).containsOnly("u1");
- }
-
- @Test
- public void create_user_with_scm_accounts_containing_one_blank_entry() {
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setPassword("password")
- .setScmAccounts(asList(""))
- .build(), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, "user").getScmAccounts()).isNull();
- }
-
- @Test
- public void create_user_with_scm_accounts_containing_duplications() {
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setPassword("password")
- .setScmAccounts(asList("u1", "u1"))
- .build(), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, "user").getScmAccountsAsList()).containsOnly("u1");
- }
-
- @Test
- public void create_not_onboarded_user_if_onboarding_setting_is_set_to_false() {
- settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey(), false);
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .build(), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, "user").isOnboarded()).isTrue();
- }
-
- @Test
- public void create_onboarded_user_if_onboarding_setting_is_set_to_true() {
- settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey(), true);
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .build(), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, "user").isOnboarded()).isFalse();
- }
-
- @Test
- public void set_notifications_readDate_setting_when_creating_user_and_organization_enabled() {
- long now = system2.now();
- organizationFlags.setEnabled(true);
- createDefaultGroup();
-
- UserDto user = underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("userLogin")
- .setName("UserName")
- .build(), u -> {
- });
-
- UserPropertyDto notificationReadDateSetting = dbClient.userPropertiesDao().selectByUser(session, user).get(0);
- assertThat(notificationReadDateSetting.getKey()).isEqualTo("notifications.readDate");
- assertThat(Long.parseLong(notificationReadDateSetting.getValue())).isGreaterThanOrEqualTo(now);
- }
-
- @Test
- public void does_not_set_notifications_readDate_setting_when_creating_user_when_not_on_and_organization_disabled() {
- createDefaultGroup();
-
- UserDto user = underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("userLogin")
- .setName("UserName")
- .build(), u -> {
- });
-
- assertThat(dbClient.userPropertiesDao().selectByUser(session, user)).isEmpty();
- }
-
- @Test
- public void create_user_and_index_other_user() {
- createDefaultGroup();
- UserDto otherUser = db.users().insertUser();
-
- UserDto created = underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setEmail("user@mail.com")
- .setPassword("PASSWORD")
- .build(), u -> {
- }, otherUser);
-
- assertThat(es.getIds(UserIndexDefinition.TYPE_USER)).containsExactlyInAnyOrder(created.getUuid(), otherUser.getUuid());
- }
-
- @Test
- public void fail_to_create_user_with_invalid_login() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Use only letters, numbers, and .-_@ please.");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("/marius/")
- .setName("Marius")
- .setEmail("marius@mail.com")
- .setPassword("password")
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_with_space_in_login() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Use only letters, numbers, and .-_@ please.");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("mari us")
- .setName("Marius")
- .setEmail("marius@mail.com")
- .setPassword("password")
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_with_too_short_login() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Login is too short (minimum is 2 characters)");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("m")
- .setName("Marius")
- .setEmail("marius@mail.com")
- .setPassword("password")
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_with_too_long_login() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Login is too long (maximum is 255 characters)");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(Strings.repeat("m", 256))
- .setName("Marius")
- .setEmail("marius@mail.com")
- .setPassword("password")
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_with_missing_name() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Name can't be empty");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName(null)
- .setEmail("marius@mail.com")
- .setPassword("password")
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_with_too_long_name() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Name is too long (maximum is 200 characters)");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName(Strings.repeat("m", 201))
- .setEmail("marius@mail.com")
- .setPassword("password")
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_with_too_long_email() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Email is too long (maximum is 100 characters)");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius")
- .setEmail(Strings.repeat("m", 101))
- .setPassword("password")
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_with_many_errors() {
- try {
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("")
- .setName("")
- .setEmail("marius@mail.com")
- .setPassword("")
- .build(), u -> {
- });
- fail();
- } catch (BadRequestException e) {
- assertThat(e.errors()).containsExactlyInAnyOrder("Name can't be empty", "Password can't be empty");
- }
- }
-
- @Test
- public void fail_to_create_user_when_scm_account_is_already_used() {
- db.users().insertUser(newLocalUser("john", "John", null).setScmAccounts(singletonList("jo")));
-
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("The scm account 'jo' is already used by user(s) : 'John (john)'");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius")
- .setEmail("marius@mail.com")
- .setPassword("password")
- .setScmAccounts(asList("jo"))
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_when_scm_account_is_already_used_by_many_users() {
- db.users().insertUser(newLocalUser("john", "John", null).setScmAccounts(singletonList("john@email.com")));
- db.users().insertUser(newLocalUser("technical-account", "Technical account", null).setScmAccounts(singletonList("john@email.com")));
-
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("The scm account 'john@email.com' is already used by user(s) : 'John (john), Technical account (technical-account)'");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius")
- .setEmail("marius@mail.com")
- .setPassword("password")
- .setScmAccounts(asList("john@email.com"))
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_when_scm_account_is_user_login() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .setScmAccounts(asList(DEFAULT_LOGIN))
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_when_scm_account_is_user_email() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .setScmAccounts(asList("marius2@mail.com"))
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_when_login_already_exists() {
- createDefaultGroup();
- UserDto existingUser = db.users().insertUser(u -> u.setLogin("existing_login"));
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("A user with login 'existing_login' already exists");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(existingUser.getLogin())
- .setName("User")
- .setPassword("PASSWORD")
- .build(), u -> {
- });
- }
-
- @Test
- public void fail_to_create_user_when_external_id_and_external_provider_already_exists() {
- createDefaultGroup();
- UserDto existingUser = db.users().insertUser(u -> u.setExternalId("existing_external_id").setExternalIdentityProvider("existing_external_provider"));
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("A user with provider id 'existing_external_id' and identity provider 'existing_external_provider' already exists");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("new_login")
- .setName("User")
- .setExternalIdentity(new ExternalIdentity(existingUser.getExternalIdentityProvider(), existingUser.getExternalLogin(), existingUser.getExternalId()))
- .build(), u -> {
- });
- }
-
- @Test
- public void notify_new_user() {
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setEmail("user@mail.com")
- .setPassword("password")
- .setScmAccounts(asList("u1", "u_1"))
- .build(), u -> {
- });
-
- verify(newUserNotifier).onNewUser(newUserHandler.capture());
- assertThat(newUserHandler.getValue().getLogin()).isEqualTo("user");
- assertThat(newUserHandler.getValue().getName()).isEqualTo("User");
- assertThat(newUserHandler.getValue().getEmail()).isEqualTo("user@mail.com");
- }
-
- @Test
- public void associate_default_group_when_creating_user_and_organizations_are_disabled() {
- GroupDto defaultGroup = createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setEmail("user@mail.com")
- .setPassword("password")
- .build(), u -> {
- });
-
- Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList("user"));
- assertThat(groups.get("user")).containsOnly(defaultGroup.getName());
- }
-
- @Test
- public void does_not_associate_default_group_when_creating_user_and_organizations_are_enabled() {
- organizationFlags.setEnabled(true);
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setEmail("user@mail.com")
- .setPassword("password")
- .build(), u -> {
- });
-
- Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList("user"));
- assertThat(groups.get("user")).isEmpty();
- }
-
- @Test
- public void fail_to_associate_default_group_when_default_group_does_not_exist() {
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Default group cannot be found");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setEmail("user@mail.com")
- .setPassword("password")
- .setScmAccounts(asList("u1", "u_1"))
- .build(), u -> {
- });
- }
-
- @Test
- public void add_user_as_member_of_default_organization_when_creating_user_and_organizations_are_disabled() {
- createDefaultGroup();
-
- UserDto dto = underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setEmail("user@mail.com")
- .setPassword("PASSWORD")
- .build(), u -> {
- });
-
- assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isPresent();
- }
-
- @Test
- public void does_not_add_user_as_member_of_default_organization_when_creating_user_and_organizations_are_enabled() {
- organizationFlags.setEnabled(true);
- createDefaultGroup();
-
- UserDto dto = underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin("user")
- .setName("User")
- .setEmail("user@mail.com")
- .setPassword("PASSWORD")
- .build(), u -> {
- });
-
- assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isNotPresent();
- }
-
- private GroupDto createDefaultGroup() {
- return db.users().insertDefaultGroup(db.getDefaultOrganization());
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java
deleted file mode 100644
index d280c1af117..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import com.google.common.collect.Multimap;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.GroupTesting;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserPropertyDto;
-import org.sonar.server.authentication.CredentialsLocalAuthentication;
-import org.sonar.server.authentication.CredentialsLocalAuthentication.HashMethod;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.organization.TestDefaultOrganizationProvider;
-import org.sonar.server.organization.TestOrganizationFlags;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static java.lang.String.format;
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.sonar.process.ProcessProperties.Property.ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS;
-
-public class UserUpdaterReactivateTest {
-
- private System2 system2 = new AlwaysIncreasingSystem2();
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Rule
- public EsTester es = EsTester.create();
-
- @Rule
- public DbTester db = DbTester.create(system2);
-
- private DbClient dbClient = db.getDbClient();
- private NewUserNotifier newUserNotifier = mock(NewUserNotifier.class);
- private DbSession session = db.getSession();
- private UserIndexer userIndexer = new UserIndexer(dbClient, es.client());
- private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
- private MapSettings settings = new MapSettings();
- private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient());
- private UserUpdater underTest = new UserUpdater(system2, newUserNotifier, dbClient, userIndexer, organizationFlags, defaultOrganizationProvider,
- new DefaultGroupFinder(dbClient), settings.asConfig(), localAuthentication);;
-
- @Test
- public void reactivate_user() {
- UserDto user = db.users().insertUser(u -> u.setActive(false));
- createDefaultGroup();
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin("marius")
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .build(),
- u -> {
- });
-
- UserDto reloaded = dbClient.userDao().selectByUuid(session, user.getUuid());
- assertThat(reloaded.isActive()).isTrue();
- assertThat(reloaded.getLogin()).isEqualTo("marius");
- assertThat(reloaded.getName()).isEqualTo("Marius2");
- assertThat(reloaded.getEmail()).isEqualTo("marius2@mail.com");
- assertThat(reloaded.getScmAccounts()).isNull();
- assertThat(reloaded.isLocal()).isTrue();
- assertThat(reloaded.getSalt()).isNull();
- assertThat(reloaded.getHashMethod()).isEqualTo(HashMethod.BCRYPT.name());
- assertThat(reloaded.getCryptedPassword()).isNotNull().isNotEqualTo("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg");
- assertThat(reloaded.getCreatedAt()).isEqualTo(user.getCreatedAt());
- assertThat(reloaded.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
- }
-
- @Test
- public void reactivate_user_without_providing_login() {
- UserDto user = db.users().insertUser(u -> u.setActive(false));
- createDefaultGroup();
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .build(),
- u -> {
- });
-
- UserDto reloaded = dbClient.userDao().selectByUuid(session, user.getUuid());
- assertThat(reloaded.isActive()).isTrue();
- assertThat(reloaded.getLogin()).isEqualTo(user.getLogin());
- }
-
- @Test
- public void reactivate_user_not_having_password() {
- UserDto user = db.users().insertDisabledUser(u -> u.setSalt(null).setCryptedPassword(null));
- createDefaultGroup();
-
- UserDto dto = underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(user.getLogin())
- .setName(user.getName())
- .build(),
- u -> {
- });
-
- assertThat(dto.isActive()).isTrue();
- assertThat(dto.getName()).isEqualTo(user.getName());
- assertThat(dto.getScmAccounts()).isNull();
- assertThat(dto.getSalt()).isNull();
- assertThat(dto.getCryptedPassword()).isNull();
- assertThat(dto.getCreatedAt()).isEqualTo(user.getCreatedAt());
- assertThat(dto.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
- }
-
- @Test
- public void reactivate_user_with_external_provider() {
- UserDto user = db.users().insertDisabledUser(u -> u.setLocal(true));
- createDefaultGroup();
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(user.getLogin())
- .setName(user.getName())
- .setExternalIdentity(new ExternalIdentity("github", "john", "ABCD"))
- .build(), u -> {
- });
- session.commit();
-
- UserDto dto = dbClient.userDao().selectByUuid(session, user.getUuid());
- assertThat(dto.isLocal()).isFalse();
- assertThat(dto.getExternalId()).isEqualTo("ABCD");
- assertThat(dto.getExternalLogin()).isEqualTo("john");
- assertThat(dto.getExternalIdentityProvider()).isEqualTo("github");
- }
-
- @Test
- public void reactivate_user_using_same_external_info_but_was_local() {
- UserDto user = db.users().insertDisabledUser(u -> u.setLocal(true)
- .setExternalId("ABCD")
- .setExternalLogin("john")
- .setExternalIdentityProvider("github"));
- createDefaultGroup();
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(user.getLogin())
- .setName(user.getName())
- .setExternalIdentity(new ExternalIdentity("github", "john", "ABCD"))
- .build(), u -> {
- });
- session.commit();
-
- UserDto dto = dbClient.userDao().selectByUuid(session, user.getUuid());
- assertThat(dto.isLocal()).isFalse();
- assertThat(dto.getExternalId()).isEqualTo("ABCD");
- assertThat(dto.getExternalLogin()).isEqualTo("john");
- assertThat(dto.getExternalIdentityProvider()).isEqualTo("github");
- }
-
- @Test
- public void reactivate_user_with_local_provider() {
- UserDto user = db.users().insertDisabledUser(u -> u.setLocal(false)
- .setExternalId("ABCD")
- .setExternalLogin("john")
- .setExternalIdentityProvider("github"));
- createDefaultGroup();
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(user.getLogin())
- .setName(user.getName())
- .build(), u -> {
- });
- session.commit();
-
- UserDto dto = dbClient.userDao().selectByUuid(session, user.getUuid());
- assertThat(dto.isLocal()).isTrue();
- assertThat(dto.getExternalId()).isEqualTo(user.getLogin());
- assertThat(dto.getExternalLogin()).isEqualTo(user.getLogin());
- assertThat(dto.getExternalIdentityProvider()).isEqualTo("sonarqube");
- }
-
- @Test
- public void fail_to_reactivate_user_if_active() {
- UserDto user = db.users().insertUser();
- createDefaultGroup();
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage(format("An active user with login '%s' already exists", user.getLogin()));
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(user.getLogin())
- .setName(user.getName())
- .build(), u -> {
- });
- }
-
- @Test
- public void associate_default_groups_when_reactivating_user_and_organizations_are_disabled() {
- UserDto userDto = db.users().insertDisabledUser();
- db.organizations().insertForUuid("org1");
- GroupDto groupDto = db.users().insertGroup(GroupTesting.newGroupDto().setName("sonar-devs").setOrganizationUuid("org1"));
- db.users().insertMember(groupDto, userDto);
- GroupDto defaultGroup = createDefaultGroup();
-
- underTest.reactivateAndCommit(db.getSession(), userDto, NewUser.builder()
- .setLogin(userDto.getLogin())
- .setName(userDto.getName())
- .build(), u -> {
- });
- session.commit();
-
- Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, singletonList(userDto.getLogin()));
- assertThat(groups.get(userDto.getLogin()).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).isTrue();
- }
-
- @Test
- public void does_not_associate_default_groups_when_reactivating_user_and_organizations_are_enabled() {
- organizationFlags.setEnabled(true);
- UserDto userDto = db.users().insertDisabledUser();
- db.organizations().insertForUuid("org1");
- GroupDto groupDto = db.users().insertGroup(GroupTesting.newGroupDto().setName("sonar-devs").setOrganizationUuid("org1"));
- db.users().insertMember(groupDto, userDto);
- GroupDto defaultGroup = createDefaultGroup();
-
- underTest.reactivateAndCommit(db.getSession(), userDto, NewUser.builder()
- .setLogin(userDto.getLogin())
- .setName(userDto.getName())
- .build(), u -> {
- });
- session.commit();
-
- Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, singletonList(userDto.getLogin()));
- assertThat(groups.get(userDto.getLogin()).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).isFalse();
- }
-
- @Test
- public void add_user_as_member_of_default_organization_when_reactivating_user_and_organizations_are_disabled() {
- UserDto user = db.users().insertDisabledUser();
- createDefaultGroup();
-
- UserDto dto = underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder().setLogin(user.getLogin()).setName(user.getName()).build(), u -> {
- });
-
- assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isPresent();
- }
-
- @Test
- public void does_not_add_user_as_member_of_default_organization_when_reactivating_user_and_organizations_are_enabled() {
- organizationFlags.setEnabled(true);
- UserDto user = db.users().insertDisabledUser();
- createDefaultGroup();
-
- UserDto dto = underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder().setLogin(user.getLogin()).setName(user.getName()).build(), u -> {
- });
-
- assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isNotPresent();
- }
-
- @Test
- public void reactivate_not_onboarded_user_if_onboarding_setting_is_set_to_false() {
- settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey(), false);
- UserDto user = db.users().insertDisabledUser(u -> u.setOnboarded(false));
- createDefaultGroup();
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(user.getLogin())
- .setName(user.getName())
- .build(), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, user.getLogin()).isOnboarded()).isTrue();
- }
-
- @Test
- public void reactivate_onboarded_user_if_onboarding_setting_is_set_to_true() {
- settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey(), true);
- UserDto user = db.users().insertDisabledUser(u -> u.setOnboarded(true));
- createDefaultGroup();
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(user.getLogin())
- .setName(user.getName())
- .build(), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, user.getLogin()).isOnboarded()).isFalse();
- }
-
- @Test
- public void set_notifications_readDate_setting_when_reactivating_user_on_sonar_cloud() {
- long now = system2.now();
- organizationFlags.setEnabled(true);
- createDefaultGroup();
- UserDto user = db.users().insertDisabledUser();
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(user.getLogin())
- .setName(user.getName())
- .build(), u -> {
- });
-
- UserPropertyDto notificationReadDateSetting = dbClient.userPropertiesDao().selectByUser(session, user).get(0);
- assertThat(notificationReadDateSetting.getKey()).isEqualTo("notifications.readDate");
- assertThat(Long.parseLong(notificationReadDateSetting.getValue())).isGreaterThanOrEqualTo(now);
- }
-
- @Test
- public void does_not_set_notifications_readDate_setting_when_reactivating_user_when_not_on_sonar_cloud() {
- createDefaultGroup();
- UserDto user = db.users().insertDisabledUser();
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(user.getLogin())
- .setName(user.getName())
- .build(), u -> {
- });
-
- assertThat(dbClient.userPropertiesDao().selectByUser(session, user)).isEmpty();
- }
-
- @Test
- public void fail_to_reactivate_user_when_login_already_exists() {
- createDefaultGroup();
- UserDto user = db.users().insertUser(u -> u.setActive(false));
- UserDto existingUser = db.users().insertUser(u -> u.setLogin("existing_login"));
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("A user with login 'existing_login' already exists");
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(existingUser.getLogin())
- .setName("Marius2")
- .setPassword("password2")
- .build(),
- u -> {
- });
- }
-
- @Test
- public void fail_to_reactivate_user_when_external_id_and_external_provider_already_exists() {
- createDefaultGroup();
- UserDto user = db.users().insertUser(u -> u.setActive(false));
- UserDto existingUser = db.users().insertUser(u -> u.setExternalId("existing_external_id").setExternalIdentityProvider("existing_external_provider"));
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("A user with provider id 'existing_external_id' and identity provider 'existing_external_provider' already exists");
-
- underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
- .setLogin(user.getLogin())
- .setName("Marius2")
- .setExternalIdentity(new ExternalIdentity(existingUser.getExternalIdentityProvider(), existingUser.getExternalLogin(), existingUser.getExternalId()))
- .build(),
- u -> {
- });
- }
-
- private GroupDto createDefaultGroup() {
- return db.users().insertDefaultGroup(db.getDefaultOrganization());
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterUpdateTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterUpdateTest.java
deleted file mode 100644
index 6e742c79a0b..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterUpdateTest.java
+++ /dev/null
@@ -1,636 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user;
-
-import com.google.common.collect.Multimap;
-import java.util.List;
-import org.elasticsearch.search.SearchHit;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.property.PropertyDto;
-import org.sonar.db.property.PropertyQuery;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.authentication.CredentialsLocalAuthentication;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.organization.OrganizationUpdater;
-import org.sonar.server.organization.TestDefaultOrganizationProvider;
-import org.sonar.server.organization.TestOrganizationFlags;
-import org.sonar.server.user.index.UserIndexDefinition;
-import org.sonar.server.user.index.UserIndexer;
-import org.sonar.server.usergroups.DefaultGroupFinder;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.assertj.core.data.MapEntry.entry;
-import static org.mockito.Mockito.mock;
-import static org.sonar.api.CoreProperties.DEFAULT_ISSUE_ASSIGNEE;
-import static org.sonar.db.user.UserTesting.newExternalUser;
-import static org.sonar.db.user.UserTesting.newLocalUser;
-import static org.sonar.db.user.UserTesting.newUserDto;
-
-public class UserUpdaterUpdateTest {
-
- private static final String DEFAULT_LOGIN = "marius";
-
- private System2 system2 = new AlwaysIncreasingSystem2();
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Rule
- public EsTester es = EsTester.create();
-
- @Rule
- public DbTester db = DbTester.create(system2);
-
- private DbClient dbClient = db.getDbClient();
- private NewUserNotifier newUserNotifier = mock(NewUserNotifier.class);
- private DbSession session = db.getSession();
- private UserIndexer userIndexer = new UserIndexer(dbClient, es.client());
- private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
- private MapSettings settings = new MapSettings();
- private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient());
- private UserUpdater underTest = new UserUpdater(system2, newUserNotifier, dbClient, userIndexer, organizationFlags, defaultOrganizationProvider,
- new DefaultGroupFinder(dbClient), settings.asConfig(), localAuthentication);
-
- @Test
- public void update_user() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setScmAccounts(asList("ma", "marius33")));
- createDefaultGroup();
- userIndexer.indexOnStartup(null);
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setScmAccounts(singletonList("ma2")), u -> {
- });
-
- UserDto updatedUser = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(updatedUser.isActive()).isTrue();
- assertThat(updatedUser.getName()).isEqualTo("Marius2");
- assertThat(updatedUser.getEmail()).isEqualTo("marius2@mail.com");
- assertThat(updatedUser.getScmAccountsAsList()).containsOnly("ma2");
- assertThat(updatedUser.getCreatedAt()).isEqualTo(user.getCreatedAt());
- assertThat(updatedUser.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
-
- List<SearchHit> indexUsers = es.getDocuments(UserIndexDefinition.TYPE_USER);
- assertThat(indexUsers).hasSize(1);
- assertThat(indexUsers.get(0).getSourceAsMap())
- .contains(
- entry("login", DEFAULT_LOGIN),
- entry("name", "Marius2"),
- entry("email", "marius2@mail.com"));
- }
-
- @Test
- public void update_user_external_identity_when_user_was_not_local() {
- UserDto user = db.users().insertUser(newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName("Marius2")
- .setEmail("marius2@email.com")
- .setExternalIdentity(new ExternalIdentity("github", "john", "ABCD")), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getExternalId()).isEqualTo("ABCD");
- assertThat(dto.getExternalLogin()).isEqualTo("john");
- assertThat(dto.getExternalIdentityProvider()).isEqualTo("github");
- assertThat(dto.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
- }
-
- @Test
- public void update_user_external_identity_when_user_was_local() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName("Marius2")
- .setEmail("marius2@email.com")
- .setExternalIdentity(new ExternalIdentity("github", "john", "ABCD")), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getExternalId()).isEqualTo("ABCD");
- assertThat(dto.getExternalLogin()).isEqualTo("john");
- assertThat(dto.getExternalIdentityProvider()).isEqualTo("github");
- // Password must be removed
- assertThat(dto.getCryptedPassword()).isNull();
- assertThat(dto.getSalt()).isNull();
- assertThat(dto.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
- }
-
- @Test
- public void update_user_with_scm_accounts_containing_blank_entry() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
- .setScmAccounts(asList("ma", "marius33")));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .setScmAccounts(asList("ma2", "", null)), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getScmAccountsAsList()).containsOnly("ma2");
- }
-
- @Test
- public void update_only_login_of_local_account() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setLogin("new_login"), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN)).isNull();
- UserDto userReloaded = dbClient.userDao().selectByUuid(session, user.getUuid());
- assertThat(userReloaded.getLogin()).isEqualTo("new_login");
- assertThat(userReloaded.getExternalIdentityProvider()).isEqualTo("sonarqube");
- assertThat(userReloaded.getExternalLogin()).isEqualTo("new_login");
- assertThat(userReloaded.getExternalId()).isEqualTo("new_login");
- // Following fields has not changed
- assertThat(userReloaded.isLocal()).isTrue();
- assertThat(userReloaded.getName()).isEqualTo(user.getName());
- assertThat(userReloaded.getEmail()).isEqualTo(user.getEmail());
- assertThat(userReloaded.getScmAccountsAsList()).containsAll(user.getScmAccountsAsList());
- assertThat(userReloaded.getSalt()).isEqualTo(user.getSalt());
- assertThat(userReloaded.getCryptedPassword()).isEqualTo(user.getCryptedPassword());
- }
-
- @Test
- public void update_only_login_of_external_account() {
- UserDto user = db.users().insertUser(newExternalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setLogin("new_login"), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN)).isNull();
- UserDto userReloaded = dbClient.userDao().selectByUuid(session, user.getUuid());
- assertThat(userReloaded.getLogin()).isEqualTo("new_login");
- // Following fields has not changed
- assertThat(userReloaded.isLocal()).isFalse();
- assertThat(userReloaded.getExternalLogin()).isEqualTo(user.getExternalLogin());
- assertThat(userReloaded.getExternalId()).isEqualTo(user.getExternalId());
- assertThat(userReloaded.getName()).isEqualTo(user.getName());
- assertThat(userReloaded.getEmail()).isEqualTo(user.getEmail());
- assertThat(userReloaded.getScmAccountsAsList()).containsAll(user.getScmAccountsAsList());
- assertThat(userReloaded.getSalt()).isEqualTo(user.getSalt());
- assertThat(userReloaded.getCryptedPassword()).isEqualTo(user.getCryptedPassword());
- }
-
- @Test
- public void update_index_when_updating_user_login() {
- UserDto oldUser = db.users().insertUser();
- createDefaultGroup();
- userIndexer.indexOnStartup(null);
-
- underTest.updateAndCommit(session, oldUser, new UpdateUser()
- .setLogin("new_login"), u -> {
- });
-
- List<SearchHit> indexUsers = es.getDocuments(UserIndexDefinition.TYPE_USER);
- assertThat(indexUsers).hasSize(1);
- assertThat(indexUsers.get(0).getSourceAsMap())
- .contains(entry("login", "new_login"));
- }
-
- @Test
- public void update_default_assignee_when_updating_login() {
- createDefaultGroup();
- UserDto oldUser = db.users().insertUser();
- ComponentDto project1 = db.components().insertPrivateProject();
- ComponentDto project2 = db.components().insertPrivateProject();
- ComponentDto anotherProject = db.components().insertPrivateProject();
- db.properties().insertProperties(
- new PropertyDto().setKey(DEFAULT_ISSUE_ASSIGNEE).setValue(oldUser.getLogin()),
- new PropertyDto().setKey(DEFAULT_ISSUE_ASSIGNEE).setValue(oldUser.getLogin()).setResourceId(project1.getId()),
- new PropertyDto().setKey(DEFAULT_ISSUE_ASSIGNEE).setValue(oldUser.getLogin()).setResourceId(project2.getId()),
- new PropertyDto().setKey(DEFAULT_ISSUE_ASSIGNEE).setValue("another login").setResourceId(anotherProject.getId()));
- userIndexer.indexOnStartup(null);
-
- underTest.updateAndCommit(session, oldUser, new UpdateUser()
- .setLogin("new_login"), u -> {
- });
-
- assertThat(db.getDbClient().propertiesDao().selectByQuery(PropertyQuery.builder().setKey(DEFAULT_ISSUE_ASSIGNEE).build(), db.getSession()))
- .extracting(PropertyDto::getValue, PropertyDto::getResourceId)
- .containsOnly(
- tuple("new_login", null),
- tuple("new_login", project1.getId()),
- tuple("new_login", project2.getId()),
- tuple("another login", anotherProject.getId()));
- }
-
- @Test
- public void update_only_user_name() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
- .setScmAccounts(asList("ma", "marius33"))
- .setSalt("salt")
- .setCryptedPassword("crypted password"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName("Marius2"), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getName()).isEqualTo("Marius2");
-
- // Following fields has not changed
- assertThat(dto.getEmail()).isEqualTo("marius@lesbronzes.fr");
- assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33");
- assertThat(dto.getSalt()).isEqualTo("salt");
- assertThat(dto.getCryptedPassword()).isEqualTo("crypted password");
- }
-
- @Test
- public void update_only_user_email() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
- .setScmAccounts(asList("ma", "marius33"))
- .setSalt("salt")
- .setCryptedPassword("crypted password"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setEmail("marius2@mail.com"), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getEmail()).isEqualTo("marius2@mail.com");
-
- // Following fields has not changed
- assertThat(dto.getName()).isEqualTo("Marius");
- assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33");
- assertThat(dto.getSalt()).isEqualTo("salt");
- assertThat(dto.getCryptedPassword()).isEqualTo("crypted password");
- }
-
- @Test
- public void update_only_scm_accounts() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
- .setScmAccounts(asList("ma", "marius33"))
- .setSalt("salt")
- .setCryptedPassword("crypted password"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setScmAccounts(asList("ma2")), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getScmAccountsAsList()).containsOnly("ma2");
-
- // Following fields has not changed
- assertThat(dto.getName()).isEqualTo("Marius");
- assertThat(dto.getEmail()).isEqualTo("marius@lesbronzes.fr");
- assertThat(dto.getSalt()).isEqualTo("salt");
- assertThat(dto.getCryptedPassword()).isEqualTo("crypted password");
- }
-
- @Test
- public void update_scm_accounts_with_same_values() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
- .setScmAccounts(asList("ma", "marius33")));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setScmAccounts(asList("ma", "marius33")), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33");
- }
-
- @Test
- public void remove_scm_accounts() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
- .setScmAccounts(asList("ma", "marius33")));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setScmAccounts(null), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getScmAccounts()).isNull();
- }
-
- @Test
- public void update_only_user_password() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
- .setScmAccounts(asList("ma", "marius33"))
- .setSalt("salt")
- .setCryptedPassword("crypted password"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setPassword("password2"), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getSalt()).isNotEqualTo("salt");
- assertThat(dto.getCryptedPassword()).isNotEqualTo("crypted password");
-
- // Following fields has not changed
- assertThat(dto.getName()).isEqualTo("Marius");
- assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33");
- assertThat(dto.getEmail()).isEqualTo("marius@lesbronzes.fr");
- }
-
- @Test
- public void update_only_external_id() {
- UserDto user = db.users().insertUser(newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setExternalId("1234")
- .setExternalLogin("john.smith")
- .setExternalIdentityProvider("github"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser().setExternalIdentity(new ExternalIdentity("github", "john.smith", "ABCD")), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN))
- .extracting(UserDto::getExternalId)
- .isEqualTo("ABCD");
- }
-
- @Test
- public void update_only_external_login() {
- UserDto user = db.users().insertUser(newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setExternalId("ABCD")
- .setExternalLogin("john")
- .setExternalIdentityProvider("github"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser().setExternalIdentity(new ExternalIdentity("github", "john.smith", "ABCD")), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN))
- .extracting(UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
- .containsOnly("john.smith", "github");
- }
-
- @Test
- public void update_only_external_identity_provider() {
- UserDto user = db.users().insertUser(newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setExternalId("ABCD")
- .setExternalLogin("john")
- .setExternalIdentityProvider("github"));
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser().setExternalIdentity(new ExternalIdentity("bitbucket", "john", "ABCD")), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN))
- .extracting(UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
- .containsOnly("john", "bitbucket");
- }
-
- @Test
- public void does_not_update_user_when_no_change() {
- UserDto user = newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setScmAccounts(asList("ma1", "ma2"));
- db.users().insertUser(user);
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName(user.getName())
- .setEmail(user.getEmail())
- .setScmAccounts(user.getScmAccountsAsList())
- .setExternalIdentity(new ExternalIdentity(user.getExternalIdentityProvider(), user.getExternalLogin(), user.getExternalId())), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN).getUpdatedAt()).isEqualTo(user.getUpdatedAt());
- }
-
- @Test
- public void does_not_update_user_when_no_change_and_scm_account_reordered() {
- UserDto user = newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setScmAccounts(asList("ma1", "ma2"));
- db.users().insertUser(user);
- createDefaultGroup();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName(user.getName())
- .setEmail(user.getEmail())
- .setScmAccounts(asList("ma2", "ma1"))
- .setExternalIdentity(new ExternalIdentity(user.getExternalIdentityProvider(), user.getExternalLogin(), user.getExternalId())), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN).getUpdatedAt()).isEqualTo(user.getUpdatedAt());
- }
-
- @Test
- public void update_user_and_index_other_user() {
- createDefaultGroup();
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setScmAccounts(asList("ma", "marius33")));
- UserDto otherUser = db.users().insertUser();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .setScmAccounts(asList("ma2")), u -> {
- }, otherUser);
-
- assertThat(es.getIds(UserIndexDefinition.TYPE_USER)).containsExactlyInAnyOrder(user.getUuid(), otherUser.getUuid());
- }
-
- @Test
- public void fail_to_set_null_password_when_local_user() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
- createDefaultGroup();
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Password can't be empty");
-
- underTest.updateAndCommit(session, user, new UpdateUser().setPassword(null), u -> {
- });
- }
-
- @Test
- public void fail_to_update_password_when_user_is_not_local() {
- UserDto user = db.users().insertUser(newUserDto()
- .setLogin(DEFAULT_LOGIN)
- .setLocal(false));
- createDefaultGroup();
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Password cannot be changed when external authentication is used");
-
- underTest.updateAndCommit(session, user, new UpdateUser().setPassword("password2"), u -> {
- });
- }
-
- @Test
- public void not_associate_default_group_when_updating_user() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
- GroupDto defaultGroup = createDefaultGroup();
-
- // Existing user, he has no group, and should not be associated to the default one
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .setScmAccounts(asList("ma2")), u -> {
- });
-
- Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList(DEFAULT_LOGIN));
- assertThat(groups.get(DEFAULT_LOGIN).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).isFalse();
- }
-
- @Test
- public void not_associate_default_group_when_updating_user_if_already_existing() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
- GroupDto defaultGroup = createDefaultGroup();
- db.users().insertMember(defaultGroup, user);
-
- // User is already associate to the default group
- Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList(DEFAULT_LOGIN));
- assertThat(groups.get(DEFAULT_LOGIN).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).as("Current user groups : %s", groups.get(defaultGroup.getName())).isTrue();
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .setScmAccounts(asList("ma2")), u -> {
- });
-
- // Nothing as changed
- groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList(DEFAULT_LOGIN));
- assertThat(groups.get(DEFAULT_LOGIN).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).isTrue();
- }
-
- @Test
- public void fail_to_update_user_when_scm_account_is_already_used() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com").setScmAccounts(singletonList("ma")));
- db.users().insertUser(newLocalUser("john", "John", "john@email.com").setScmAccounts(singletonList("jo")));
- createDefaultGroup();
-
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("The scm account 'jo' is already used by user(s) : 'John (john)'");
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .setScmAccounts(asList("jo")), u -> {
- });
- }
-
- @Test
- public void fail_to_update_user_when_scm_account_is_user_login() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
- createDefaultGroup();
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
-
- underTest.updateAndCommit(session, user, new UpdateUser().setScmAccounts(asList(DEFAULT_LOGIN)), u -> {
- });
- }
-
- @Test
- public void fail_to_update_user_when_scm_account_is_existing_user_email() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
- createDefaultGroup();
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
-
- underTest.updateAndCommit(session, user, new UpdateUser().setScmAccounts(asList("marius@lesbronzes.fr")), u -> {
- });
- }
-
- @Test
- public void fail_to_update_user_when_scm_account_is_new_user_email() {
- UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
- createDefaultGroup();
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setEmail("marius@newmail.com")
- .setScmAccounts(asList("marius@newmail.com")), u -> {
- });
- }
-
- @Test
- public void fail_to_update_login_when_format_is_invalid() {
- UserDto user = db.users().insertUser();
- createDefaultGroup();
-
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Use only letters, numbers, and .-_@ please.");
-
- underTest.updateAndCommit(session, user, new UpdateUser().setLogin("With space"), u -> {
- });
- }
-
- @Test
- public void fail_to_update_user_when_login_already_exists() {
- createDefaultGroup();
- UserDto user = db.users().insertUser(u -> u.setActive(false));
- UserDto existingUser = db.users().insertUser(u -> u.setLogin("existing_login"));
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("A user with login 'existing_login' already exists");
-
- underTest.updateAndCommit(session, user, new UpdateUser().setLogin(existingUser.getLogin()), u -> {
- });
- }
-
- @Test
- public void fail_to_update_user_when_external_id_and_external_provider_already_exists() {
- createDefaultGroup();
- UserDto user = db.users().insertUser(u -> u.setActive(false));
- UserDto existingUser = db.users().insertUser(u -> u.setExternalId("existing_external_id").setExternalIdentityProvider("existing_external_provider"));
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("A user with provider id 'existing_external_id' and identity provider 'existing_external_provider' already exists");
-
- underTest.updateAndCommit(session, user, new UpdateUser()
- .setExternalIdentity(new ExternalIdentity(existingUser.getExternalIdentityProvider(), existingUser.getExternalLogin(), existingUser.getExternalId())), u -> {
- });
- }
-
- private GroupDto createDefaultGroup() {
- return db.users().insertDefaultGroup(db.getDefaultOrganization());
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/DefaultGroupCreatorImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/DefaultGroupCreatorImplTest.java
deleted file mode 100644
index 01150aec14d..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/DefaultGroupCreatorImplTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usergroups;
-
-import java.util.Optional;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.db.DbTester;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.template.PermissionTemplateDto;
-import org.sonar.db.user.GroupDto;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultGroupCreatorImplTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Rule
- public DbTester db = DbTester.create();
-
- private DefaultGroupCreator underTest = new DefaultGroupCreatorImpl(db.getDbClient());
-
- @Test
- public void create_default_group() {
- OrganizationDto organizationDto = db.organizations().insert();
-
- underTest.create(db.getSession(), organizationDto.getUuid());
-
- Optional<Integer> defaultGroupId = db.getDbClient().organizationDao().getDefaultGroupId(db.getSession(), organizationDto.getUuid());
- assertThat(defaultGroupId).isPresent();
- assertThat(db.getDbClient().groupDao().selectById(db.getSession(), defaultGroupId.get()))
- .extracting(GroupDto::getName, GroupDto::getDescription)
- .containsOnly("Members", "All members of the organization");
- }
-
- @Test
- public void fail_with_IAE_when_default_group_already_exist() {
- OrganizationDto organizationDto = db.organizations().insert();
- PermissionTemplateDto permissionTemplate = db.permissionTemplates().insertTemplate();
- db.organizations().setDefaultTemplates(organizationDto, permissionTemplate.getUuid(), null, null);
- db.users().insertGroup(organizationDto, "Members");
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage(String.format("The group '%s' already exist on organization '%s'", "Members", organizationDto.getUuid()));
-
- underTest.create(db.getSession(), organizationDto.getUuid());
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/DefaultGroupFinderTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/DefaultGroupFinderTest.java
deleted file mode 100644
index a894287b77c..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/DefaultGroupFinderTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usergroups;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.db.DbTester;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.user.GroupDto;
-
-import static java.lang.String.format;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultGroupFinderTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Rule
- public DbTester db = DbTester.create();
-
- private DefaultGroupFinder underTest = new DefaultGroupFinder(db.getDbClient());
-
- @Test
- public void find_default_group() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "default");
-
- GroupDto result = underTest.findDefaultGroup(db.getSession(), organization.getUuid());
-
- assertThat(result.getId()).isEqualTo(defaultGroup.getId());
- assertThat(result.getName()).isEqualTo("default");
- }
-
- @Test
- public void fail_with_ISE_when_no_default_group_on_org() {
- OrganizationDto organization = db.organizations().insert();
- db.users().insertGroup(organization);
-
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage(format("Default group cannot be found on organization '%s'", organization.getUuid()));
-
- underTest.findDefaultGroup(db.getSession(), organization.getUuid());
- }
-
- @Test
- public void fail_with_NPE_when_default_group_does_not_exist() {
- OrganizationDto organization = db.organizations().insert();
- GroupDto defaultGroup = db.users().insertDefaultGroup(organization, "default");
- db.getDbClient().groupDao().deleteById(db.getSession(), defaultGroup.getId());
-
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage(format("Group '%s' cannot be found", defaultGroup.getId()));
-
- underTest.findDefaultGroup(db.getSession(), organization.getUuid());
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/usertoken/TokenGeneratorImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/usertoken/TokenGeneratorImplTest.java
deleted file mode 100644
index d5222a9e55c..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/usertoken/TokenGeneratorImplTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usertoken;
-
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class TokenGeneratorImplTest {
- TokenGeneratorImpl underTest = new TokenGeneratorImpl();
-
- @Test
- public void generate_different_tokens() {
- // this test is not enough to ensure that generated strings are unique,
- // but it still does a simple and stupid verification
- String firstToken = underTest.generate();
- String secondToken = underTest.generate();
-
- assertThat(firstToken)
- .isNotEqualTo(secondToken)
- .hasSize(40);
- }
-
- @Test
- public void token_does_not_contain_colon() {
- assertThat(underTest.generate()).doesNotContain(":");
- }
-
- @Test
- public void hash_token() {
- String hash = underTest.hash("1234567890123456789012345678901234567890");
-
- assertThat(hash)
- .hasSize(96)
- .isEqualTo("b2501fc3833ae6feba7dc8a973a22d709b7c796ee97cbf66db2c22df873a9fa147b1b630878f771457b7769efd9ffa0d")
- .matches("[0-9a-f]+");
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/usertoken/UserTokenAuthenticationTest.java b/server/sonar-server/src/test/java/org/sonar/server/usertoken/UserTokenAuthenticationTest.java
deleted file mode 100644
index b93ae8bb6c8..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/usertoken/UserTokenAuthenticationTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usertoken;
-
-import java.util.Optional;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTokenDto;
-import org.sonar.server.authentication.UserLastConnectionDatesUpdater;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class UserTokenAuthenticationTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Rule
- public DbTester db = DbTester.create(System2.INSTANCE);
-
- private TokenGenerator tokenGenerator = mock(TokenGenerator.class);
- private UserLastConnectionDatesUpdater userLastConnectionDatesUpdater = mock(UserLastConnectionDatesUpdater.class);
-
- private UserTokenAuthentication underTest = new UserTokenAuthentication(tokenGenerator, db.getDbClient(), userLastConnectionDatesUpdater);
-
- @Test
- public void return_login_when_token_hash_found_in_db() {
- String token = "known-token";
- String tokenHash = "123456789";
- when(tokenGenerator.hash(token)).thenReturn(tokenHash);
- UserDto user1 = db.users().insertUser();
- db.users().insertToken(user1, t -> t.setTokenHash(tokenHash));
- UserDto user2 = db.users().insertUser();
- db.users().insertToken(user2, t -> t.setTokenHash("another-token-hash"));
-
- Optional<String> login = underTest.authenticate(token);
-
- assertThat(login.isPresent()).isTrue();
- assertThat(login.get()).isEqualTo(user1.getUuid());
- verify(userLastConnectionDatesUpdater).updateLastConnectionDateIfNeeded(any(UserTokenDto.class));
- }
-
- @Test
- public void return_absent_if_token_hash_is_not_found() {
- Optional<String> login = underTest.authenticate("unknown-token");
-
- assertThat(login.isPresent()).isFalse();
- verify(userLastConnectionDatesUpdater, never()).updateLastConnectionDateIfNeeded(any(UserTokenDto.class));
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/usertoken/UserTokenModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/usertoken/UserTokenModuleTest.java
deleted file mode 100644
index 3d2b3669b0c..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/usertoken/UserTokenModuleTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.usertoken;
-
-import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
-
-public class UserTokenModuleTest {
- @Test
- public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
- new UserTokenModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/util/MetricKeyValidatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/util/MetricKeyValidatorTest.java
deleted file mode 100644
index 68d3eaba609..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/util/MetricKeyValidatorTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.util;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class MetricKeyValidatorTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Test
- public void isMetricKeyValid() {
- assertThat(MetricKeyValidator.isMetricKeyValid("")).isFalse();
- assertThat(MetricKeyValidator.isMetricKeyValid("1_2_3-ABC-1_2_3")).isTrue();
- assertThat(MetricKeyValidator.isMetricKeyValid("123_321")).isTrue();
- assertThat(MetricKeyValidator.isMetricKeyValid("123456")).isFalse();
- assertThat(MetricKeyValidator.isMetricKeyValid("1.2.3_A_3:2:1")).isFalse();
- }
-
- @Test
- public void checkMetricKeyFormat() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Malformed metric key '123456'. Allowed characters are alphanumeric, '-', '_', with at least one non-digit.");
-
- MetricKeyValidator.checkMetricKeyFormat("123456");
- }
-}