ci: add password complexity options to organization edit page (#1949)

* Support uploading roles and permissions via xlsx file.

* Template xlsx file for uploading users and permissions.

* reformat according to gofumpt.

* fix typo.

* add password complexity options to organization edit page.

* add password complexity options to organization edit page.

* Fixed Typos.

* Fixed Typos.

* feat:add password complexity options to organization edit page

* Auto generate i18n fields.

* Refactor code according to instructions

* Support autocheck passwd complexity in frontend when setting passwd in user edit page.

* feat:Backend Support for password validation in signup and forget page.

* feat:Frontend Support for password validation in signup and forget page.

* Add default password complex option & Update historical empty filed with default option.

* Migrator for field `password_complex_options` in org table.

* feat: support frontend password complex option check in user_edit/forget/signup page.

* frontend update for user edit page

* update i18n file

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
This commit is contained in:
leoil 2023-06-17 00:01:20 +08:00 committed by Yang Luo
parent edc6aa0d50
commit 0f57ac297b
24 changed files with 420 additions and 24 deletions

View File

@ -140,6 +140,13 @@ func (c *ApiController) Signup() {
username = id username = id
} }
password := authForm.Password
msg = object.CheckPasswordComplexityByOrg(organization, password)
if msg != "" {
c.ResponseError(msg)
return
}
initScore, err := organization.GetInitScore() initScore, err := organization.GetInitScore()
if err != nil { if err != nil {
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error()) c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())

View File

@ -448,6 +448,12 @@ func (c *ApiController) SetPassword() {
} }
} }
msg := object.CheckPasswordComplexity(targetUser, newPassword)
if msg != "" {
c.ResponseError(msg)
return
}
targetUser.Password = newPassword targetUser.Password = newPassword
_, err = object.SetUserField(targetUser, "password", targetUser.Password) _, err = object.SetUserField(targetUser, "password", targetUser.Password)
if err != nil { if err != nil {

View File

@ -8,6 +8,7 @@
"favicon": "", "favicon": "",
"passwordType": "plain", "passwordType": "plain",
"passwordSalt": "", "passwordSalt": "",
"passwordOptions": ["AtLeast6"],
"countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"], "countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"],
"defaultAvatar": "", "defaultAvatar": "",
"defaultApplication": "", "defaultApplication": "",

View File

@ -203,6 +203,16 @@ func CheckPassword(user *User, password string, lang string, options ...bool) st
} }
} }
func CheckPasswordComplexityByOrg(organization *Organization, password string) string {
errorMsg := checkPasswordComplexity(password, organization.PasswordOptions)
return errorMsg
}
func CheckPasswordComplexity(user *User, password string) string {
organization, _ := GetOrganizationByUser(user)
return CheckPasswordComplexityByOrg(organization, password)
}
func checkLdapUserPassword(user *User, password string, lang string) string { func checkLdapUserPassword(user *User, password string, lang string) string {
ldaps, err := GetLdaps(user.Owner) ldaps, err := GetLdaps(user.Owner)
if err != nil { if err != nil {

View File

@ -0,0 +1,98 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package object
import (
"regexp"
)
type ValidatorFunc func(password string) string
var (
regexLowerCase = regexp.MustCompile(`[a-z]`)
regexUpperCase = regexp.MustCompile(`[A-Z]`)
regexDigit = regexp.MustCompile(`\d`)
regexSpecial = regexp.MustCompile(`[!@#$%^&*]`)
)
func isValidOption_AtLeast6(password string) string {
if len(password) < 6 {
return "The password must have at least 6 characters"
}
return ""
}
func isValidOption_AtLeast8(password string) string {
if len(password) < 8 {
return "The password must have at least 8 characters"
}
return ""
}
func isValidOption_Aa123(password string) string {
hasLowerCase := regexLowerCase.MatchString(password)
hasUpperCase := regexUpperCase.MatchString(password)
hasDigit := regexDigit.MatchString(password)
if !hasLowerCase || !hasUpperCase || !hasDigit {
return "The password must contain at least one uppercase letter, one lowercase letter and one digit"
}
return ""
}
func isValidOption_SpecialChar(password string) string {
if !regexSpecial.MatchString(password) {
return "The password must contain at least one special character"
}
return ""
}
func isValidOption_NoRepeat(password string) string {
for i := 0; i < len(password)-1; i++ {
if password[i] == password[i+1] {
return "The password must not contain any repeated characters"
}
}
return ""
}
func checkPasswordComplexity(password string, options []string) string {
if len(password) == 0 {
return "Please input your password!"
}
if len(options) == 0 {
options = []string{"AtLeast6"}
}
checkers := map[string]ValidatorFunc{
"AtLeast6": isValidOption_AtLeast6,
"AtLeast8": isValidOption_AtLeast8,
"Aa123": isValidOption_Aa123,
"SpecialChar": isValidOption_SpecialChar,
"NoRepeat": isValidOption_NoRepeat,
}
for _, option := range options {
checkerFunc, ok := checkers[option]
if ok {
errorMsg := checkerFunc(password)
if errorMsg != "" {
return errorMsg
}
}
}
return ""
}

View File

@ -92,6 +92,7 @@ func initBuiltInOrganization() bool {
WebsiteUrl: "https://example.com", WebsiteUrl: "https://example.com",
Favicon: fmt.Sprintf("%s/img/casbin/favicon.ico", conf.GetConfigString("staticBaseUrl")), Favicon: fmt.Sprintf("%s/img/casbin/favicon.ico", conf.GetConfigString("staticBaseUrl")),
PasswordType: "plain", PasswordType: "plain",
PasswordOptions: []string{"AtLeast6"},
CountryCodes: []string{"US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"}, CountryCodes: []string{"US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"},
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")), DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
Tags: []string{}, Tags: []string{},

View File

@ -56,6 +56,7 @@ type Organization struct {
Favicon string `xorm:"varchar(100)" json:"favicon"` Favicon string `xorm:"varchar(100)" json:"favicon"`
PasswordType string `xorm:"varchar(100)" json:"passwordType"` PasswordType string `xorm:"varchar(100)" json:"passwordType"`
PasswordSalt string `xorm:"varchar(100)" json:"passwordSalt"` PasswordSalt string `xorm:"varchar(100)" json:"passwordSalt"`
PasswordOptions []string `xorm:"varchar(100)" json:"passwordOptions"`
CountryCodes []string `xorm:"varchar(200)" json:"countryCodes"` CountryCodes []string `xorm:"varchar(200)" json:"countryCodes"`
DefaultAvatar string `xorm:"varchar(200)" json:"defaultAvatar"` DefaultAvatar string `xorm:"varchar(200)" json:"defaultAvatar"`
DefaultApplication string `xorm:"varchar(100)" json:"defaultApplication"` DefaultApplication string `xorm:"varchar(100)" json:"defaultApplication"`

View File

@ -193,6 +193,29 @@ class OrganizationEditPage extends React.Component {
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: "20px"}}>
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Password complexity options"), i18next.t("general:Password complexity options - Tooltip"))} :
</Col>
<Col span={22} >
<Select
virtual={false}
style={{width: "100%"}}
mode="multiple"
value={this.state.organization.passwordOptions}
onChange={(value => {
this.updateOrganizationField("passwordOptions", value);
})}
options={[
{value: "AtLeast6", name: i18next.t("user:The password must have at least 6 characters")},
{value: "AtLeast8", name: i18next.t("user:The password must have at least 8 characters")},
{value: "Aa123", name: i18next.t("user:The password must contain at least one uppercase letter, one lowercase letter and one digit")},
{value: "SpecialChar", name: i18next.t("user:The password must contain at least one special character")},
{value: "NoRepeat", name: i18next.t("user:The password must not contain any repeated characters")},
].map((item) => Setting.getOption(item.name, item.value))}
/>
</Col>
</Row>
<Row style={{marginTop: "20px"}} > <Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Supported country codes"), i18next.t("general:Supported country codes - Tooltip"))} : {Setting.getLabel(i18next.t("general:Supported country codes"), i18next.t("general:Supported country codes - Tooltip"))} :

View File

@ -34,6 +34,7 @@ class OrganizationListPage extends BaseListPage {
favicon: `${Setting.StaticBaseUrl}/img/favicon.png`, favicon: `${Setting.StaticBaseUrl}/img/favicon.png`,
passwordType: "plain", passwordType: "plain",
PasswordSalt: "", PasswordSalt: "",
passwordOptions: [],
countryCodes: ["CN"], countryCodes: ["CN"],
defaultAvatar: `${Setting.StaticBaseUrl}/img/casbin.svg`, defaultAvatar: `${Setting.StaticBaseUrl}/img/casbin.svg`,
defaultApplication: "", defaultApplication: "",

View File

@ -24,6 +24,8 @@ import * as UserBackend from "../backend/UserBackend";
import {CheckCircleOutlined, KeyOutlined, LockOutlined, SolutionOutlined, UserOutlined} from "@ant-design/icons"; import {CheckCircleOutlined, KeyOutlined, LockOutlined, SolutionOutlined, UserOutlined} from "@ant-design/icons";
import CustomGithubCorner from "../common/CustomGithubCorner"; import CustomGithubCorner from "../common/CustomGithubCorner";
import {withRouter} from "react-router-dom"; import {withRouter} from "react-router-dom";
import * as PasswordChecker from "../common/PasswordChecker";
const {Option} = Select; const {Option} = Select;
class ForgetPage extends React.Component { class ForgetPage extends React.Component {
@ -45,7 +47,6 @@ class ForgetPage extends React.Component {
this.form = React.createRef(); this.form = React.createRef();
} }
componentDidMount() { componentDidMount() {
if (this.getApplicationObj() === undefined) { if (this.getApplicationObj() === undefined) {
if (this.state.applicationName !== undefined) { if (this.state.applicationName !== undefined) {
@ -66,7 +67,6 @@ class ForgetPage extends React.Component {
this.onUpdateApplication(application); this.onUpdateApplication(application);
}); });
} }
getApplicationObj() { getApplicationObj() {
return this.props.application; return this.props.application;
} }
@ -378,7 +378,15 @@ class ForgetPage extends React.Component {
rules={[ rules={[
{ {
required: true, required: true,
message: i18next.t("login:Please input your password!"), validateTrigger: "onChange",
validator: (rule, value) => {
const errorMsg = PasswordChecker.checkPasswordComplexity(value, application.organizationObj.passwordOptions);
if (errorMsg === "") {
return Promise.resolve();
} else {
return Promise.reject(errorMsg);
}
},
}, },
]} ]}
hasFeedback hasFeedback

View File

@ -28,6 +28,7 @@ import CustomGithubCorner from "../common/CustomGithubCorner";
import LanguageSelect from "../common/select/LanguageSelect"; import LanguageSelect from "../common/select/LanguageSelect";
import {withRouter} from "react-router-dom"; import {withRouter} from "react-router-dom";
import {CountryCodeSelect} from "../common/select/CountryCodeSelect"; import {CountryCodeSelect} from "../common/select/CountryCodeSelect";
import * as PasswordChecker from "../common/PasswordChecker";
const formItemLayout = { const formItemLayout = {
labelCol: { labelCol: {
@ -458,8 +459,15 @@ class SignupPage extends React.Component {
rules={[ rules={[
{ {
required: required, required: required,
min: 6, validateTrigger: "onChange",
message: i18next.t("login:Please input your password, at least 6 characters!"), validator: (rule, value) => {
const errorMsg = PasswordChecker.checkPasswordComplexity(value, application.organizationObj.passwordOptions);
if (errorMsg === "") {
return Promise.resolve();
} else {
return Promise.reject(errorMsg);
}
},
}, },
]} ]}
hasFeedback hasFeedback

View File

@ -0,0 +1,82 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import i18next from "i18next";
function isValidOption_AtLeast6(password) {
if (password.length < 6) {
return i18next.t("user:The password must have at least 6 characters");
}
return "";
}
function isValidOption_AtLeast8(password) {
if (password.length < 8) {
return i18next.t("user:The password must have at least 8 characters");
}
return "";
}
function isValidOption_Aa123(password) {
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).+$/;
if (!regex.test(password)) {
return i18next.t("user:The password must contain at least one uppercase letter, one lowercase letter and one digit");
}
return "";
}
function isValidOption_SpecialChar(password) {
const regex = /^(?=.*[!@#$%^&*]).+$/;
if (!regex.test(password)) {
return i18next.t("user:The password must contain at least one special character");
}
return "";
}
function isValidOption_NoRepeat(password) {
const regex = /(.)\1+/;
if (regex.test(password)) {
return i18next.t("user:The password must not contain any repeated characters");
}
return "";
}
export function checkPasswordComplexity(password, options) {
if (password.length === 0) {
return i18next.t("login:Please input your password!");
}
if (options.length === 0) {
options = ["AtLeast6"];
}
const checkers = {
AtLeast6: isValidOption_AtLeast6,
AtLeast8: isValidOption_AtLeast8,
Aa123: isValidOption_Aa123,
SpecialChar: isValidOption_SpecialChar,
NoRepeat: isValidOption_NoRepeat,
};
for (const option of options) {
const checkerFunc = checkers[option];
if (checkerFunc) {
const errorMsg = checkerFunc(password);
if (errorMsg !== "") {
return errorMsg;
}
}
}
return "";
}

View File

@ -17,6 +17,8 @@ import i18next from "i18next";
import React from "react"; import React from "react";
import * as UserBackend from "../../backend/UserBackend"; import * as UserBackend from "../../backend/UserBackend";
import * as Setting from "../../Setting"; import * as Setting from "../../Setting";
import * as OrganizationBackend from "../../backend/OrganizationBackend";
import * as PasswordChecker from "../PasswordChecker";
export const PasswordModal = (props) => { export const PasswordModal = (props) => {
const [visible, setVisible] = React.useState(false); const [visible, setVisible] = React.useState(false);
@ -27,6 +29,26 @@ export const PasswordModal = (props) => {
const {user} = props; const {user} = props;
const {account} = props; const {account} = props;
const [passwordOptions, setPasswordOptions] = React.useState([]);
const [newPasswordValid, setNewPasswordValid] = React.useState(false);
const [rePasswordValid, setRePasswordValid] = React.useState(false);
const [newPasswordErrorMessage, setNewPasswordErrorMessage] = React.useState("");
const [rePasswordErrorMessage, setRePasswordErrorMessage] = React.useState("");
React.useEffect(() => {
OrganizationBackend.getOrganizations("admin")
.then((res) => {
const organizations = (res.msg === undefined) ? res : [];
// Find the user's corresponding organization
const organization = organizations.find((org) => org.name === user.owner);
if (organization) {
setPasswordOptions(organization.passwordOptions);
}
})
.catch((error) => {
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
});
}, [user.owner]);
const showModal = () => { const showModal = () => {
setVisible(true); setVisible(true);
}; };
@ -34,6 +56,24 @@ export const PasswordModal = (props) => {
const handleCancel = () => { const handleCancel = () => {
setVisible(false); setVisible(false);
}; };
const handleNewPassword = (value) => {
setNewPassword(value);
const errorMessage = PasswordChecker.checkPasswordComplexity(value, passwordOptions);
setNewPasswordValid(errorMessage === "");
setNewPasswordErrorMessage(errorMessage);
};
const handleRePassword = (value) => {
setRePassword(value);
if (value !== newPassword) {
setRePasswordErrorMessage(i18next.t("signup:Your confirmed password is inconsistent with the password!"));
setRePasswordValid(false);
} else {
setRePasswordValid(true);
}
};
const handleOk = () => { const handleOk = () => {
if (newPassword === "" || rePassword === "") { if (newPassword === "" || rePassword === "") {
@ -45,12 +85,44 @@ export const PasswordModal = (props) => {
return; return;
} }
setConfirmLoading(true); setConfirmLoading(true);
UserBackend.setPassword(user.owner, user.name, oldPassword, newPassword).then((res) => {
setConfirmLoading(false); OrganizationBackend.getOrganizations("admin").then((res) => {
if (res.status === "ok") { const organizations = (res.msg === undefined) ? res : [];
Setting.showMessage("success", i18next.t("user:Password set successfully"));
setVisible(false); // find the users' corresponding organization
} else {Setting.showMessage("error", i18next.t(`user:${res.msg}`));} let organization = null;
for (let i = 0; i < organizations.length; i++) {
if (organizations[i].name === user.owner) {
organization = organizations[i];
break;
}
}
if (organization === null) {
Setting.showMessage("error", "organization is null");
setConfirmLoading(false);
return;
}
const errorMsg = PasswordChecker.checkPasswordComplexity(newPassword, organization.passwordOptions);
if (errorMsg !== "") {
Setting.showMessage("error", errorMsg);
setConfirmLoading(false);
return;
}
UserBackend.setPassword(user.owner, user.name, oldPassword, newPassword)
.then((res) => {
if (res.status === "ok") {
Setting.showMessage("success", i18next.t("user:Password set successfully"));
setVisible(false);
} else {
Setting.showMessage("error", i18next.t(`user:${res.msg}`));
}
})
.finally(() => {
setConfirmLoading(false);
});
}); });
}; };
@ -79,11 +151,23 @@ export const PasswordModal = (props) => {
</Row> </Row>
) : null} ) : null}
<Row style={{width: "100%", marginBottom: "20px"}}> <Row style={{width: "100%", marginBottom: "20px"}}>
<Input.Password addonBefore={i18next.t("user:New Password")} placeholder={i18next.t("user:input password")} onChange={(e) => setNewPassword(e.target.value)} /> <Input.Password
addonBefore={i18next.t("user:New Password")}
placeholder={i18next.t("user:input password")}
onChange={(e) => {handleNewPassword(e.target.value);}}
status={(!newPasswordValid && newPasswordErrorMessage) ? "error" : undefined}
/>
</Row> </Row>
{!newPasswordValid && newPasswordErrorMessage && <div style={{color: "red", marginTop: "-20px"}}>{newPasswordErrorMessage}</div>}
<Row style={{width: "100%", marginBottom: "20px"}}> <Row style={{width: "100%", marginBottom: "20px"}}>
<Input.Password addonBefore={i18next.t("user:Re-enter New")} placeholder={i18next.t("user:input password")} onChange={(e) => setRePassword(e.target.value)} /> <Input.Password
addonBefore={i18next.t("user:Re-enter New")}
placeholder={i18next.t("user:input password")}
onChange={(e) => handleRePassword(e.target.value)}
status={(!rePasswordValid && rePasswordErrorMessage) ? "error" : undefined}
/>
</Row> </Row>
{!rePasswordValid && rePasswordErrorMessage && <div style={{color: "red", marginTop: "-20px"}}>{rePasswordErrorMessage}</div>}
</Col> </Col>
</Modal> </Modal>
</Row> </Row>

View File

@ -261,6 +261,8 @@
"Organizations": "Organisationen", "Organizations": "Organisationen",
"Password": "Passwort", "Password": "Passwort",
"Password - Tooltip": "Stellen Sie sicher, dass das Passwort korrekt ist", "Password - Tooltip": "Stellen Sie sicher, dass das Passwort korrekt ist",
"Password complexity options": "Password complexity options",
"Password complexity options - Tooltip": "Password complexity options - Tooltip",
"Password salt": "Passwort-Salt", "Password salt": "Passwort-Salt",
"Password salt - Tooltip": "Zufälliger Parameter, der für die Verschlüsselung von Passwörtern verwendet wird", "Password salt - Tooltip": "Zufälliger Parameter, der für die Verschlüsselung von Passwörtern verwendet wird",
"Password type": "Passworttyp", "Password type": "Passworttyp",
@ -394,7 +396,6 @@
"Please input your code!": "Bitte geben Sie Ihren Code ein!", "Please input your code!": "Bitte geben Sie Ihren Code ein!",
"Please input your organization name!": "Please input your organization name!", "Please input your organization name!": "Please input your organization name!",
"Please input your password!": "Bitte geben Sie Ihr Passwort ein!", "Please input your password!": "Bitte geben Sie Ihr Passwort ein!",
"Please input your password, at least 6 characters!": "Bitte geben Sie Ihr Passwort ein, es muss mindestens 6 Zeichen lang sein!",
"Please select an organization": "Please select an organization", "Please select an organization": "Please select an organization",
"Please select an organization to sign in": "Please select an organization to sign in", "Please select an organization to sign in": "Please select an organization to sign in",
"Please type an organization to sign in": "Please type an organization to sign in", "Please type an organization to sign in": "Please type an organization to sign in",
@ -938,6 +939,11 @@
"Set password...": "Passwort festlegen...", "Set password...": "Passwort festlegen...",
"Tag": "Tag", "Tag": "Tag",
"Tag - Tooltip": "Tags des Benutzers", "Tag - Tooltip": "Tags des Benutzers",
"The password must contain at least one special character": "The password must contain at least one special character",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
"The password must have at least 6 characters": "The password must have at least 6 characters",
"The password must have at least 8 characters": "The password must have at least 8 characters",
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
"Title": "Titel", "Title": "Titel",
"Title - Tooltip": "Position in der Zugehörigkeit", "Title - Tooltip": "Position in der Zugehörigkeit",
"Two passwords you typed do not match.": "Zwei von Ihnen eingegebene Passwörter stimmen nicht überein.", "Two passwords you typed do not match.": "Zwei von Ihnen eingegebene Passwörter stimmen nicht überein.",

View File

@ -261,6 +261,8 @@
"Organizations": "Organizations", "Organizations": "Organizations",
"Password": "Password", "Password": "Password",
"Password - Tooltip": "Make sure the password is correct", "Password - Tooltip": "Make sure the password is correct",
"Password complexity options": "Password complexity options",
"Password complexity options - Tooltip": "Different combinations of password complexity options",
"Password salt": "Password salt", "Password salt": "Password salt",
"Password salt - Tooltip": "Random parameter used for password encryption", "Password salt - Tooltip": "Random parameter used for password encryption",
"Password type": "Password type", "Password type": "Password type",
@ -394,7 +396,6 @@
"Please input your code!": "Please input your code!", "Please input your code!": "Please input your code!",
"Please input your organization name!": "Please input your organization name!", "Please input your organization name!": "Please input your organization name!",
"Please input your password!": "Please input your password!", "Please input your password!": "Please input your password!",
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
"Please select an organization": "Please select an organization", "Please select an organization": "Please select an organization",
"Please select an organization to sign in": "Please select an organization to sign in", "Please select an organization to sign in": "Please select an organization to sign in",
"Please type an organization to sign in": "Please type an organization to sign in", "Please type an organization to sign in": "Please type an organization to sign in",
@ -938,6 +939,11 @@
"Set password...": "Set password...", "Set password...": "Set password...",
"Tag": "Tag", "Tag": "Tag",
"Tag - Tooltip": "Tag of the user", "Tag - Tooltip": "Tag of the user",
"The password must contain at least one special character": "The password must contain at least one special character",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
"The password must have at least 6 characters": "The password must have at least 6 characters",
"The password must have at least 8 characters": "The password must have at least 8 characters",
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
"Title": "Title", "Title": "Title",
"Title - Tooltip": "Position in the affiliation", "Title - Tooltip": "Position in the affiliation",
"Two passwords you typed do not match.": "Two passwords you typed do not match.", "Two passwords you typed do not match.": "Two passwords you typed do not match.",

View File

@ -261,6 +261,8 @@
"Organizations": "Organizaciones", "Organizations": "Organizaciones",
"Password": "Contraseña", "Password": "Contraseña",
"Password - Tooltip": "Asegúrate de que la contraseña sea correcta", "Password - Tooltip": "Asegúrate de que la contraseña sea correcta",
"Password complexity options": "Password complexity options",
"Password complexity options - Tooltip": "Password complexity options - Tooltip",
"Password salt": "Sal de contraseña", "Password salt": "Sal de contraseña",
"Password salt - Tooltip": "Parámetro aleatorio utilizado para la encriptación de contraseñas", "Password salt - Tooltip": "Parámetro aleatorio utilizado para la encriptación de contraseñas",
"Password type": "Tipo de contraseña", "Password type": "Tipo de contraseña",
@ -394,7 +396,6 @@
"Please input your code!": "¡Por favor ingrese su código!", "Please input your code!": "¡Por favor ingrese su código!",
"Please input your organization name!": "Please input your organization name!", "Please input your organization name!": "Please input your organization name!",
"Please input your password!": "¡Ingrese su contraseña, por favor!", "Please input your password!": "¡Ingrese su contraseña, por favor!",
"Please input your password, at least 6 characters!": "Por favor ingrese su contraseña, ¡de al menos 6 caracteres!",
"Please select an organization": "Please select an organization", "Please select an organization": "Please select an organization",
"Please select an organization to sign in": "Please select an organization to sign in", "Please select an organization to sign in": "Please select an organization to sign in",
"Please type an organization to sign in": "Please type an organization to sign in", "Please type an organization to sign in": "Please type an organization to sign in",
@ -938,6 +939,11 @@
"Set password...": "Establecer contraseña...", "Set password...": "Establecer contraseña...",
"Tag": "Etiqueta", "Tag": "Etiqueta",
"Tag - Tooltip": "Etiqueta del usuario", "Tag - Tooltip": "Etiqueta del usuario",
"The password must contain at least one special character": "The password must contain at least one special character",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
"The password must have at least 6 characters": "The password must have at least 6 characters",
"The password must have at least 8 characters": "The password must have at least 8 characters",
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
"Title": "Título", "Title": "Título",
"Title - Tooltip": "Posición en la afiliación", "Title - Tooltip": "Posición en la afiliación",
"Two passwords you typed do not match.": "Dos contraseñas que has escrito no coinciden.", "Two passwords you typed do not match.": "Dos contraseñas que has escrito no coinciden.",

View File

@ -261,6 +261,8 @@
"Organizations": "Organisations", "Organizations": "Organisations",
"Password": "Mot de passe", "Password": "Mot de passe",
"Password - Tooltip": "Assurez-vous que le mot de passe est correct", "Password - Tooltip": "Assurez-vous que le mot de passe est correct",
"Password complexity options": "Password complexity options",
"Password complexity options - Tooltip": "Password complexity options - Tooltip",
"Password salt": "Sel de mot de passe", "Password salt": "Sel de mot de passe",
"Password salt - Tooltip": "Paramètre aléatoire utilisé pour le cryptage de mot de passe", "Password salt - Tooltip": "Paramètre aléatoire utilisé pour le cryptage de mot de passe",
"Password type": "Type de mot de passe", "Password type": "Type de mot de passe",
@ -394,7 +396,6 @@
"Please input your code!": "Veuillez entrer votre code !", "Please input your code!": "Veuillez entrer votre code !",
"Please input your organization name!": "Please input your organization name!", "Please input your organization name!": "Please input your organization name!",
"Please input your password!": "Veuillez entrer votre mot de passe !", "Please input your password!": "Veuillez entrer votre mot de passe !",
"Please input your password, at least 6 characters!": "Veuillez entrer votre mot de passe, au moins 6 caractères!",
"Please select an organization": "Please select an organization", "Please select an organization": "Please select an organization",
"Please select an organization to sign in": "Please select an organization to sign in", "Please select an organization to sign in": "Please select an organization to sign in",
"Please type an organization to sign in": "Please type an organization to sign in", "Please type an organization to sign in": "Please type an organization to sign in",
@ -938,6 +939,11 @@
"Set password...": "Définir le mot de passe...", "Set password...": "Définir le mot de passe...",
"Tag": "Étiquette", "Tag": "Étiquette",
"Tag - Tooltip": "Tag de l'utilisateur", "Tag - Tooltip": "Tag de l'utilisateur",
"The password must contain at least one special character": "The password must contain at least one special character",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
"The password must have at least 6 characters": "The password must have at least 6 characters",
"The password must have at least 8 characters": "The password must have at least 8 characters",
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
"Title": "Titre", "Title": "Titre",
"Title - Tooltip": "Position dans l'affiliation", "Title - Tooltip": "Position dans l'affiliation",
"Two passwords you typed do not match.": "Deux mots de passe que vous avez tapés ne correspondent pas.", "Two passwords you typed do not match.": "Deux mots de passe que vous avez tapés ne correspondent pas.",

View File

@ -261,6 +261,8 @@
"Organizations": "Organisasi", "Organizations": "Organisasi",
"Password": "Kata sandi", "Password": "Kata sandi",
"Password - Tooltip": "Pastikan kata sandi yang benar", "Password - Tooltip": "Pastikan kata sandi yang benar",
"Password complexity options": "Password complexity options",
"Password complexity options - Tooltip": "Password complexity options - Tooltip",
"Password salt": "Garam sandi", "Password salt": "Garam sandi",
"Password salt - Tooltip": "Parameter acak yang digunakan untuk enkripsi kata sandi", "Password salt - Tooltip": "Parameter acak yang digunakan untuk enkripsi kata sandi",
"Password type": "Jenis kata sandi", "Password type": "Jenis kata sandi",
@ -394,7 +396,6 @@
"Please input your code!": "Silakan masukkan kode Anda!", "Please input your code!": "Silakan masukkan kode Anda!",
"Please input your organization name!": "Please input your organization name!", "Please input your organization name!": "Please input your organization name!",
"Please input your password!": "Masukkan kata sandi Anda!", "Please input your password!": "Masukkan kata sandi Anda!",
"Please input your password, at least 6 characters!": "Silakan masukkan kata sandi Anda, minimal 6 karakter!",
"Please select an organization": "Please select an organization", "Please select an organization": "Please select an organization",
"Please select an organization to sign in": "Please select an organization to sign in", "Please select an organization to sign in": "Please select an organization to sign in",
"Please type an organization to sign in": "Please type an organization to sign in", "Please type an organization to sign in": "Please type an organization to sign in",
@ -938,6 +939,11 @@
"Set password...": "Tetapkan kata sandi...", "Set password...": "Tetapkan kata sandi...",
"Tag": "tanda", "Tag": "tanda",
"Tag - Tooltip": "Tag pengguna", "Tag - Tooltip": "Tag pengguna",
"The password must contain at least one special character": "The password must contain at least one special character",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
"The password must have at least 6 characters": "The password must have at least 6 characters",
"The password must have at least 8 characters": "The password must have at least 8 characters",
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
"Title": "Judul", "Title": "Judul",
"Title - Tooltip": "Posisi dalam afiliasi", "Title - Tooltip": "Posisi dalam afiliasi",
"Two passwords you typed do not match.": "Dua password yang Anda ketikkan tidak cocok.", "Two passwords you typed do not match.": "Dua password yang Anda ketikkan tidak cocok.",

View File

@ -261,6 +261,8 @@
"Organizations": "組織", "Organizations": "組織",
"Password": "パスワード", "Password": "パスワード",
"Password - Tooltip": "パスワードが正しいことを確認してください", "Password - Tooltip": "パスワードが正しいことを確認してください",
"Password complexity options": "Password complexity options",
"Password complexity options - Tooltip": "Password complexity options - Tooltip",
"Password salt": "パスワードのソルト", "Password salt": "パスワードのソルト",
"Password salt - Tooltip": "ランダムパラメーターは、パスワードの暗号化に使用されます", "Password salt - Tooltip": "ランダムパラメーターは、パスワードの暗号化に使用されます",
"Password type": "パスワードタイプ", "Password type": "パスワードタイプ",
@ -394,7 +396,6 @@
"Please input your code!": "あなたのコードを入力してください!", "Please input your code!": "あなたのコードを入力してください!",
"Please input your organization name!": "Please input your organization name!", "Please input your organization name!": "Please input your organization name!",
"Please input your password!": "パスワードを入力してください!", "Please input your password!": "パスワードを入力してください!",
"Please input your password, at least 6 characters!": "パスワードを入力してください。少なくとも6文字です",
"Please select an organization": "Please select an organization", "Please select an organization": "Please select an organization",
"Please select an organization to sign in": "Please select an organization to sign in", "Please select an organization to sign in": "Please select an organization to sign in",
"Please type an organization to sign in": "Please type an organization to sign in", "Please type an organization to sign in": "Please type an organization to sign in",
@ -938,6 +939,11 @@
"Set password...": "パスワードの設定...", "Set password...": "パスワードの設定...",
"Tag": "タグ", "Tag": "タグ",
"Tag - Tooltip": "ユーザーのタグ", "Tag - Tooltip": "ユーザーのタグ",
"The password must contain at least one special character": "The password must contain at least one special character",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
"The password must have at least 6 characters": "The password must have at least 6 characters",
"The password must have at least 8 characters": "The password must have at least 8 characters",
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
"Title": "タイトル", "Title": "タイトル",
"Title - Tooltip": "所属のポジション", "Title - Tooltip": "所属のポジション",
"Two passwords you typed do not match.": "2つのパスワードが一致しません。", "Two passwords you typed do not match.": "2つのパスワードが一致しません。",

View File

@ -261,6 +261,8 @@
"Organizations": "조직들", "Organizations": "조직들",
"Password": "비밀번호", "Password": "비밀번호",
"Password - Tooltip": "비밀번호가 올바른지 확인하세요", "Password - Tooltip": "비밀번호가 올바른지 확인하세요",
"Password complexity options": "Password complexity options",
"Password complexity options - Tooltip": "Password complexity options - Tooltip",
"Password salt": "비밀번호 솔트", "Password salt": "비밀번호 솔트",
"Password salt - Tooltip": "암호화에 사용되는 임의 매개변수", "Password salt - Tooltip": "암호화에 사용되는 임의 매개변수",
"Password type": "암호 유형", "Password type": "암호 유형",
@ -394,7 +396,6 @@
"Please input your code!": "코드를 입력해주세요!", "Please input your code!": "코드를 입력해주세요!",
"Please input your organization name!": "Please input your organization name!", "Please input your organization name!": "Please input your organization name!",
"Please input your password!": "비밀번호를 입력해주세요!", "Please input your password!": "비밀번호를 입력해주세요!",
"Please input your password, at least 6 characters!": "비밀번호를 입력해주세요. 최소 6자 이상 필요합니다!",
"Please select an organization": "Please select an organization", "Please select an organization": "Please select an organization",
"Please select an organization to sign in": "Please select an organization to sign in", "Please select an organization to sign in": "Please select an organization to sign in",
"Please type an organization to sign in": "Please type an organization to sign in", "Please type an organization to sign in": "Please type an organization to sign in",
@ -938,6 +939,11 @@
"Set password...": "비밀번호 설정...", "Set password...": "비밀번호 설정...",
"Tag": "태그", "Tag": "태그",
"Tag - Tooltip": "사용자의 태그", "Tag - Tooltip": "사용자의 태그",
"The password must contain at least one special character": "The password must contain at least one special character",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
"The password must have at least 6 characters": "The password must have at least 6 characters",
"The password must have at least 8 characters": "The password must have at least 8 characters",
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
"Title": "제목", "Title": "제목",
"Title - Tooltip": "소속 내 직위", "Title - Tooltip": "소속 내 직위",
"Two passwords you typed do not match.": "두 개의 비밀번호가 일치하지 않습니다.", "Two passwords you typed do not match.": "두 개의 비밀번호가 일치하지 않습니다.",

View File

@ -261,6 +261,8 @@
"Organizations": "Organizações", "Organizations": "Organizações",
"Password": "Senha", "Password": "Senha",
"Password - Tooltip": "Certifique-se de que a senha está correta", "Password - Tooltip": "Certifique-se de que a senha está correta",
"Password complexity options": "Password complexity options",
"Password complexity options - Tooltip": "Password complexity options - Tooltip",
"Password salt": "Salt de senha", "Password salt": "Salt de senha",
"Password salt - Tooltip": "Parâmetro aleatório usado para criptografia de senha", "Password salt - Tooltip": "Parâmetro aleatório usado para criptografia de senha",
"Password type": "Tipo de senha", "Password type": "Tipo de senha",
@ -394,7 +396,6 @@
"Please input your code!": "Por favor, informe o código!", "Please input your code!": "Por favor, informe o código!",
"Please input your organization name!": "Please input your organization name!", "Please input your organization name!": "Please input your organization name!",
"Please input your password!": "Por favor, informe sua senha!", "Please input your password!": "Por favor, informe sua senha!",
"Please input your password, at least 6 characters!": "Por favor, informe sua senha, pelo menos 6 caracteres!",
"Please select an organization": "Please select an organization", "Please select an organization": "Please select an organization",
"Please select an organization to sign in": "Please select an organization to sign in", "Please select an organization to sign in": "Please select an organization to sign in",
"Please type an organization to sign in": "Please type an organization to sign in", "Please type an organization to sign in": "Please type an organization to sign in",
@ -938,6 +939,11 @@
"Set password...": "Definir senha...", "Set password...": "Definir senha...",
"Tag": "Tag", "Tag": "Tag",
"Tag - Tooltip": "Tag do usuário", "Tag - Tooltip": "Tag do usuário",
"The password must contain at least one special character": "The password must contain at least one special character",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
"The password must have at least 6 characters": "The password must have at least 6 characters",
"The password must have at least 8 characters": "The password must have at least 8 characters",
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
"Title": "Título", "Title": "Título",
"Title - Tooltip": "Cargo na afiliação", "Title - Tooltip": "Cargo na afiliação",
"Two passwords you typed do not match.": "As duas senhas digitadas não coincidem.", "Two passwords you typed do not match.": "As duas senhas digitadas não coincidem.",

View File

@ -261,6 +261,8 @@
"Organizations": "Организации", "Organizations": "Организации",
"Password": "Пароль", "Password": "Пароль",
"Password - Tooltip": "Убедитесь, что пароль правильный", "Password - Tooltip": "Убедитесь, что пароль правильный",
"Password complexity options": "Password complexity options",
"Password complexity options - Tooltip": "Password complexity options - Tooltip",
"Password salt": "Соль пароля", "Password salt": "Соль пароля",
"Password salt - Tooltip": "Случайный параметр, используемый для шифрования пароля", "Password salt - Tooltip": "Случайный параметр, используемый для шифрования пароля",
"Password type": "Тип пароля", "Password type": "Тип пароля",
@ -394,7 +396,6 @@
"Please input your code!": "Пожалуйста, введите свой код!", "Please input your code!": "Пожалуйста, введите свой код!",
"Please input your organization name!": "Please input your organization name!", "Please input your organization name!": "Please input your organization name!",
"Please input your password!": "Пожалуйста, введите свой пароль!", "Please input your password!": "Пожалуйста, введите свой пароль!",
"Please input your password, at least 6 characters!": "Пожалуйста, введите свой пароль, длина должна быть не менее 6 символов!",
"Please select an organization": "Please select an organization", "Please select an organization": "Please select an organization",
"Please select an organization to sign in": "Please select an organization to sign in", "Please select an organization to sign in": "Please select an organization to sign in",
"Please type an organization to sign in": "Please type an organization to sign in", "Please type an organization to sign in": "Please type an organization to sign in",
@ -938,6 +939,11 @@
"Set password...": "Установить пароль...", "Set password...": "Установить пароль...",
"Tag": "Метка", "Tag": "Метка",
"Tag - Tooltip": "Тег пользователя", "Tag - Tooltip": "Тег пользователя",
"The password must contain at least one special character": "The password must contain at least one special character",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
"The password must have at least 6 characters": "The password must have at least 6 characters",
"The password must have at least 8 characters": "The password must have at least 8 characters",
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
"Title": "Заголовок", "Title": "Заголовок",
"Title - Tooltip": "Положение в аффилиации", "Title - Tooltip": "Положение в аффилиации",
"Two passwords you typed do not match.": "Два введенных вами пароля не совпадают.", "Two passwords you typed do not match.": "Два введенных вами пароля не совпадают.",

View File

@ -261,6 +261,8 @@
"Organizations": "Tổ chức", "Organizations": "Tổ chức",
"Password": "Mật khẩu", "Password": "Mật khẩu",
"Password - Tooltip": "Hãy đảm bảo rằng mật khẩu là chính xác", "Password - Tooltip": "Hãy đảm bảo rằng mật khẩu là chính xác",
"Password complexity options": "Password complexity options",
"Password complexity options - Tooltip": "Password complexity options - Tooltip",
"Password salt": "Muối mật khẩu", "Password salt": "Muối mật khẩu",
"Password salt - Tooltip": "Tham số ngẫu nhiên được sử dụng để mã hóa mật khẩu", "Password salt - Tooltip": "Tham số ngẫu nhiên được sử dụng để mã hóa mật khẩu",
"Password type": "Loại mật khẩu", "Password type": "Loại mật khẩu",
@ -394,7 +396,6 @@
"Please input your code!": "Vui lòng nhập mã của bạn!", "Please input your code!": "Vui lòng nhập mã của bạn!",
"Please input your organization name!": "Please input your organization name!", "Please input your organization name!": "Please input your organization name!",
"Please input your password!": "Vui lòng nhập mật khẩu của bạn!", "Please input your password!": "Vui lòng nhập mật khẩu của bạn!",
"Please input your password, at least 6 characters!": "Vui lòng nhập mật khẩu của bạn, ít nhất 6 ký tự!",
"Please select an organization": "Please select an organization", "Please select an organization": "Please select an organization",
"Please select an organization to sign in": "Please select an organization to sign in", "Please select an organization to sign in": "Please select an organization to sign in",
"Please type an organization to sign in": "Please type an organization to sign in", "Please type an organization to sign in": "Please type an organization to sign in",
@ -938,6 +939,11 @@
"Set password...": "Đặt mật khẩu...", "Set password...": "Đặt mật khẩu...",
"Tag": "Thẻ", "Tag": "Thẻ",
"Tag - Tooltip": "Thẻ của người dùng", "Tag - Tooltip": "Thẻ của người dùng",
"The password must contain at least one special character": "The password must contain at least one special character",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
"The password must have at least 6 characters": "The password must have at least 6 characters",
"The password must have at least 8 characters": "The password must have at least 8 characters",
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
"Title": "Tiêu đề", "Title": "Tiêu đề",
"Title - Tooltip": "Vị trí trong tổ chức", "Title - Tooltip": "Vị trí trong tổ chức",
"Two passwords you typed do not match.": "Hai mật khẩu mà bạn đã nhập không khớp.", "Two passwords you typed do not match.": "Hai mật khẩu mà bạn đã nhập không khớp.",

View File

@ -261,6 +261,8 @@
"Organizations": "组织", "Organizations": "组织",
"Password": "密码", "Password": "密码",
"Password - Tooltip": "请确认密码正确", "Password - Tooltip": "请确认密码正确",
"Password complexity options": "密码复杂度选项",
"Password complexity options - Tooltip": "密码复杂度组合,登录密码复杂度必须符合该规范",
"Password salt": "密码Salt值", "Password salt": "密码Salt值",
"Password salt - Tooltip": "用于密码加密的随机参数", "Password salt - Tooltip": "用于密码加密的随机参数",
"Password type": "密码类型", "Password type": "密码类型",
@ -394,7 +396,6 @@
"Please input your code!": "请输入您的验证码!", "Please input your code!": "请输入您的验证码!",
"Please input your organization name!": "请输入组织的名字!", "Please input your organization name!": "请输入组织的名字!",
"Please input your password!": "请输入您的密码!", "Please input your password!": "请输入您的密码!",
"Please input your password, at least 6 characters!": "请输入您的密码不少于6位",
"Please select an organization": "请选择一个组织", "Please select an organization": "请选择一个组织",
"Please select an organization to sign in": "请选择要登录的组织", "Please select an organization to sign in": "请选择要登录的组织",
"Please type an organization to sign in": "请输入要登录的组织", "Please type an organization to sign in": "请输入要登录的组织",
@ -938,6 +939,11 @@
"Set password...": "设置密码...", "Set password...": "设置密码...",
"Tag": "标签", "Tag": "标签",
"Tag - Tooltip": "用户的标签", "Tag - Tooltip": "用户的标签",
"The password must contain at least one special character": "密码必须包含至少一个特殊字符",
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "密码必须包含至少一个大写字母、一个小写字母和一个数字",
"The password must have at least 6 characters": "密码长度必须至少为6个字符",
"The password must have at least 8 characters": "密码长度必须至少为8个字符",
"The password must not contain any repeated characters": "密码不得包含任何重复字符",
"Title": "职务", "Title": "职务",
"Title - Tooltip": "在工作单位担任的职务", "Title - Tooltip": "在工作单位担任的职务",
"Two passwords you typed do not match.": "两次输入的密码不匹配。", "Two passwords you typed do not match.": "两次输入的密码不匹配。",