diff --git a/server/channels/api4/user_test.go b/server/channels/api4/user_test.go index 37b9583ced..3e0dd715ef 100644 --- a/server/channels/api4/user_test.go +++ b/server/channels/api4/user_test.go @@ -4272,6 +4272,91 @@ func TestSwitchAccount(t *testing.T) { _, appErr := th.App.Srv().Store().User().UpdateAuthData(th.BasicUser.Id, model.UserAuthServiceGitlab, &fakeAuthData, th.BasicUser.Email, true) require.NoError(t, appErr) + t.Run("From GitLab to Email", func(t *testing.T) { + sr = &model.SwitchRequest{ + CurrentService: model.UserAuthServiceGitlab, + NewService: model.UserAuthServiceEmail, + Email: th.BasicUser.Email, + NewPassword: th.BasicUser.Password, + } + + t.Run("Switching from OAuth to email is disabled if EnableSignUpWithEmail is false", func(t *testing.T) { + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.EmailSettings.EnableSignUpWithEmail = false }) + t.Cleanup(func() { + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.EmailSettings.EnableSignUpWithEmail = true }) + }) + + _, resp, err = th.Client.SwitchAccountType(context.Background(), sr) + require.Error(t, err) + assert.Equal(t, "api.user.auth_switch.not_available.email_signup_disabled.app_error", err.(*model.AppError).Id) + CheckForbiddenStatus(t, resp) + }) + + t.Run("Switching from OAuth to email is disabled if EnableSignInWithEmail and EnableSignInWithUsername is false", func(t *testing.T) { + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.EmailSettings.EnableSignInWithEmail = false + *cfg.EmailSettings.EnableSignInWithUsername = false + }) + t.Cleanup(func() { + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.EmailSettings.EnableSignInWithEmail = true + *cfg.EmailSettings.EnableSignInWithUsername = true + }) + }) + + _, resp, err = th.Client.SwitchAccountType(context.Background(), sr) + require.Error(t, err) + assert.Equal(t, "api.user.auth_switch.not_available.login_disabled.app_error", err.(*model.AppError).Id) + CheckForbiddenStatus(t, resp) + }) + }) + + t.Run("From LDAP to Email", func(t *testing.T) { + _, err = th.App.Srv().Store().User().UpdateAuthData(th.BasicUser.Id, model.UserAuthServiceLdap, &fakeAuthData, th.BasicUser.Email, true) + require.NoError(t, err) + + t.Cleanup(func() { + _, err = th.App.Srv().Store().User().UpdateAuthData(th.BasicUser.Id, model.UserAuthServiceGitlab, &fakeAuthData, th.BasicUser.Email, true) + require.NoError(t, err) + }) + + sr = &model.SwitchRequest{ + CurrentService: model.UserAuthServiceLdap, + NewService: model.UserAuthServiceEmail, + Email: th.BasicUser.Email, + NewPassword: th.BasicUser.Password, + } + + t.Run("Switching from LDAP to email is disabled if EnableSignUpWithEmail is false", func(t *testing.T) { + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.EmailSettings.EnableSignUpWithEmail = false }) + t.Cleanup(func() { + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.EmailSettings.EnableSignUpWithEmail = true }) + }) + + _, resp, err = th.Client.SwitchAccountType(context.Background(), sr) + require.Error(t, err) + assert.Equal(t, "api.user.auth_switch.not_available.email_signup_disabled.app_error", err.(*model.AppError).Id) + CheckForbiddenStatus(t, resp) + }) + t.Run("Switching from LDAP to email is disabled if EnableSignInWithEmail and EnableSignInWithUsername is false", func(t *testing.T) { + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.EmailSettings.EnableSignInWithEmail = false + *cfg.EmailSettings.EnableSignInWithUsername = false + }) + t.Cleanup(func() { + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.EmailSettings.EnableSignInWithEmail = true + *cfg.EmailSettings.EnableSignInWithUsername = true + }) + }) + + _, resp, err = th.Client.SwitchAccountType(context.Background(), sr) + require.Error(t, err) + assert.Equal(t, "api.user.auth_switch.not_available.login_disabled.app_error", err.(*model.AppError).Id) + CheckForbiddenStatus(t, resp) + }) + }) + sr = &model.SwitchRequest{ CurrentService: model.UserAuthServiceGitlab, NewService: model.UserAuthServiceEmail, diff --git a/server/channels/app/ldap.go b/server/channels/app/ldap.go index 515556597b..8840798398 100644 --- a/server/channels/app/ldap.go +++ b/server/channels/app/ldap.go @@ -129,6 +129,14 @@ func (a *App) SwitchLdapToEmail(c request.CTX, ldapPassword, code, email, newPas return "", model.NewAppError("ldapToEmail", "api.user.ldap_to_email.not_available.app_error", nil, "", http.StatusForbidden) } + if !*a.Config().EmailSettings.EnableSignUpWithEmail { + return "", model.NewAppError("SwitchEmailToLdap", "api.user.auth_switch.not_available.email_signup_disabled.app_error", nil, "", http.StatusForbidden) + } + + if !*a.Config().EmailSettings.EnableSignInWithEmail && !*a.Config().EmailSettings.EnableSignInWithUsername { + return "", model.NewAppError("SwitchEmailToLdap", "api.user.auth_switch.not_available.login_disabled.app_error", nil, "", http.StatusForbidden) + } + user, err := a.GetUserByEmail(email) if err != nil { return "", err diff --git a/server/channels/app/oauth.go b/server/channels/app/oauth.go index 2a394bef45..7b11d4b384 100644 --- a/server/channels/app/oauth.go +++ b/server/channels/app/oauth.go @@ -986,6 +986,14 @@ func (a *App) SwitchOAuthToEmail(c request.CTX, email, password, requesterId str return "", model.NewAppError("oauthToEmail", "api.user.oauth_to_email.not_available.app_error", nil, "", http.StatusForbidden) } + if !*a.Config().EmailSettings.EnableSignUpWithEmail { + return "", model.NewAppError("SwitchOAuthToEmail", "api.user.auth_switch.not_available.email_signup_disabled.app_error", nil, "", http.StatusForbidden) + } + + if !*a.Config().EmailSettings.EnableSignInWithEmail && !*a.Config().EmailSettings.EnableSignInWithUsername { + return "", model.NewAppError("SwitchOAuthToEmail", "api.user.auth_switch.not_available.login_disabled.app_error", nil, "", http.StatusForbidden) + } + user, err := a.GetUserByEmail(email) if err != nil { return "", err diff --git a/server/i18n/en.json b/server/i18n/en.json index 27abe9f077..8bd0903e16 100644 --- a/server/i18n/en.json +++ b/server/i18n/en.json @@ -4066,6 +4066,14 @@ "id": "api.user.add_user_to_group_syncables.not_ldap_user.app_error", "translation": "not an ldap user" }, + { + "id": "api.user.auth_switch.not_available.email_signup_disabled.app_error", + "translation": "Authentication Transfer is not available as email signup is disabled." + }, + { + "id": "api.user.auth_switch.not_available.login_disabled.app_error", + "translation": "Authentication Transfer is not available as neither email login nor username login is enabled." + }, { "id": "api.user.authorize_oauth_user.bad_response.app_error", "translation": "Bad response from token request." diff --git a/webapp/channels/src/components/user_settings/security/__snapshots__/user_settings_security.test.tsx.snap b/webapp/channels/src/components/user_settings/security/__snapshots__/user_settings_security.test.tsx.snap index 0a6b0a3cba..4210350748 100644 --- a/webapp/channels/src/components/user_settings/security/__snapshots__/user_settings_security.test.tsx.snap +++ b/webapp/channels/src/components/user_settings/security/__snapshots__/user_settings_security.test.tsx.snap @@ -547,3 +547,141 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps `; + +exports[`components/user_settings/display/UserSettingsDisplay should match snapshot, to email 1`] = ` +
+ + } + /> +
+ + } + /> +
+ + } + updateSection={[Function]} + /> +
+ +
+
+ +
+ + } + max={null} + section="signin" + title="Sign-in Method" + updateSection={[Function]} + /> +
+
+ + + + + + + + +
+
+`; diff --git a/webapp/channels/src/components/user_settings/security/index.ts b/webapp/channels/src/components/user_settings/security/index.ts index 60c910c08d..649ee065d8 100644 --- a/webapp/channels/src/components/user_settings/security/index.ts +++ b/webapp/channels/src/components/user_settings/security/index.ts @@ -35,7 +35,7 @@ function mapStateToProps(state: GlobalState, ownProps: Props) { const userHasTokenRole = UserUtils.hasUserAccessTokenRole(ownProps.user.roles) || UserUtils.isSystemAdmin(ownProps.user.roles); const enableOAuthServiceProvider = config.EnableOAuthServiceProvider === 'true'; - const enableSignUpWithEmail = config.EnableSignUpWithEmail === 'true'; + const allowedToSwitchToEmail = config.EnableSignUpWithEmail === 'true' && (config.EnableSignInWithEmail === 'true' || config.EnableSignInWithUsername === 'true'); const enableSignUpWithGitLab = config.EnableSignUpWithGitLab === 'true'; const enableSignUpWithGoogle = config.EnableSignUpWithGoogle === 'true'; const enableSignUpWithOpenId = config.EnableSignUpWithOpenId === 'true'; @@ -47,7 +47,7 @@ function mapStateToProps(state: GlobalState, ownProps: Props) { return { canUseAccessTokens: tokensEnabled && userHasTokenRole, enableOAuthServiceProvider, - enableSignUpWithEmail, + allowedToSwitchToEmail, enableSignUpWithGitLab, enableSignUpWithGoogle, enableSignUpWithOpenId, diff --git a/webapp/channels/src/components/user_settings/security/user_settings_security.test.tsx b/webapp/channels/src/components/user_settings/security/user_settings_security.test.tsx index 84c3963085..1095648421 100644 --- a/webapp/channels/src/components/user_settings/security/user_settings_security.test.tsx +++ b/webapp/channels/src/components/user_settings/security/user_settings_security.test.tsx @@ -8,6 +8,7 @@ import type {OAuthApp} from '@mattermost/types/integrations'; import type {UserProfile} from '@mattermost/types/users'; import type {MockIntl} from 'tests/helpers/intl-test-helper'; +import Constants from 'utils/constants'; import type * as Utils from 'utils/utils'; import {SecurityTab} from './user_settings_security'; @@ -37,7 +38,7 @@ describe('components/user_settings/display/UserSettingsDisplay', () => { }, canUseAccessTokens: true, enableOAuthServiceProvider: false, - enableSignUpWithEmail: true, + allowedToSwitchToEmail: true, enableSignUpWithGitLab: false, enableSignUpWithGoogle: true, enableSignUpWithOpenId: false, @@ -80,6 +81,18 @@ describe('components/user_settings/display/UserSettingsDisplay', () => { expect(wrapper).toMatchSnapshot(); }); + test('should match snapshot, to email', () => { + const user = { + id: 'user_id', + auth_service: Constants.OPENID_SERVICE, + }; + + const props = {...requiredProps, user: user as UserProfile}; + + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); + }); + test('componentDidMount() should have called getAuthorizedOAuthApps', () => { const props = {...requiredProps, enableOAuthServiceProvider: true}; diff --git a/webapp/channels/src/components/user_settings/security/user_settings_security.tsx b/webapp/channels/src/components/user_settings/security/user_settings_security.tsx index 2a0cabecd1..88ad8d1720 100644 --- a/webapp/channels/src/components/user_settings/security/user_settings_security.tsx +++ b/webapp/channels/src/components/user_settings/security/user_settings_security.tsx @@ -56,7 +56,7 @@ type Props = { setRequireConfirm: () => void; canUseAccessTokens: boolean; enableOAuthServiceProvider: boolean; - enableSignUpWithEmail: boolean; + allowedToSwitchToEmail: boolean; enableSignUpWithGitLab: boolean; enableSignUpWithGoogle: boolean; enableSignUpWithOpenId: boolean; @@ -671,7 +671,7 @@ export class SecurityTab extends React.PureComponent {
); } - } else if (this.props.enableSignUpWithEmail) { + } else if (this.props.allowedToSwitchToEmail) { let link; if (user.auth_service === Constants.LDAP_SERVICE) { link = @@ -966,7 +966,7 @@ export class SecurityTab extends React.PureComponent { // If there are other sign-in methods and either email is enabled or the user's account is email, then allow switching let signInSection; if ( - (this.props.enableSignUpWithEmail || user.auth_service === '') && + (this.props.allowedToSwitchToEmail || user.auth_service === '') && numMethods > 0 && this.props.experimentalEnableAuthenticationTransfer ) {