• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / gui / 897326496

pending completion
897326496

Pull #3752

gitlab-ci

mzedel
chore(e2e): made use of shared timeout & login checking values to remove code duplication

Signed-off-by: Manuel Zedel <manuel.zedel@northern.tech>
Pull Request #3752: chore(e2e-tests): slightly simplified log in test + separated log out test

4395 of 6392 branches covered (68.76%)

8060 of 9780 relevant lines covered (82.41%)

126.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

64.0
/src/js/components/settings/user-management/twofactorauthsetup.js
1
// Copyright 2019 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14
import React, { useCallback, useEffect, useState } from 'react';
15
import { connect } from 'react-redux';
16

17
import { Collapse, Switch } from '@mui/material';
18

19
import { setSnackbar } from '../../../actions/appActions';
20
import { disableUser2fa, enableUser2fa, get2FAQRCode, verify2FA, verifyEmailComplete, verifyEmailStart } from '../../../actions/userActions';
21
import { twoFAStates } from '../../../constants/userConstants';
22
import { getCurrentUser, getHas2FA } from '../../../selectors';
23
import InfoText from '../../common/infotext';
24
import AuthSetup from './twofactorauth-steps/authsetup';
25
import EmailVerification from './twofactorauth-steps/emailverification';
26

27
export const TwoFactorAuthSetup = ({
6✔
28
  activationCode,
29
  currentUser,
30
  disableUser2fa,
31
  enableUser2fa,
32
  get2FAQRCode,
33
  has2FA,
34
  qrImage,
35
  setSnackbar,
36
  verify2FA,
37
  verifyEmailComplete,
38
  verifyEmailStart
39
}) => {
40
  const [qrExpanded, setQrExpanded] = useState(false);
5✔
41
  const [is2FAEnabled, setIs2FAEnabled] = useState(has2FA);
5✔
42
  const [showEmailVerification, setShowEmailVerification] = useState(false);
5✔
43

44
  useEffect(() => {
5✔
45
    if ((currentUser.verified || currentUser.email?.endsWith('@example.com')) && is2FAEnabled && !has2FA) {
3!
46
      setShowEmailVerification(false);
1✔
47
      setQrExpanded(true);
1✔
48
    }
49
  }, [currentUser.email, currentUser.verified, is2FAEnabled, has2FA]);
50

51
  useEffect(() => {
5✔
52
    if (activationCode) {
2!
53
      setIs2FAEnabled(true);
×
54
      verifyEmailComplete(activationCode)
×
55
        .catch(() => {
56
          setShowEmailVerification(true);
×
57
          setQrExpanded(false);
×
58
        })
59
        // we have to explicitly call this, to not send the returned promise as user to activate 2fa for
60
        .then(() => enableUser2fa())
×
61
        .then(get2FAQRCode);
62
    }
63
  }, [activationCode]);
64

65
  useEffect(() => {
5✔
66
    if (has2FA) {
2!
67
      setIs2FAEnabled(has2FA);
×
68
    }
69
  }, [has2FA]);
70

71
  const handle2FAState = state => {
5✔
72
    setIs2FAEnabled(state !== twoFAStates.disabled);
2✔
73
    setQrExpanded(state === twoFAStates.unverified);
2✔
74
    let request;
75
    if (state === twoFAStates.disabled) {
2!
76
      request = disableUser2fa();
×
77
    } else if (state === twoFAStates.enabled && has2FA) {
2!
78
      request = Promise.resolve(setQrExpanded(false));
×
79
    } else {
80
      request = enableUser2fa();
2✔
81
    }
82
    request.then(() => {
2✔
83
      if (state === twoFAStates.unverified) {
1!
84
        get2FAQRCode();
1✔
85
      } else if (state === twoFAStates.enabled) {
×
86
        setSnackbar('Two Factor authentication set up successfully.');
×
87
      }
88
    });
89
  };
90

91
  const onToggle2FAClick = useCallback(() => {
5✔
92
    if (!(currentUser.verified || currentUser.email?.endsWith('@example.com'))) {
1!
93
      setShowEmailVerification(!showEmailVerification);
×
94
      setIs2FAEnabled(!showEmailVerification);
×
95
      return;
×
96
    }
97
    if (has2FA) {
1!
98
      handle2FAState(twoFAStates.disabled);
×
99
    } else {
100
      is2FAEnabled ? disableUser2fa() : handle2FAState(twoFAStates.unverified);
1!
101
      setQrExpanded(!is2FAEnabled);
1✔
102
      setIs2FAEnabled(!is2FAEnabled);
1✔
103
    }
104
  }, [currentUser.email, currentUser.verified, has2FA, is2FAEnabled, showEmailVerification]);
105

106
  return (
5✔
107
    <div className="margin-top">
108
      <div className="clickable flexbox space-between" onClick={onToggle2FAClick}>
109
        <p className="help-content">Enable Two Factor authentication</p>
110
        <Switch checked={is2FAEnabled} />
111
      </div>
112
      <InfoText style={{ width: '75%', margin: 0 }}>
113
        Two Factor Authentication adds a second layer of protection to your account by asking for an additional verification code each time you log in.
114
      </InfoText>
115
      {showEmailVerification && (
5!
116
        <EmailVerification activationCode={activationCode} verifyEmailComplete={verifyEmailComplete} verifyEmailStart={verifyEmailStart} />
117
      )}
118
      <Collapse in={qrExpanded} timeout="auto" unmountOnExit>
119
        <AuthSetup currentUser={currentUser} handle2FAState={handle2FAState} has2FA={has2FA} qrImage={qrImage} verify2FA={verify2FA} />
120
      </Collapse>
121
    </div>
122
  );
123
};
124

125
const actionCreators = { disableUser2fa, enableUser2fa, get2FAQRCode, setSnackbar, verify2FA, verifyEmailComplete, verifyEmailStart };
6✔
126

127
const mapStateToProps = state => {
6✔
128
  return {
2✔
129
    activationCode: state.users.activationCode,
130
    currentUser: getCurrentUser(state),
131
    has2FA: getHas2FA(state),
132
    previousPhases: state.users.globalSettings.previousPhases,
133
    qrImage: state.users.qrCode
134
  };
135
};
136

137
export default connect(mapStateToProps, actionCreators)(TwoFactorAuthSetup);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc