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

mendersoftware / gui / 1081664682

22 Nov 2023 02:11PM UTC coverage: 82.798% (-17.2%) from 99.964%
1081664682

Pull #4214

gitlab-ci

tranchitella
fix: Fixed the infinite page redirects when the back button is pressed

Remove the location and navigate from the useLocationParams.setValue callback
dependencies as they change the set function that is presented in other
useEffect dependencies. This happens when the back button is clicked, which
leads to the location changing infinitely.

Changelog: Title
Ticket: MEN-6847
Ticket: MEN-6796

Signed-off-by: Ihor Aleksandrychiev <ihor.aleksandrychiev@northern.tech>
Signed-off-by: Fabio Tranchitella <fabio.tranchitella@northern.tech>
Pull Request #4214: fix: Fixed the infinite page redirects when the back button is pressed

4319 of 6292 branches covered (0.0%)

8332 of 10063 relevant lines covered (82.8%)

191.0 hits per line

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

79.49
/src/js/components/settings/organization/samlconfig.js
1
// Copyright 2022 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, useState } from 'react';
15
import Dropzone from 'react-dropzone';
16

17
// material ui
18
import { CloudUpload } from '@mui/icons-material';
19
import { Button } from '@mui/material';
20
import { listItemTextClasses } from '@mui/material/ListItemText';
21
import { makeStyles } from 'tss-react/mui';
22

23
import { useradmApiUrl } from '../../../constants/userConstants';
24
import { toggle } from '../../../helpers';
25
import ExpandableAttribute from '../../common/expandable-attribute';
26
import { HELPTOOLTIPS, MenderHelpTooltip } from '../../helptips/helptooltips';
27
import { maxWidth } from './organizationsettingsitem';
28
import SSOEditor from './ssoeditor';
29

30
const useStyles = makeStyles()(theme => ({
6✔
31
  configDetail: {
32
    maxWidth,
33
    [`.${listItemTextClasses.primary}`]: {
34
      color: theme.palette.text.disabled,
35
      fontSize: 'smaller'
36
    }
37
  },
38
  uploadIcon: {
39
    marginBottom: theme.spacing(-0.5),
40
    marginRight: theme.spacing()
41
  },
42
  tinyMargin: {
43
    marginLeft: theme.spacing(0.5),
44
    marginRight: theme.spacing(0.5)
45
  },
46
  wrapper: {
47
    alignItems: 'start',
48
    columnGap: theme.spacing(2),
49
    display: 'grid',
50
    gridTemplateColumns: `minmax(max-content, ${maxWidth}px) max-content max-content`,
51
    position: 'relative',
52
    ['&.has-sso']: {
53
      gridTemplateColumns: `${maxWidth - 45}px 1fr`
54
    }
55
  }
56
}));
57

58
const defaultDetails = [
6✔
59
  { key: 'entityID', label: 'Entity ID', getValue: id => `${window.location.origin}${useradmApiUrl}/sso/sp/metadata/${id}` },
3✔
60
  { key: 'acs', label: 'ACS URL', getValue: id => `${window.location.origin}${useradmApiUrl}/auth/sso/${id}/acs` },
3✔
61
  { key: 'startURL', label: 'Start URL', getValue: id => `${window.location.origin}${useradmApiUrl}/auth/sso/${id}/login` }
3✔
62
];
63

64
export const SAMLConfig = ({ configs, onCancel, onSave, setSnackbar, token }) => {
6✔
65
  const [configDetails, setConfigDetails] = useState([]);
17✔
66
  const [fileContent, setFileContent] = useState('');
17✔
67
  const [hasSSOConfig, setHasSSOConfig] = useState(false);
17✔
68
  const [isEditing, setIsEditing] = useState(false);
17✔
69

70
  const config = configs.length ? configs[0] : undefined;
17✔
71
  const { id, ...content } = config || {};
17✔
72
  const configContent = content.config || '';
17✔
73

74
  const { classes } = useStyles();
17✔
75

76
  useEffect(() => {
17✔
77
    setHasSSOConfig(!!config);
7✔
78
    setFileContent(configContent);
7✔
79
    if (config?.config) {
7✔
80
      setConfigDetails(defaultDetails.map(item => ({ ...item, value: item.getValue(config.id) })));
9✔
81
    }
82
  }, [config, configContent]);
83

84
  const onCancelSSOSettings = () => {
17✔
85
    setHasSSOConfig(!!config);
×
86
    setFileContent(configContent);
×
87
    setIsEditing(false);
×
88
    onCancel();
×
89
  };
90

91
  const onSaveSSOSettings = () => {
17✔
92
    onSave(id, fileContent);
×
93
    setIsEditing(false);
×
94
  };
95

96
  const onDrop = acceptedFiles => {
17✔
97
    let reader = new FileReader();
1✔
98
    reader.fileName = acceptedFiles[0].name;
1✔
99
    reader.onerror = error => console.log('Error: ', error);
1✔
100
    reader.onload = () => {
1✔
101
      setIsEditing(true);
×
102
      setFileContent(reader.result);
×
103
    };
104
    reader.readAsBinaryString(acceptedFiles[0]);
1✔
105
  };
106

107
  const onOpenEditorClick = () => setIsEditing(toggle);
17✔
108

109
  return (
17✔
110
    <>
111
      <div className={`flexbox center-aligned ${classes.wrapper} ${hasSSOConfig ? 'has-sso' : ''}`}>
17✔
112
        {hasSSOConfig ? (
17✔
113
          <a onClick={onOpenEditorClick}>View metadata in the text editor</a>
114
        ) : (
115
          <>
116
            <MenderHelpTooltip id={HELPTOOLTIPS.samlMetadata.id} style={{ position: 'absolute', left: -35 }} placement="left" />
117
            <Dropzone multiple={false} onDrop={onDrop}>
118
              {({ getRootProps, getInputProps }) => (
119
                <div {...getRootProps()} className="dropzone onboard dashboard-placeholder flexbox centered">
12✔
120
                  <input {...getInputProps()} />
121
                  <CloudUpload className={classes.uploadIcon} fontSize="small" /> Drag here or <a className={classes.tinyMargin}>browse</a> to upload a metadata
122
                  document
123
                </div>
124
              )}
125
            </Dropzone>
126
            <div>
127
              or <a onClick={onOpenEditorClick}>input with the text editor</a>
128
            </div>
129
          </>
130
        )}
131
        <div className="flexbox">
132
          {hasSSOConfig && !isEditing ? (
44✔
133
            <Button onClick={onOpenEditorClick}>Edit</Button>
134
          ) : (
135
            <>
136
              <Button onClick={onCancelSSOSettings}>Cancel</Button>
137
              <Button className={classes.tinyMargin} onClick={onSaveSSOSettings} disabled={!fileContent} variant="contained">
138
                Save
139
              </Button>
140
            </>
141
          )}
142
        </div>
143
      </div>
144
      {hasSSOConfig && (
27✔
145
        <div className="flexbox column margin-top">
146
          {configDetails.map(item => (
147
            <ExpandableAttribute
30✔
148
              className={classes.configDetail}
149
              copyToClipboard
150
              key={item.key}
151
              primary={item.label}
152
              secondary={item.value}
153
              setSnackbar={setSnackbar}
154
              disableGutters
155
              dividerDisabled
156
            />
157
          ))}
158
        </div>
159
      )}
160
      <SSOEditor
161
        open={isEditing}
162
        config={configContent}
163
        fileContent={fileContent}
164
        hasSSOConfig={hasSSOConfig}
165
        onCancel={onCancelSSOSettings}
166
        onClose={onOpenEditorClick}
167
        onSave={onSaveSSOSettings}
168
        setFileContent={setFileContent}
169
        token={token}
170
      />
171
    </>
172
  );
173
};
174

175
export default SAMLConfig;
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