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

mendersoftware / gui / 951400782

pending completion
951400782

Pull #3900

gitlab-ci

web-flow
chore: bump @testing-library/jest-dom from 5.16.5 to 5.17.0

Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 5.16.5 to 5.17.0.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v5.16.5...v5.17.0)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #3900: chore: bump @testing-library/jest-dom from 5.16.5 to 5.17.0

4446 of 6414 branches covered (69.32%)

8342 of 10084 relevant lines covered (82.73%)

186.0 hits per line

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

88.04
/src/js/components/settings/user-management/userdefinition.js
1
// Copyright 2021 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, { useEffect, useMemo, useState } from 'react';
15

16
// material ui
17
import { Close as CloseIcon } from '@mui/icons-material';
18
import { Button, Checkbox, Divider, Drawer, FormControl, FormControlLabel, FormHelperText, IconButton, InputLabel, TextField } from '@mui/material';
19
import { makeStyles } from 'tss-react/mui';
20

21
import validator from 'validator';
22

23
import { mapUserRolesToUiPermissions } from '../../../actions/userActions';
24
import { uiPermissionsByArea, uiPermissionsById } from '../../../constants/userConstants';
25
import { toggle } from '../../../helpers';
26
import { TwoColumnData } from '../../common/configurationobject';
27
import { OAuth2Providers, genericProvider } from '../../login/oauth2providers';
28
import { UserRolesSelect } from './userform';
29

30
const useStyles = makeStyles()(theme => ({
6✔
31
  actionButtons: { justifyContent: 'flex-end' },
32
  divider: { marginTop: theme.spacing(4) },
33
  leftButton: { marginRight: theme.spacing(2) },
34
  oauthIcon: { fontSize: '36px', marginRight: 10 },
35
  widthLimit: { maxWidth: 500 }
36
}));
37

38
export const getUserSSOState = user => {
6✔
39
  const { sso = [] } = user;
51✔
40
  const isOAuth2 = !!sso.length;
51✔
41
  const provider = isOAuth2 ? OAuth2Providers.find(provider => sso.some(({ kind }) => kind.includes(provider.id))) ?? genericProvider : null;
51!
42
  return { isOAuth2, provider };
51✔
43
};
44

45
const mapPermissions = permissions => permissions.map(permission => uiPermissionsById[permission].title).join(', ');
36✔
46

47
const scopedPermissionAreas = ['groups', 'releases'];
6✔
48

49
export const UserDefinition = ({ currentUser, isEnterprise, onCancel, onSubmit, onRemove, roles, selectedUser }) => {
6✔
50
  const { email = '', id } = selectedUser;
41✔
51

52
  const { classes } = useStyles();
41✔
53

54
  const [nameError, setNameError] = useState(false);
41✔
55
  const [hadRoleChanges, setHadRoleChanges] = useState(false);
41✔
56
  const [selectedRoles, setSelectedRoles] = useState([]);
41✔
57
  const [shouldResetPassword, setShouldResetPassword] = useState(false);
41✔
58
  const [currentEmail, setCurrentEmail] = useState('');
41✔
59

60
  useEffect(() => {
41✔
61
    setCurrentEmail(email);
8✔
62
  }, [email]);
63

64
  useEffect(() => {
41✔
65
    setSelectedRoles(selectedUser.roles || []);
4✔
66
  }, [selectedUser.roles]);
67

68
  const validateNameChange = ({ target: { value } }) => {
41✔
69
    setNameError(!validator.isEmail(value) || validator.isEmpty(value));
14✔
70
    setCurrentEmail(value);
14✔
71
  };
72

73
  const onRemoveClick = () => {
41✔
74
    onRemove(selectedUser);
1✔
75
  };
76

77
  const onRolesSelect = (newlySelectedRoles, hadRoleChanges) => {
41✔
78
    setSelectedRoles(newlySelectedRoles);
3✔
79
    setHadRoleChanges(hadRoleChanges);
3✔
80
  };
81

82
  const onSubmitClick = () => {
41✔
83
    if (id && !hadRoleChanges && email === currentEmail) {
1!
84
      return onSubmit(null, 'edit', id, shouldResetPassword ? email : null);
×
85
    }
86
    const changedRoles = hadRoleChanges ? { roles: selectedRoles } : {};
1!
87
    const submissionData = { ...selectedUser, ...changedRoles, email: currentEmail };
1✔
88
    return onSubmit(submissionData, 'edit', id, shouldResetPassword ? currentEmail : null);
1!
89
  };
90

91
  const togglePasswordReset = () => setShouldResetPassword(toggle);
41✔
92

93
  const { areas, groups } = useMemo(() => {
41✔
94
    const emptySelection = { areas: {}, groups: {}, releases: {} };
11✔
95
    if (!(selectedRoles && roles)) {
11!
96
      return emptySelection;
×
97
    }
98

99
    return Object.entries(mapUserRolesToUiPermissions(selectedRoles, roles)).reduce((accu, [key, values]) => {
11✔
100
      if (scopedPermissionAreas.includes(key)) {
55✔
101
        accu[key] = Object.entries(values).reduce((groupsAccu, [name, uiPermissions]) => {
22✔
102
          groupsAccu[name] = mapPermissions(uiPermissions);
3✔
103
          return groupsAccu;
3✔
104
        }, {});
105
      } else {
106
        accu.areas[uiPermissionsByArea[key].title] = mapPermissions(values);
33✔
107
      }
108
      return accu;
55✔
109
    }, emptySelection);
110
  }, [selectedRoles, roles]);
111

112
  const isSubmitDisabled = !selectedRoles.length;
41✔
113

114
  const { isOAuth2, provider } = getUserSSOState(selectedUser);
41✔
115
  return (
41✔
116
    <Drawer anchor="right" open={!!id} PaperProps={{ style: { minWidth: 600, width: '50vw' } }}>
117
      <div className="flexbox margin-bottom-small space-between">
118
        <h3>Edit user</h3>
119
        <div className="flexbox center-aligned">
120
          {currentUser.id !== id && (
82✔
121
            <Button className={`flexbox center-aligned ${classes.leftButton}`} color="secondary" onClick={onRemoveClick}>
122
              delete user
123
            </Button>
124
          )}
125
          <IconButton onClick={onCancel} aria-label="close">
126
            <CloseIcon />
127
          </IconButton>
128
        </div>
129
      </div>
130
      <Divider />
131
      <FormControl className={classes.widthLimit}>
132
        <TextField label="Email" id="email" value={currentEmail} disabled={isOAuth2 || currentUser.id === id} error={nameError} onChange={validateNameChange} />
82✔
133
        {nameError && <FormHelperText className="warning">Please enter a valid email address</FormHelperText>}
53✔
134
      </FormControl>
135
      {isOAuth2 ? (
41!
136
        <div className="flexbox margin-top-small margin-bottom">
137
          <div className={classes.oauthIcon}>{provider.icon}</div>
138
          <div className="info">
139
            This user logs in using his <strong>{provider.name}</strong> account.
140
            <br />
141
            He can connect to {provider.name} to update his login settings.
142
          </div>
143
        </div>
144
      ) : (
145
        <FormControlLabel
146
          control={<Checkbox checked={shouldResetPassword} onChange={togglePasswordReset} />}
147
          label="Send an email to the user containing a link to reset the password"
148
        />
149
      )}
150
      {isEnterprise && (
82✔
151
        <>
152
          <UserRolesSelect currentUser={currentUser} onSelect={onRolesSelect} roles={roles} user={selectedUser} />
153
          {!!(Object.keys(groups).length || Object.keys(areas).length) && (
163✔
154
            <InputLabel className="margin-top" shrink>
155
              Role permissions
156
            </InputLabel>
157
          )}
158
          <TwoColumnData config={areas} />
159
          {!!Object.keys(groups).length && (
42✔
160
            <>
161
              <div className="slightly-smaller text-muted">Device groups</div>
162
              <TwoColumnData config={groups} />
163
            </>
164
          )}
165
        </>
166
      )}
167
      <Divider className={classes.divider} light />
168
      <div className={`flexbox centered margin-top ${classes.actionButtons}`}>
169
        <Button className={classes.leftButton} onClick={onCancel}>
170
          Cancel
171
        </Button>
172
        <Button color="secondary" variant="contained" disabled={isSubmitDisabled} target="_blank" onClick={onSubmitClick}>
173
          Save
174
        </Button>
175
      </div>
176
    </Drawer>
177
  );
178
};
179

180
export default UserDefinition;
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