diff --git a/dev/App/Abstract.js b/dev/App/Abstract.js index 487ff90c6..c4d0f930b 100644 --- a/dev/App/Abstract.js +++ b/dev/App/Abstract.js @@ -48,14 +48,6 @@ export class AbstractApp { return true; } - /** - * @param {string} token - */ - setClientSideToken(token) { - rl.hash.set(); - Settings.set('AuthAccountHash', token); - } - logoutReload(close = false) { const url = logoutLink(); diff --git a/dev/Common/Enums.js b/dev/Common/Enums.js index 27ee8149d..916ed3aaf 100644 --- a/dev/Common/Enums.js +++ b/dev/Common/Enums.js @@ -98,10 +98,10 @@ export const Notification = { AccountTwoFactorAuthRequired: 120, AccountTwoFactorAuthError: 121, -// CurrentPasswordIncorrect: 131, -// NewPasswordShort: 132, -// NewPasswordWeak: 133, -// NewPasswordForbidden: 134, + CouldNotSaveNewPassword: 130, + CurrentPasswordIncorrect: 131, + NewPasswordShort: 132, + NewPasswordWeak: 133, ContactsSyncError: 140, diff --git a/dev/Remote/User/Fetch.js b/dev/Remote/User/Fetch.js index 5c9777031..c02954f91 100644 --- a/dev/Remote/User/Fetch.js +++ b/dev/Remote/User/Fetch.js @@ -594,6 +594,18 @@ class RemoteUserFetch extends AbstractFetchRemote { }; } + /** + * @param {?Function} fCallback + * @param {string} prevPassword + * @param {string} newPassword + */ + changePassword(fCallback, prevPassword, newPassword) { + this.defaultRequest(fCallback, 'ChangePassword', { + 'PrevPassword': prevPassword, + 'NewPassword': newPassword + }); + } + /** * @param {?Function} fCallback * @param {string} sFolderFullNameRaw diff --git a/dev/Screen/User/Settings.js b/dev/Screen/User/Settings.js index 75bf6c026..918c067a9 100644 --- a/dev/Screen/User/Settings.js +++ b/dev/Screen/User/Settings.js @@ -18,6 +18,7 @@ import { TemplatesUserSettings } from 'Settings/User/Templates'; import { FoldersUserSettings } from 'Settings/User/Folders'; import { ThemesUserSettings } from 'Settings/User/Themes'; import { OpenPgpUserSettings } from 'Settings/User/OpenPgp'; +import { ChangePasswordUserSettings } from 'Settings/User/ChangePassword'; import { SystemDropDownSettingsUserView } from 'View/User/Settings/SystemDropDown'; import { MenuSettingsUserView } from 'View/User/Settings/Menu'; @@ -77,6 +78,15 @@ export class SettingsUserScreen extends AbstractSettingsScreen { ); } + if (Settings.get('ChangePasswordIsAllowed')) { + settingsAddViewModel( + ChangePasswordUserSettings, + 'SettingsChangePassword', + 'GLOBAL/PASSWORD', + 'change-password' + ); + } + if (Settings.capa(Capa.Folders)) { settingsAddViewModel(FoldersUserSettings, 'SettingsFolders', 'SETTINGS_LABELS/LABEL_FOLDERS_NAME', 'folders'); } diff --git a/dev/Settings/User/ChangePassword.js b/dev/Settings/User/ChangePassword.js new file mode 100644 index 000000000..4ab2bac95 --- /dev/null +++ b/dev/Settings/User/ChangePassword.js @@ -0,0 +1,90 @@ +import ko from 'ko'; + +import { StorageResultType, Notification } from 'Common/Enums'; +import { getNotificationFromResponse, i18n } from 'Common/Translator'; +import { Settings } from 'Common/Globals'; + +import Remote from 'Remote/User/Fetch'; + +import { decorateKoCommands } from 'Knoin/Knoin'; + +export class ChangePasswordUserSettings { + constructor() { + ko.addObservablesTo(this, { + changeProcess: false, + + errorDescription: '', + passwordMismatch: false, + passwordUpdateError: false, + passwordUpdateSuccess: false, + + currentPassword: '', + currentPasswordError: false, + newPassword: '', + newPassword2: '', + }); + + this.currentPassword.subscribe(() => this.resetUpdate(true)); + this.newPassword.subscribe(() => this.resetUpdate()); + this.newPassword2.subscribe(() => this.resetUpdate()); + + decorateKoCommands(this, { + saveNewPasswordCommand: self => !self.changeProcess() + && '' !== self.currentPassword() + && '' !== self.newPassword() + && '' !== self.newPassword2() + }); + } + + saveNewPasswordCommand() { + if (this.newPassword() !== this.newPassword2()) { + this.passwordMismatch(true); + this.errorDescription(i18n('SETTINGS_CHANGE_PASSWORD/ERROR_PASSWORD_MISMATCH')); + } else { + this.reset(true); + Remote.changePassword(this.onChangePasswordResponse.bind(this), this.currentPassword(), this.newPassword()); + } + } + + reset(change) { + this.changeProcess(change); + this.resetUpdate(); + this.currentPasswordError(false); + this.errorDescription(''); + } + + resetUpdate(current) { + this.passwordUpdateError(false); + this.passwordUpdateSuccess(false); + current ? this.currentPasswordError(false) : this.passwordMismatch(false); + } + + onHide() { + this.reset(false); + this.currentPassword(''); + this.newPassword(''); + this.newPassword2(''); + } + + onChangePasswordResponse(result, data) { + this.reset(false); + + if (StorageResultType.Success === result && data && data.Result) { + this.currentPassword(''); + this.newPassword(''); + this.newPassword2(''); + + this.passwordUpdateSuccess(true); + + rl.hash.set(); + Settings.set('AuthAccountHash', data.Result); + } else { + if (data && Notification.CurrentPasswordIncorrect === data.ErrorCode) { + this.currentPasswordError(true); + } + + this.passwordUpdateError(true); + this.errorDescription(getNotificationFromResponse(data, Notification.CouldNotSaveNewPassword)); + } + } +} diff --git a/plugins/change-password-example/ChangePasswordExampleDriver.php b/plugins/change-password-example/ChangePasswordExampleDriver.php new file mode 100644 index 000000000..884a31932 --- /dev/null +++ b/plugins/change-password-example/ChangePasswordExampleDriver.php @@ -0,0 +1,36 @@ +sAllowedEmails = $sAllowedEmails; + return $this; + } + + public function isPossible(\RainLoop\Model\Account $oAccount) : bool + { + $sFoundedValue = ''; + return $oAccount && $oAccount->Email() && + \RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails, $sFoundedValue); + } + + public function ChangePassword(\RainLoop\Model\Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool + { + $bResult = false; + + // TODO + + return $bResult; + } +} diff --git a/plugins/change-password-example/LICENSE b/plugins/change-password-example/LICENSE new file mode 100644 index 000000000..271342337 --- /dev/null +++ b/plugins/change-password-example/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 RainLoop Team + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/plugins/change-password-example/index.php b/plugins/change-password-example/index.php new file mode 100644 index 000000000..1f3f2783e --- /dev/null +++ b/plugins/change-password-example/index.php @@ -0,0 +1,49 @@ +addHook('main.fabrica', 'MainFabrica'); + } + + /** + * @param string $sName + * @param mixed $oProvider + */ + public function MainFabrica($sName, &$oProvider) + { + switch ($sName) + { + case 'change-password': + + include_once __DIR__.'/ChangePasswordExampleDriver.php'; + + $oProvider = new ChangePasswordExampleDriver(); + $oProvider->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', '')))); + + break; + } + } + + /** + * @return array + */ + public function configMapping() : array + { + return array( + \RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) + ->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net') + ->SetDefaultValue('*') + ); + } +} diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index 2fa65c6fb..8a305d2eb 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -12,6 +12,7 @@ class Actions use Actions\User; use Actions\Raw; use Actions\Response; + use Actions\ChangePassword; const AUTH_TFA_SIGN_ME_TOKEN_KEY = 'rltfasmauth'; const AUTH_SIGN_ME_TOKEN_KEY = 'rlsmauth'; @@ -1064,6 +1065,7 @@ class Actions 'StartupUrl' => \trim(\ltrim(\trim($oConfig->Get('labs', 'startup_url', '')), '#/')), 'SieveAllowFileintoInbox' => (bool)$oConfig->Get('labs', 'sieve_allow_fileinto_inbox', false), 'ContactsIsAllowed' => false, + 'ChangePasswordIsAllowed' => false, 'RequireTwoFactor' => false, 'Admin' => array(), 'Capa' => array(), @@ -1115,6 +1117,7 @@ class Actions $aResult['OutLogin'] = $oAccount->OutLogin(); $aResult['AccountHash'] = $oAccount->Hash(); $aResult['AccountSignMe'] = $oAccount->SignMe(); + $aResult['ChangePasswordIsAllowed'] = $this->ChangePasswordProvider()->isPossible($oAccount); $aResult['ContactsIsAllowed'] = $oAddressBookProvider->IsActive(); $aResult['ContactsSyncIsAllowed'] = (bool)$oConfig->Get('contacts', 'allow_sync', false); $aResult['ContactsSyncInterval'] = (int)$oConfig->Get('contacts', 'sync_interval', 20); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/ChangePassword.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/ChangePassword.php new file mode 100644 index 000000000..9598c1db1 --- /dev/null +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/ChangePassword.php @@ -0,0 +1,48 @@ +oChangePasswordProvider) { + $this->oChangePasswordProvider = new \RainLoop\Providers\ChangePassword( + $this, $this->fabrica('change-password'), !!$this->Config()->Get('labs', 'check_new_password_strength') + ); + } + + return $this->oChangePasswordProvider; + } + + public function DoChangePassword() : array + { + $mResult = false; + + if ($oAccount = $this->getAccountFromToken()) { + try + { + $mResult = $this->ChangePasswordProvider()->ChangePassword( + $oAccount, + $this->GetActionParam('PrevPassword', ''), + $this->GetActionParam('NewPassword', '') + ); + } + catch (\Throwable $oException) + { + $this->loginErrorDelay(); + $this->Logger()->Write('Error: Can\'t change password for '.$oAccount->Email().' account.', \MailSo\Log\Enumerations\Type::NOTICE); + + throw $oException; + } + } + + return $this->DefaultResponse(__FUNCTION__, $mResult); + } + +} diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Notifications.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Notifications.php index b0258105c..ed8443242 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Notifications.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Notifications.php @@ -13,10 +13,10 @@ class Notifications const AccountTwoFactorAuthRequired = 120; const AccountTwoFactorAuthError = 121; -// const CurrentPasswordIncorrect = 131; -// const NewPasswordShort = 132; -// const NewPasswordWeak = 133; -// const NewPasswordForbidden = 134; + const CouldNotSaveNewPassword = 130; + const CurrentPasswordIncorrect = 131; + const NewPasswordShort = 132; + const NewPasswordWeak = 133; const ContactsSyncError = 140; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/ChangePassword.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/ChangePassword.php new file mode 100644 index 000000000..f247fe41a --- /dev/null +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/ChangePassword.php @@ -0,0 +1,71 @@ +oActions = $oActions; + $this->oDriver = $oDriver; + $this->bCheckWeak = $bCheckWeak; + } + + public function isPossible(Account $oAccount) : bool + { + return $this->IsActive() && $this->oDriver->isPossible($oAccount); + } + + public function ChangePassword(Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool + { + if (!$this->isPossible($oAccount)) { + throw new ClientException(Notifications::CouldNotSaveNewPassword); + } + + if ($sPrevPassword !== $oAccount->Password()) { + throw new ClientException(Notifications::CurrentPasswordIncorrect); + } + + $sPasswordForCheck = \trim($sNewPassword); + if (10 > \strlen($sPasswordForCheck)) { + throw new ClientException(Notifications::NewPasswordShort); + } + + if ($this->bCheckWeak && !\MailSo\Base\Utils::PasswordWeaknessCheck($sPasswordForCheck)) { + throw new ClientException(Notifications::NewPasswordWeak); + } + + if (!$this->oDriver->ChangePassword($oAccount, $sPrevPassword, $sNewPassword)) { + throw new ClientException(Notifications::CouldNotSaveNewPassword); + } + + $oAccount->SetPassword($sNewPassword); + $this->oActions->SetAuthToken($oAccount); + + return $this->oActions->GetSpecAuthToken(); + } + + public function IsActive() : bool + { + return $this->oDriver instanceof ChangePassword\ChangePasswordInterface; + } +} diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php new file mode 100644 index 000000000..4d4c66c63 --- /dev/null +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php @@ -0,0 +1,10 @@ +Logger()->AddSecret($this->oActions->GetActionParam('Password', '')); break; + case 'DoChangePassword': + $this->Logger()->AddSecret($this->oActions->GetActionParam('PrevPassword', '')); + $this->Logger()->AddSecret($this->oActions->GetActionParam('NewPassword', '')); + break; } $this->Logger()->Write(\MailSo\Base\Utils::Php2js($aPost, $this->Logger()), diff --git a/snappymail/v/0.0.0/app/localization/admin/_source.en.yml b/snappymail/v/0.0.0/app/localization/admin/_source.en.yml index b108fda69..ca93094da 100644 --- a/snappymail/v/0.0.0/app/localization/admin/_source.en.yml +++ b/snappymail/v/0.0.0/app/localization/admin/_source.en.yml @@ -174,7 +174,6 @@ en: CURRENT_PASSWORD_INCORRECT: "Current password incorrect" NEW_PASSWORD_SHORT: "Password is too short" NEW_PASSWORD_WEAK: "Password is too easy" - NEW_PASSWORD_FORBIDDEN: "Password contains forbidden characters" CONTACTS_SYNC_ERROR: "Contacts synchronization error" CANT_GET_MESSAGE_LIST: "Can't get message list" CANT_GET_MESSAGE: "Can't get message" diff --git a/snappymail/v/0.0.0/app/localization/admin/de_DE.yml b/snappymail/v/0.0.0/app/localization/admin/de_DE.yml index c399cb3eb..6329b82b7 100644 --- a/snappymail/v/0.0.0/app/localization/admin/de_DE.yml +++ b/snappymail/v/0.0.0/app/localization/admin/de_DE.yml @@ -170,7 +170,6 @@ de_DE: CURRENT_PASSWORD_INCORRECT: "Aktuelles Passwort falsch" NEW_PASSWORD_SHORT: "Passwort ist zu kurz" NEW_PASSWORD_WEAK: "Passwort ist zu einfach" - NEW_PASSWORD_FORBIDDEN: "Passwort enthält unzulässige Zeichen" CONTACTS_SYNC_ERROR: "Fehler bei Kontakte-Synchronisierung" CANT_GET_MESSAGE_LIST: "Die Nachrichtenliste ist nicht verfügbar" CANT_GET_MESSAGE: "Diese Nachricht ist nicht verfügbar" diff --git a/snappymail/v/0.0.0/app/localization/admin/en_US.yml b/snappymail/v/0.0.0/app/localization/admin/en_US.yml index 4311f9faa..fd5bf6eba 100644 --- a/snappymail/v/0.0.0/app/localization/admin/en_US.yml +++ b/snappymail/v/0.0.0/app/localization/admin/en_US.yml @@ -171,7 +171,6 @@ en_US: CURRENT_PASSWORD_INCORRECT: "Current password incorrect" NEW_PASSWORD_SHORT: "Password is too short" NEW_PASSWORD_WEAK: "Password is too easy" - NEW_PASSWORD_FORBIDDEN: "Password contains forbidden characters" CONTACTS_SYNC_ERROR: "Contacts synchronization error" CANT_GET_MESSAGE_LIST: "Can't get message list" CANT_GET_MESSAGE: "Can't get message" diff --git a/snappymail/v/0.0.0/app/localization/admin/es_ES.yml b/snappymail/v/0.0.0/app/localization/admin/es_ES.yml index 444e327ea..e707e4f84 100644 --- a/snappymail/v/0.0.0/app/localization/admin/es_ES.yml +++ b/snappymail/v/0.0.0/app/localization/admin/es_ES.yml @@ -171,7 +171,6 @@ es_ES: CURRENT_PASSWORD_INCORRECT: "La contraseña actual es incorrecta" NEW_PASSWORD_SHORT: "La contraseña es muy corta" NEW_PASSWORD_WEAK: "La contraseña es muy fácil" - NEW_PASSWORD_FORBIDDEN: "La contraseña contiene caracteres prohibidos" CONTACTS_SYNC_ERROR: "Error de sincronización de Contactos" CANT_GET_MESSAGE_LIST: "No se puede obtener la lista de mensajes" CANT_GET_MESSAGE: "No se puede obtener el mensaje" diff --git a/snappymail/v/0.0.0/app/localization/admin/fr_FR.yml b/snappymail/v/0.0.0/app/localization/admin/fr_FR.yml index 08f2ef7c1..65beabf80 100644 --- a/snappymail/v/0.0.0/app/localization/admin/fr_FR.yml +++ b/snappymail/v/0.0.0/app/localization/admin/fr_FR.yml @@ -171,7 +171,6 @@ fr_FR: CURRENT_PASSWORD_INCORRECT: "Le mot de passe actuel est incorrect" NEW_PASSWORD_SHORT: "Le mot de passe est trop court" NEW_PASSWORD_WEAK: "Le mot de passe n'est pas assez fort" - NEW_PASSWORD_FORBIDDEN: "Le mot de passe contient des caractères invalides" CONTACTS_SYNC_ERROR: "Erreur de synchronisation des contacts" CANT_GET_MESSAGE_LIST: "Impossible d'obtenir la liste des messages" CANT_GET_MESSAGE: "Impossible d'obtenir le message" diff --git a/snappymail/v/0.0.0/app/localization/admin/nl_NL.yml b/snappymail/v/0.0.0/app/localization/admin/nl_NL.yml index 7bcbe88fa..2afe933ed 100644 --- a/snappymail/v/0.0.0/app/localization/admin/nl_NL.yml +++ b/snappymail/v/0.0.0/app/localization/admin/nl_NL.yml @@ -170,7 +170,6 @@ nl_NL: CURRENT_PASSWORD_INCORRECT: "Huidig wachtwoord is onjuist" NEW_PASSWORD_SHORT: "Wachtwoord is te kort" NEW_PASSWORD_WEAK: "Wachtwoord is te gemakkelijk" - NEW_PASSWORD_FORBIDDEN: "Wachtwoord bevat verboden karakters" CONTACTS_SYNC_ERROR: "Contactpersonen synchronisatie fout" CANT_GET_MESSAGE_LIST: "Kan berichtenlijst niet ophalen" CANT_GET_MESSAGE: "Kan bericht niet ophalen" diff --git a/snappymail/v/0.0.0/app/localization/admin/zh_CN.yml b/snappymail/v/0.0.0/app/localization/admin/zh_CN.yml index 96fe6178f..4182a78e4 100644 --- a/snappymail/v/0.0.0/app/localization/admin/zh_CN.yml +++ b/snappymail/v/0.0.0/app/localization/admin/zh_CN.yml @@ -171,7 +171,6 @@ zh_CN: CURRENT_PASSWORD_INCORRECT: "当前密码不正确" NEW_PASSWORD_SHORT: "密码太短" NEW_PASSWORD_WEAK: "密码过于简单" - NEW_PASSWORD_FORBIDDEN: "密码包含禁止使用的字符" CONTACTS_SYNC_ERROR: "联系人同步错误" CANT_GET_MESSAGE_LIST: "无法获取邮件列表" CANT_GET_MESSAGE: "无法获取邮件" diff --git a/snappymail/v/0.0.0/app/localization/webmail/_source.en.yml b/snappymail/v/0.0.0/app/localization/webmail/_source.en.yml index 9c97d01d5..fdafc29e5 100644 --- a/snappymail/v/0.0.0/app/localization/webmail/_source.en.yml +++ b/snappymail/v/0.0.0/app/localization/webmail/_source.en.yml @@ -515,7 +515,6 @@ en: CURRENT_PASSWORD_INCORRECT: "Current password incorrect" NEW_PASSWORD_SHORT: "Password is too short" NEW_PASSWORD_WEAK: "Password is too easy" - NEW_PASSWORD_FORBIDDEN: "Password contains forbidden characters" CONTACTS_SYNC_ERROR: "Contacts synchronization error" CANT_GET_MESSAGE_LIST: "Can't get message list" CANT_GET_MESSAGE: "Can't get message" diff --git a/snappymail/v/0.0.0/app/localization/webmail/de_DE.yml b/snappymail/v/0.0.0/app/localization/webmail/de_DE.yml index 7dba77461..63fc5d050 100644 --- a/snappymail/v/0.0.0/app/localization/webmail/de_DE.yml +++ b/snappymail/v/0.0.0/app/localization/webmail/de_DE.yml @@ -516,7 +516,6 @@ de_DE: CURRENT_PASSWORD_INCORRECT: "Aktuelles Passwort falsch" NEW_PASSWORD_SHORT: "Passwort ist zu kurz" NEW_PASSWORD_WEAK: "Passwort ist zu einfach" - NEW_PASSWORD_FORBIDDEN: "Passwort enthält unzulässige Zeichen" CONTACTS_SYNC_ERROR: "Fehler bei Kontakte-Synchronisierung" CANT_GET_MESSAGE_LIST: "Die Nachrichtenliste ist nicht verfügbar" CANT_GET_MESSAGE: "Diese Nachricht ist nicht verfügbar" diff --git a/snappymail/v/0.0.0/app/localization/webmail/en_GB.yml b/snappymail/v/0.0.0/app/localization/webmail/en_GB.yml index 52f76bd7e..16f59a292 100644 --- a/snappymail/v/0.0.0/app/localization/webmail/en_GB.yml +++ b/snappymail/v/0.0.0/app/localization/webmail/en_GB.yml @@ -515,7 +515,6 @@ en_GB: CURRENT_PASSWORD_INCORRECT: "Current password incorrect" NEW_PASSWORD_SHORT: "Password is too short" NEW_PASSWORD_WEAK: "Password is too easy" - NEW_PASSWORD_FORBIDDEN: "Password contains forbidden characters" CONTACTS_SYNC_ERROR: "Contacts synchronization error" CANT_GET_MESSAGE_LIST: "Can't get message list" CANT_GET_MESSAGE: "Can't get message" diff --git a/snappymail/v/0.0.0/app/localization/webmail/en_US.yml b/snappymail/v/0.0.0/app/localization/webmail/en_US.yml index e7ed919fd..a0da83f14 100644 --- a/snappymail/v/0.0.0/app/localization/webmail/en_US.yml +++ b/snappymail/v/0.0.0/app/localization/webmail/en_US.yml @@ -515,7 +515,6 @@ en_US: CURRENT_PASSWORD_INCORRECT: "Current password incorrect" NEW_PASSWORD_SHORT: "Password is too short" NEW_PASSWORD_WEAK: "Password is too easy" - NEW_PASSWORD_FORBIDDEN: "Password contains forbidden characters" CONTACTS_SYNC_ERROR: "Contacts synchronization error" CANT_GET_MESSAGE_LIST: "Can't get message list" CANT_GET_MESSAGE: "Can't get message" diff --git a/snappymail/v/0.0.0/app/localization/webmail/es_ES.yml b/snappymail/v/0.0.0/app/localization/webmail/es_ES.yml index 908f0ca69..a85e4a4e8 100644 --- a/snappymail/v/0.0.0/app/localization/webmail/es_ES.yml +++ b/snappymail/v/0.0.0/app/localization/webmail/es_ES.yml @@ -517,7 +517,6 @@ es_ES: CURRENT_PASSWORD_INCORRECT: "La contraseña actual es incorrecta" NEW_PASSWORD_SHORT: "La contraseña es muy corta" NEW_PASSWORD_WEAK: "La contraseña es muy fácil" - NEW_PASSWORD_FORBIDDEN: "La contraseña contiene caracteres prohibidos" CONTACTS_SYNC_ERROR: "Error de sincronización de Contactos" CANT_GET_MESSAGE_LIST: "No se puede obtener la lista de mensajes" CANT_GET_MESSAGE: "No se puede obtener el mensaje" diff --git a/snappymail/v/0.0.0/app/localization/webmail/fr_FR.yml b/snappymail/v/0.0.0/app/localization/webmail/fr_FR.yml index 29eba15a7..9ec65974c 100644 --- a/snappymail/v/0.0.0/app/localization/webmail/fr_FR.yml +++ b/snappymail/v/0.0.0/app/localization/webmail/fr_FR.yml @@ -516,7 +516,6 @@ fr_FR: CURRENT_PASSWORD_INCORRECT: "Le mot de passe actuel est incorrect" NEW_PASSWORD_SHORT: "Le mot de passe est trop court" NEW_PASSWORD_WEAK: "Le mot de passe n'est pas assez fort" - NEW_PASSWORD_FORBIDDEN: "Le mot de passe contient des caractères invalides" CONTACTS_SYNC_ERROR: "Erreur de synchronisation des contacts" CANT_GET_MESSAGE_LIST: "Impossible d'obtenir la liste des messages" CANT_GET_MESSAGE: "Impossible d'obtenir le message" diff --git a/snappymail/v/0.0.0/app/localization/webmail/nl_NL.yml b/snappymail/v/0.0.0/app/localization/webmail/nl_NL.yml index 9870801af..1c172e4ac 100644 --- a/snappymail/v/0.0.0/app/localization/webmail/nl_NL.yml +++ b/snappymail/v/0.0.0/app/localization/webmail/nl_NL.yml @@ -515,7 +515,6 @@ nl_NL: CURRENT_PASSWORD_INCORRECT: "Huidig wachtwoord onjuist" NEW_PASSWORD_SHORT: "Wachtwoord is te kort" NEW_PASSWORD_WEAK: "Wachtwoord is te makkelijk" - NEW_PASSWORD_FORBIDDEN: "Wachtwoord bevat verboden tekens" CONTACTS_SYNC_ERROR: "Contactpersonen synchronisatie fout" CANT_GET_MESSAGE_LIST: "Berichtenlijst kan niet worden opgehaald" CANT_GET_MESSAGE: "Bericht kan niet worden opgehaald" diff --git a/snappymail/v/0.0.0/app/localization/webmail/zh_CN.yml b/snappymail/v/0.0.0/app/localization/webmail/zh_CN.yml index f51464e26..d5586f533 100644 --- a/snappymail/v/0.0.0/app/localization/webmail/zh_CN.yml +++ b/snappymail/v/0.0.0/app/localization/webmail/zh_CN.yml @@ -513,7 +513,6 @@ zh_CN: CURRENT_PASSWORD_INCORRECT: "当前密码不正确" NEW_PASSWORD_SHORT: "密码太短" NEW_PASSWORD_WEAK: "密码过于简单" - NEW_PASSWORD_FORBIDDEN: "密码包含禁止使用的字符" CONTACTS_SYNC_ERROR: "联系人同步错误" CANT_GET_MESSAGE_LIST: "无法获取邮件列表" CANT_GET_MESSAGE: "无法获取邮件" diff --git a/snappymail/v/0.0.0/app/templates/Views/User/SettingsChangePassword.html b/snappymail/v/0.0.0/app/templates/Views/User/SettingsChangePassword.html new file mode 100644 index 000000000..646c6ef56 --- /dev/null +++ b/snappymail/v/0.0.0/app/templates/Views/User/SettingsChangePassword.html @@ -0,0 +1,40 @@ +