diff --git a/frontend/src/components/btn-qr-code.js b/frontend/src/components/btn-qr-code.js index 7761db1867..3c441d66a0 100644 --- a/frontend/src/components/btn-qr-code.js +++ b/frontend/src/components/btn-qr-code.js @@ -16,8 +16,7 @@ class ButtonQR extends React.Component { this.state = { isPopoverOpen: false }; - - this.btnID = 'btn-' + Math.random().toString().substr(2, 5); + this.btn = null; } togglePopover = () => { @@ -30,14 +29,16 @@ class ButtonQR extends React.Component { const { link } = this.props; const { isPopoverOpen } = this.state; return ( -
- - - - -

{gettext('Scan the QR code to view the shared content directly')}

-
-
+
this.btn = ref}> + + {this.btn && ( + + + +

{gettext('Scan the QR code to view the shared content directly')}

+
+
+ )}
); } diff --git a/frontend/src/components/dialog/org-add-user-dialog.js b/frontend/src/components/dialog/org-add-user-dialog.js index 20ade6b1f9..3e26722c49 100644 --- a/frontend/src/components/dialog/org-add-user-dialog.js +++ b/frontend/src/components/dialog/org-add-user-dialog.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { Button, Modal, Input, ModalBody, ModalFooter, Label, Form, InputGroup, FormGroup } from 'reactstrap'; import { gettext } from '../../utils/constants'; import SeahubModalHeader from '@/components/common/seahub-modal-header'; +import { Utils } from '../../utils/utils'; const propTypes = { toggle: PropTypes.func.isRequired, @@ -48,7 +49,7 @@ class AddOrgUserDialog extends React.Component { }; generatePassword = () => { - let val = Math.random().toString(36).substr(5); + let val = Utils.generatePassword(8); this.setState({ password: val, newPassword: val, diff --git a/frontend/src/utils/utils.js b/frontend/src/utils/utils.js index 51f138e1b2..7aac7e2251 100644 --- a/frontend/src/utils/utils.js +++ b/frontend/src/utils/utils.js @@ -1578,21 +1578,34 @@ export const Utils = { } }, - generatePassword: function (length, hasNum = 1, hasChar = 1, hasSymbol = 1) { + generateSecureRandomInRange: function (min, max) { + const start = Math.min(min, max); + const end = Math.max(min, max); + const range = end - start + 1; + const byteSize = Math.ceil(Math.log2(range) / 8); + + const randomBytes = new Uint8Array(byteSize); + window.crypto.getRandomValues(randomBytes); + + const randomValue = Array.from(randomBytes).reduce((pre, byte) => (pre << 8) | byte, 0); + return start + (randomValue % range); + }, + + generatePassword: function (length) { var password = ''; // 65~90:A~Z - password += String.fromCharCode(Math.floor((Math.random() * (90 - 65)) + 65)); + password += String.fromCharCode(this.generateSecureRandomInRange(65, 90)); // 97~122:a~z - password += String.fromCharCode(Math.floor((Math.random() * (122 - 97)) + 97)); + password += String.fromCharCode(this.generateSecureRandomInRange(97, 122)); // 48~57:0~9 - password += String.fromCharCode(Math.floor((Math.random() * (57 - 48)) + 48)); + password += String.fromCharCode(this.generateSecureRandomInRange(48, 57)); // 33~47:!~/ - password += String.fromCharCode(Math.floor((Math.random() * (47 - 33)) + 33)); + password += String.fromCharCode(this.generateSecureRandomInRange(33, 47)); // 33~47:!~/ // 48~57:0~9 @@ -1602,8 +1615,7 @@ export const Utils = { // 97~122:a~z // 123~127:{~ for (var i = 0; i < length - 4; i++) { - var num = Math.floor((Math.random() * (127 - 33)) + 33); - password += String.fromCharCode(num); + password += String.fromCharCode(this.generateSecureRandomInRange(33, 127)); } return password;