diff --git a/scm-ui/src/users/components/UserForm.js b/scm-ui/src/users/components/UserForm.js index 15553a2b3a..22c04ac237 100644 --- a/scm-ui/src/users/components/UserForm.js +++ b/scm-ui/src/users/components/UserForm.js @@ -1,9 +1,10 @@ // @flow import React from "react"; -import {translate} from "react-i18next"; -import type {User} from "../types/User"; -import {Checkbox, InputField} from "../../components/forms"; -import {SubmitButton} from "../../components/buttons"; +import { translate } from "react-i18next"; +import type { User } from "../types/User"; +import { Checkbox, InputField } from "../../components/forms"; +import { SubmitButton } from "../../components/buttons"; +import * as validator from "./userValidation"; type Props = { submitForm: User => void, @@ -21,11 +22,10 @@ type State = { validatePassword: string }; - class UserForm extends React.Component { constructor(props: Props) { super(props); - + this.state = { user: { name: "", @@ -46,7 +46,7 @@ class UserForm extends React.Component { } componentDidMount() { - this.setState({ user: {...this.props.user} }); + this.setState({ user: { ...this.props.user } }); } submit = (event: Event) => { @@ -57,8 +57,14 @@ class UserForm extends React.Component { render() { const { t } = this.props; const user = this.state.user; - const ButtonClickable = (this.state.validatePasswordError || this.state.nameValidationError || this.state.mailValidationError || this.state.validatePasswordError - || this.state.displayNameValidationError || user.name === undefined|| user.displayName === undefined); + const ButtonClickable = + this.state.validatePasswordError || + this.state.nameValidationError || + this.state.mailValidationError || + this.state.validatePasswordError || + this.state.displayNameValidationError || + user.name === undefined || + user.displayName === undefined; let nameField = null; if (!this.props.user) { nameField = ( @@ -66,8 +72,8 @@ class UserForm extends React.Component { label={t("user.name")} onChange={this.handleUsernameChange} value={user ? user.name : ""} - validationError= {this.state.nameValidationError} - errorMessage= {t("validation.name-invalid")} + validationError={this.state.nameValidationError} + errorMessage={t("validation.name-invalid")} /> ); } @@ -85,7 +91,7 @@ class UserForm extends React.Component { label={t("user.mail")} onChange={this.handleEmailChange} value={user ? user.mail : ""} - validationError= {this.state.mailValidationError} + validationError={this.state.mailValidationError} errorMessage={t("validation.mail-invalid")} /> { onChange={this.handleActiveChange} checked={user ? user.active : false} /> - + ); } - handleUsernameChange = (name: string) => { - const REGEX_NAME = /^[^ ][A-z0-9\\.\-_@ ]*[^ ]$/; - this.setState( {nameValidationError: !REGEX_NAME.test(name), user : {...this.state.user, name} } ); + this.setState({ + nameValidationError: !validator.isNameValid(name), + user: { ...this.state.user, name } + }); }; - handleDisplayNameChange = (displayName: string) => { - const REGEX_NAME = /^[^ ][A-z0-9\\.\-_@ ]*[^ ]$/; - this.setState({displayNameValidationError: !REGEX_NAME.test(displayName), user : {...this.state.user, displayName} } ); + handleDisplayNameChange = (displayName: string) => { + this.setState({ + displayNameValidationError: !validator.isDisplayNameValid(displayName), + user: { ...this.state.user, displayName } + }); }; handleEmailChange = (mail: string) => { - const REGEX_MAIL = /^[A-z0-9][\w.-]*@[A-z0-9][\w\-\\.]*\.[A-z0-9][A-z0-9-]+$/; - this.setState( {mailValidationError: !REGEX_MAIL.test(mail), user : {...this.state.user, mail} } ); + this.setState({ + mailValidationError: !validator.isMailValid(mail), + user: { ...this.state.user, mail } + }); }; handlePasswordChange = (password: string) => { - const validatePasswordError = !this.checkPasswords(password, this.state.validatePassword); - this.setState( {validatePasswordError: (password.length < 6) || (password.length > 32), passwordValidationError: validatePasswordError, user : {...this.state.user, password} } ); + const validatePasswordError = !this.checkPasswords( + password, + this.state.validatePassword + ); + this.setState({ + validatePasswordError: !validator.isPasswordValid(password), + passwordValidationError: validatePasswordError, + user: { ...this.state.user, password } + }); }; handlePasswordValidationChange = (validatePassword: string) => { - const validatePasswordError = this.checkPasswords(this.state.user.password, validatePassword) - this.setState({ validatePassword, passwordValidationError: !validatePasswordError }); + const validatePasswordError = this.checkPasswords( + this.state.user.password, + validatePassword + ); + this.setState({ + validatePassword, + passwordValidationError: !validatePasswordError + }); }; checkPasswords = (password1: string, password2: string) => { - return (password1 === password2); - } + return password1 === password2; + }; handleAdminChange = (admin: boolean) => { - this.setState({ user : {...this.state.user, admin} }); + this.setState({ user: { ...this.state.user, admin } }); }; handleActiveChange = (active: boolean) => { - this.setState({ user : {...this.state.user, active} }); + this.setState({ user: { ...this.state.user, active } }); }; } diff --git a/scm-ui/src/users/components/userValidation.js b/scm-ui/src/users/components/userValidation.js new file mode 100644 index 0000000000..aba73063f8 --- /dev/null +++ b/scm-ui/src/users/components/userValidation.js @@ -0,0 +1,24 @@ +// @flow + +const nameRegex = /^([A-z0-9\.\-_@]|[^ ]([A-z0-9\.\-_@ ]*[A-z0-9\.\-_@]|[^\s])?)$/; + +export const isNameValid = (name: string) => { + return nameRegex.test(name); +}; + +export const isDisplayNameValid = (displayName: string) => { + if (displayName) { + return true; + } + return false; +}; + +const mailRegex = /^[A-z0-9][\w.-]*@[A-z0-9][\w\-\.]*\.[A-z0-9][A-z0-9-]+$/; + +export const isMailValid = (mail: string) => { + return mailRegex.test(mail); +}; + +export const isPasswordValid = (password: string) => { + return password.length > 6 && password.length < 32; +}; diff --git a/scm-ui/src/users/components/userValidator.test.js b/scm-ui/src/users/components/userValidator.test.js new file mode 100644 index 0000000000..370247fe90 --- /dev/null +++ b/scm-ui/src/users/components/userValidator.test.js @@ -0,0 +1,114 @@ +// @flow +import * as validator from "./userValidation"; + +describe("test name validation", () => { + it("should return false", () => { + // invalid names taken from ValidationUtilTest.java + const invalidNames = [ + " test 123", + " test 123 ", + "test 123 ", + "test/123", + "test%123", + "test:123", + "t ", + " t", + " t ", + "" + ]; + for (let name of invalidNames) { + expect(validator.isNameValid(name)).toBe(false); + } + }); + + it("should return true", () => { + // valid names taken from ValidationUtilTest.java + const validNames = [ + "test", + "test.git", + "Test123.git", + "Test123-git", + "Test_user-123.git", + "test@scm-manager.de", + "test 123", + "tt", + "t" + ]; + for (let name of validNames) { + expect(validator.isNameValid(name)).toBe(true); + } + }); +}); + +describe("test displayName validation", () => { + it("should return false", () => { + expect(validator.isDisplayNameValid("")).toBe(false); + }); + + it("should return true", () => { + // valid names taken from ValidationUtilTest.java + const validNames = [ + "Arthur Dent", + "Tricia.McMillan@hitchhiker.com", + "Ford Prefect (ford.prefect@hitchhiker.com)", + "Zaphod Beeblebrox ", + "Marvin, der depressive Roboter" + ]; + for (let name of validNames) { + expect(validator.isDisplayNameValid(name)).toBe(true); + } + }); +}); + +describe("test mail validation", () => { + it("should return false", () => { + // invalid taken from ValidationUtilTest.java + const invalid = [ + "ostfalia.de", + "@ostfalia.de", + "s.sdorra@", + "s.sdorra@ostfalia", + "s.sdorra@@ostfalia.de", + "s.sdorra@ ostfalia.de", + "s.sdorra @ostfalia.de" + ]; + for (let mail of invalid) { + expect(validator.isMailValid(mail)).toBe(false); + } + }); + + it("should return true", () => { + // valid taken from ValidationUtilTest.java + const valid = [ + "s.sdorra@ostfalia.de", + "sdorra@ostfalia.de", + "s.sdorra@hbk-bs.de", + "s.sdorra@gmail.com", + "s.sdorra@t.co", + "s.sdorra@ucla.college", + "s.sdorra@example.xn--p1ai", + "s.sdorra@scm.solutions" + ]; + for (let mail of valid) { + expect(validator.isMailValid(mail)).toBe(true); + } + }); +}); + +describe("test password validation", () => { + it("should return false", () => { + // invalid taken from ValidationUtilTest.java + const invalid = ["", "abc", "aaabbbcccdddeeefffggghhhiiijjjkkk"]; + for (let password of invalid) { + expect(validator.isPasswordValid(password)).toBe(false); + } + }); + + it("should return true", () => { + // valid taken from ValidationUtilTest.java + const valid = ["secret123", "mySuperSecretPassword"]; + for (let password of valid) { + expect(validator.isPasswordValid(password)).toBe(true); + } + }); +});