diff --git a/frontend/src/components/Inputs/InputPasswordConfirmation.vue b/frontend/src/components/Inputs/InputPasswordConfirmation.vue index 19d4ab02e..ecb3aa55a 100644 --- a/frontend/src/components/Inputs/InputPasswordConfirmation.vue +++ b/frontend/src/components/Inputs/InputPasswordConfirmation.vue @@ -9,6 +9,8 @@ containsUppercaseCharacter: true, containsNumericCharacter: true, atLeastEightCharactera: true, + atLeastOneSpecialCharater: true, + noWhitespaceCharacters: true, }" :label="register ? $t('form.password') : $t('form.password_new')" :showAllErrors="true" diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 2842a6a39..468c88f85 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -170,7 +170,9 @@ "dont_match": "Die Passwörter stimmen nicht überein.", "lowercase": "Ein Kleinbuchstabe erforderlich.", "minimum": "Mindestens 8 Zeichen.", + "no-whitespace": "Keine Leerzeichen und Tabulatoren", "one_number": "Eine Zahl erforderlich.", + "special-char": "Ein Sonderzeichen erforderlich (z.B. _ oder ä)", "subtitle": "Werde Teil der Gemeinschaft!", "title": "Erstelle dein Gradido-Konto", "uppercase": "Ein Großbuchstabe erforderlich." diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 90faa6b33..05ce82b7b 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -170,7 +170,9 @@ "dont_match": "Passwords don't match.", "lowercase": "One lowercase letter required.", "minimum": "8 characters minimum.", + "no-whitespace": "No white spaces and tabs", "one_number": "One number required.", + "special-char": "One special character required (e.g. _ or ä)", "subtitle": "Become a part of the community!", "title": "Create your Gradido account", "uppercase": "One uppercase letter required." diff --git a/frontend/src/validation-rules.js b/frontend/src/validation-rules.js index da4e07b78..9ea954a92 100644 --- a/frontend/src/validation-rules.js +++ b/frontend/src/validation-rules.js @@ -112,6 +112,20 @@ export const loadAllRules = (i18nCallback) => { message: (_, values) => i18nCallback.t('site.signup.minimum', values), }) + extend('atLeastOneSpecialCharater', { + validate(value) { + return !!value.match(/[^a-zA-Z0-9]/) + }, + message: (_, values) => i18nCallback.t('site.signup.special-char', values), + }) + + extend('noWhitespaceCharacters', { + validate(value) { + return !!value.match(/[^ \t\n\r]/) + }, + message: (_, values) => i18nCallback.t('site.signup.no-whitespace', values), + }) + extend('samePassword', { validate(value, [pwd]) { return value === pwd diff --git a/frontend/src/views/Pages/Register.spec.js b/frontend/src/views/Pages/Register.spec.js index 1a266606b..8c00d5bd6 100644 --- a/frontend/src/views/Pages/Register.spec.js +++ b/frontend/src/views/Pages/Register.spec.js @@ -132,8 +132,8 @@ describe('Register', () => { wrapper.find('#registerFirstname').setValue('Max') wrapper.find('#registerLastname').setValue('Mustermann') wrapper.find('#Email-input-field').setValue('max.mustermann@gradido.net') - wrapper.find('input[name="form.password"]').setValue('Aa123456') - wrapper.find('input[name="form.passwordRepeat"]').setValue('Aa123456') + wrapper.find('input[name="form.password"]').setValue('Aa123456_') + wrapper.find('input[name="form.passwordRepeat"]').setValue('Aa123456_') wrapper.find('.language-switch-select').findAll('option').at(1).setSelected() wrapper.find('input[name="site.signup.agree"]').setChecked(true) }) @@ -186,8 +186,8 @@ describe('Register', () => { wrapper.find('#registerFirstname').setValue('Max') wrapper.find('#registerLastname').setValue('Mustermann') wrapper.find('#Email-input-field').setValue('max.mustermann@gradido.net') - wrapper.find('input[name="form.password"]').setValue('Aa123456') - wrapper.find('input[name="form.passwordRepeat"]').setValue('Aa123456') + wrapper.find('input[name="form.password"]').setValue('Aa123456_') + wrapper.find('input[name="form.passwordRepeat"]').setValue('Aa123456_') wrapper.find('.language-switch-select').findAll('option').at(1).setSelected() }) @@ -234,7 +234,7 @@ describe('Register', () => { email: 'max.mustermann@gradido.net', firstName: 'Max', lastName: 'Mustermann', - password: 'Aa123456', + password: 'Aa123456_', language: 'de', }, }), diff --git a/frontend/src/views/Pages/ResetPassword.spec.js b/frontend/src/views/Pages/ResetPassword.spec.js index 87198ba62..94be6df53 100644 --- a/frontend/src/views/Pages/ResetPassword.spec.js +++ b/frontend/src/views/Pages/ResetPassword.spec.js @@ -140,8 +140,8 @@ describe('ResetPassword', () => { beforeEach(async () => { await wrapper.setData({ authenticated: true, sessionId: 1 }) await wrapper.vm.$nextTick() - await wrapper.findAll('input').at(0).setValue('Aa123456') - await wrapper.findAll('input').at(1).setValue('Aa123456') + await wrapper.findAll('input').at(0).setValue('Aa123456_') + await wrapper.findAll('input').at(1).setValue('Aa123456_') await flushPromises() await wrapper.find('form').trigger('submit') }) @@ -169,7 +169,7 @@ describe('ResetPassword', () => { variables: { sessionId: 1, email: 'user@example.org', - password: 'Aa123456', + password: 'Aa123456_', }, }), ) diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.spec.js b/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.spec.js index dcce66b7f..1b5c97e72 100644 --- a/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.spec.js +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.spec.js @@ -105,12 +105,14 @@ describe('UserCard_FormUserPasswort', () => { describe('validation', () => { it('displays all password requirements', () => { const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') - expect(feedbackArray).toHaveLength(5) + expect(feedbackArray).toHaveLength(7) expect(feedbackArray.at(0).text()).toBe('validations.messages.required') expect(feedbackArray.at(1).text()).toBe('site.signup.lowercase') expect(feedbackArray.at(2).text()).toBe('site.signup.uppercase') expect(feedbackArray.at(3).text()).toBe('site.signup.one_number') expect(feedbackArray.at(4).text()).toBe('site.signup.minimum') + expect(feedbackArray.at(5).text()).toBe('site.signup.special-char') + expect(feedbackArray.at(6).text()).toBe('site.signup.no-whitespace') }) it('removes first message when a character is given', async () => { @@ -125,7 +127,7 @@ describe('UserCard_FormUserPasswort', () => { await wrapper.findAll('input').at(1).setValue('a') await flushPromises() const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') - expect(feedbackArray).toHaveLength(3) + expect(feedbackArray).toHaveLength(4) expect(feedbackArray.at(0).text()).toBe('site.signup.uppercase') }) @@ -133,7 +135,7 @@ describe('UserCard_FormUserPasswort', () => { await wrapper.findAll('input').at(1).setValue('Aa') await flushPromises() const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') - expect(feedbackArray).toHaveLength(2) + expect(feedbackArray).toHaveLength(3) expect(feedbackArray.at(0).text()).toBe('site.signup.one_number') }) @@ -141,14 +143,22 @@ describe('UserCard_FormUserPasswort', () => { await wrapper.findAll('input').at(1).setValue('Aa1') await flushPromises() const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') - expect(feedbackArray).toHaveLength(1) + expect(feedbackArray).toHaveLength(2) expect(feedbackArray.at(0).text()).toBe('site.signup.minimum') }) - it('removes all messages when all rules are fulfilled', async () => { + it('removes the first five messages when a eight lowercase, uppercase and numeric characters are given', async () => { await wrapper.findAll('input').at(1).setValue('Aa123456') await flushPromises() const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') + expect(feedbackArray).toHaveLength(1) + expect(feedbackArray.at(0).text()).toBe('site.signup.special-char') + }) + + it('removes all messages when a eight lowercase, uppercase and numeric characters are given', async () => { + await wrapper.findAll('input').at(1).setValue('Aa123456_') + await flushPromises() + const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') expect(feedbackArray).toHaveLength(0) }) }) @@ -164,8 +174,8 @@ describe('UserCard_FormUserPasswort', () => { }, }) await form.findAll('input').at(0).setValue('1234') - await form.findAll('input').at(1).setValue('Aa123456') - await form.findAll('input').at(2).setValue('Aa123456') + await form.findAll('input').at(1).setValue('Aa123456_') + await form.findAll('input').at(2).setValue('Aa123456_') await form.trigger('submit') await flushPromises() }) @@ -176,7 +186,7 @@ describe('UserCard_FormUserPasswort', () => { variables: { email: 'user@example.org', password: '1234', - passwordNew: 'Aa123456', + passwordNew: 'Aa123456_', }, }), ) @@ -197,8 +207,8 @@ describe('UserCard_FormUserPasswort', () => { message: 'error', }) await form.findAll('input').at(0).setValue('1234') - await form.findAll('input').at(1).setValue('Aa123456') - await form.findAll('input').at(2).setValue('Aa123456') + await form.findAll('input').at(1).setValue('Aa123456_') + await form.findAll('input').at(2).setValue('Aa123456_') await form.trigger('submit') await flushPromises() }) diff --git a/login_server/src/LOCALE/de_DE.mo b/login_server/src/LOCALE/de_DE.mo index bfee8efd3..d3d2c86e9 100644 Binary files a/login_server/src/LOCALE/de_DE.mo and b/login_server/src/LOCALE/de_DE.mo differ diff --git a/login_server/src/LOCALE/de_DE.po b/login_server/src/LOCALE/de_DE.po index b4bca3098..b9eea0d59 100644 --- a/login_server/src/LOCALE/de_DE.po +++ b/login_server/src/LOCALE/de_DE.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-06-21 13:37+0200\n" -"PO-Revision-Date: 2021-06-21 13:38+0200\n" +"POT-Creation-Date: 2021-09-23 17:56+0200\n" +"PO-Revision-Date: 2021-09-27 13:31+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: de_DE\n" @@ -455,11 +455,10 @@ msgstr "Gradido: Passwort zurücksetzen" #: src/cpp/SingletonManager/SessionManager.cpp:604 msgid "" "Please enter a valid password with at least 8 characters, upper and lower " -"case letters, at least one number and one special character (@$!%*?&+-_)!" +"case letters, at least one number and one special character!" msgstr "" "Bitte gebe ein gültiges Password ein mit mindestens 8 Zeichen, Groß- und " -"Kleinbuchstaben, mindestens einer Zahl und einem Sonderzeichen (@$!%*?&+-_) " -"ein!" +"Kleinbuchstaben, mindestens einer Zahl und einem Sonderzeichen!" #: src/cpp/SingletonManager/SessionManager.cpp:610 msgid "Your password is to short!" @@ -478,8 +477,8 @@ msgid "Your password does not contain any number!" msgstr "Dein Passwort enthält keine Zahlen!" #: src/cpp/SingletonManager/SessionManager.cpp:630 -msgid "Your password does not contain special characters (@$!%*?&+-)!" -msgstr "Dein Passwort enthält keine Sonderzeichen (@$!%*?&+-)!" +msgid "Your password does not contain special characters!" +msgstr "Dein Passwort enthält keine Sonderzeichen!" #~ msgid "Account" #~ msgstr "Konto" diff --git a/login_server/src/cpp/SingletonManager/SessionManager.cpp b/login_server/src/cpp/SingletonManager/SessionManager.cpp index d854c2a97..c4039b10d 100644 --- a/login_server/src/cpp/SingletonManager/SessionManager.cpp +++ b/login_server/src/cpp/SingletonManager/SessionManager.cpp @@ -46,22 +46,22 @@ bool SessionManager::init() case VALIDATE_NAME: mValidations[i] = new Poco::RegularExpression("^[^<>&;]{2,}$"); break; case VALIDATE_USERNAME: mValidations[i] = new Poco::RegularExpression("^[a-zA-Z][a-zA-Z0-9_-]*$"); break; case VALIDATE_EMAIL: mValidations[i] = new Poco::RegularExpression("^[a-zA-Z0-9.!#$%&?*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$"); break; - case VALIDATE_PASSWORD: mValidations[i] = new Poco::RegularExpression("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[@$!%*?&+-_])[A-Za-z0-9@$!%*?&+-_]{8,}$"); break; + case VALIDATE_PASSWORD: mValidations[i] = new Poco::RegularExpression("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^a-zA-Z0-9 \\t\\n\\r]).{8,}$"); break; case VALIDATE_PASSPHRASE: mValidations[i] = new Poco::RegularExpression("^(?:[a-z]* ){23}[a-z]*\s*$"); break; case VALIDATE_GROUP_ALIAS: mValidations[i] = new Poco::RegularExpression("^[a-z0-9-]{3,120}"); break; case VALIDATE_HEDERA_ID: mValidations[i] = new Poco::RegularExpression("^[0-9]*\.[0-9]*\.[0-9]\.$"); break; - case VALIDATE_HAS_NUMBER: mValidations[i] = new Poco::RegularExpression(".*[0-9].*"); break; + case VALIDATE_HAS_NUMBER: mValidations[i] = new Poco::RegularExpression("[0-9]"); break; case VALIDATE_ONLY_INTEGER: mValidations[i] = new Poco::RegularExpression("^[0-9]*$"); break; case VALIDATE_ONLY_DECIMAL: mValidations[i] = new Poco::RegularExpression("^[0-9]*(\.|,)[0-9]*$"); break; case VALIDATE_ONLY_HEX: mValidations[i] = new Poco::RegularExpression("^(0x)?[a-fA-F0-9]*$"); break; //case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}$"); break; case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\/?"); break; - case VALIDATE_HAS_SPECIAL_CHARACTER: mValidations[i] = new Poco::RegularExpression(".*[@$!%*?&+-].*"); break; + case VALIDATE_HAS_SPECIAL_CHARACTER: mValidations[i] = new Poco::RegularExpression("[^a-zA-Z0-9 \\t\\n\\r]"); break; case VALIDATE_HAS_UPPERCASE_LETTER: - mValidations[i] = new Poco::RegularExpression(".*[A-Z].*"); + mValidations[i] = new Poco::RegularExpression("[A-Z]"); ServerConfig::g_ServerKeySeed->put(i, DRRandom::r64()); break; - case VALIDATE_HAS_LOWERCASE_LETTER: mValidations[i] = new Poco::RegularExpression(".*[a-z].*"); break; + case VALIDATE_HAS_LOWERCASE_LETTER: mValidations[i] = new Poco::RegularExpression("[a-z]"); break; default: printf("[SessionManager::%s] unknown validation type\n", __FUNCTION__); } } @@ -601,7 +601,7 @@ bool SessionManager::checkPwdValidation(const std::string& pwd, NotificationList if (!isValid(pwd, VALIDATE_PASSWORD)) { errorReciver->addError(new Error( lang->gettext("Password"), - lang->gettext("Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character (@$!%*?&+-_)!"))); + lang->gettext("Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!"))); // @$!%*?&+- if (pwd.size() < 8) { @@ -627,7 +627,7 @@ bool SessionManager::checkPwdValidation(const std::string& pwd, NotificationList else if (!isValid(pwd, VALIDATE_HAS_SPECIAL_CHARACTER)) { errorReciver->addError(new Error( lang->gettext("Password"), - lang->gettext("Your password does not contain special characters (@$!%*?&+-)!"))); + lang->gettext("Your password does not contain special characters!"))); } return false; diff --git a/login_server/src/cpsp/UserUpdatePassword.cpsp b/login_server/src/cpsp/UserUpdatePassword.cpsp index 04d1e487e..260a29475 100644 --- a/login_server/src/cpsp/UserUpdatePassword.cpsp +++ b/login_server/src/cpsp/UserUpdatePassword.cpsp @@ -85,7 +85,7 @@ enum PageState {

Bitte denke dir ein sicheres Passwort aus, das mindestens 8 Zeichen lang ist, einen Klein- und einen Großbuchstaben enthält, - eine Zahl und eines der folgenden Sonderzeichen: @$!%*?&+- + eine Zahl und ein Sonderzeichen.