(Grav GitSync) Automatic Commit from dan
This commit is contained in:
parent
5c8cb11563
commit
3aba6cc06e
26 changed files with 230 additions and 161 deletions
|
@ -1,3 +1,9 @@
|
|||
# v1.10.42
|
||||
## 06/14/2023
|
||||
|
||||
1. [](#new)
|
||||
* Added a couple of string translations
|
||||
|
||||
# v1.10.41.2
|
||||
## 05/11/2023
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: Admin Panel
|
||||
slug: admin
|
||||
type: plugin
|
||||
version: 1.10.41.2
|
||||
version: 1.10.42
|
||||
description: Adds an advanced administration panel to manage your site
|
||||
icon: empire
|
||||
author:
|
||||
|
@ -15,7 +15,7 @@ docs: https://github.com/getgrav/grav-plugin-admin/blob/develop/README.md
|
|||
license: MIT
|
||||
|
||||
dependencies:
|
||||
- { name: grav, version: '>=1.7.41' }
|
||||
- { name: grav, version: '>=1.7.42' }
|
||||
- { name: form, version: '>=6.0.1' }
|
||||
- { name: login, version: '>=3.7.0' }
|
||||
- { name: email, version: '>=3.1.6' }
|
||||
|
|
|
@ -107,7 +107,6 @@ PLUGIN_ADMIN:
|
|||
BACKUP_DELETED: "Backup Successfully Deleted"
|
||||
BACKUP_NOT_FOUND: "Backup Not Found"
|
||||
BACKUP_DATE: "Backup Date"
|
||||
|
||||
STATISTICS: "Statistics"
|
||||
VIEWS_STATISTICS: "Page View Statistics"
|
||||
TODAY: "Today"
|
||||
|
@ -207,11 +206,13 @@ PLUGIN_ADMIN:
|
|||
PASSWORD: "Password"
|
||||
PASSWORD_CONFIRM: "Confirm Password"
|
||||
TITLE: "Title"
|
||||
LANGUAGE: "Language"
|
||||
ACCOUNT: "Account"
|
||||
EMAIL_VALIDATION_MESSAGE: "Must be a valid email address"
|
||||
PASSWORD_VALIDATION_MESSAGE: "Password must contain at least one number and one uppercase and lowercase letter, and at least 8 or more characters"
|
||||
LANGUAGE: "Language"
|
||||
LANGUAGE_HELP: "Set the favorite language"
|
||||
LANGUAGE_DEBUG: "Debug language"
|
||||
LANGUAGE_DEBUG_HELP: "Enable the debug of languages which are using the |t twig filter by adding a span around them that can be styled to help diagnose issues"
|
||||
MEDIA: "Media"
|
||||
DEFAULTS: "Defaults"
|
||||
SITE_TITLE: "Site Title"
|
||||
|
|
|
@ -1,3 +1,25 @@
|
|||
# v4.0.4
|
||||
## 07/10/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fix for email file attachments using stream
|
||||
|
||||
# v4.0.3
|
||||
## 06/29/2023
|
||||
|
||||
1. [](#improved)
|
||||
* Simplified the `Email::processRecipients()` logic for readability
|
||||
1. [](#bugfix)
|
||||
* Fix an issue with 2 email addresses provided with 'just' email and no name [#176](https://github.com/getgrav/grav-plugin-email/issues/176)
|
||||
* Fix for blank subjectlines when using `Message::setSubject()` in Twig templates [getgrav/grav-plugin-login#299](https://github.com/getgrav/grav-plugin-login/issues/299)
|
||||
|
||||
# v4.0.2
|
||||
## 06/27/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* some recipient handling improvements. e.g. missing `bcc_name` throwing error
|
||||
* Allow overriding of defaults with a form configuration. Use `null` to remove default email configuration
|
||||
|
||||
# v4.0.1
|
||||
## 05/20/2023
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: Email
|
||||
slug: email
|
||||
type: plugin
|
||||
version: 4.0.1
|
||||
version: 4.0.4
|
||||
testing: false
|
||||
description: Enables the emailing system for Grav
|
||||
icon: envelope
|
||||
|
|
|
@ -138,8 +138,9 @@ class Email
|
|||
$email = $message->getEmail();
|
||||
|
||||
// Extend parameters with defaults.
|
||||
$params += [
|
||||
$defaults = [
|
||||
'bcc' => $config->get('plugins.email.bcc', []),
|
||||
'bcc_name' => $config->get('plugins.email.bcc_name'),
|
||||
'body' => $config->get('plugins.email.body', '{% include "forms/data.html.twig" %}'),
|
||||
'cc' => $config->get('plugins.email.cc', []),
|
||||
'cc_name' => $config->get('plugins.email.cc_name'),
|
||||
|
@ -157,6 +158,12 @@ class Email
|
|||
'message' => $message
|
||||
];
|
||||
|
||||
foreach ($defaults as $key => $value) {
|
||||
if (!key_exists($key, $params)) {
|
||||
$params[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$params['to']) {
|
||||
throw new \RuntimeException($language->translate('PLUGIN_EMAIL.PLEASE_CONFIGURE_A_TO_ADDRESS'));
|
||||
}
|
||||
|
@ -237,38 +244,39 @@ class Email
|
|||
*/
|
||||
protected function processRecipients(string $type, array $params): array
|
||||
{
|
||||
if (array_key_exists($type, $params) && $params[$type] === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$recipients = $params[$type] ?? Grav::instance()['config']->get('plugins.email.'.$type) ?? [];
|
||||
|
||||
$list = [];
|
||||
|
||||
if (!empty($recipients)) {
|
||||
if (is_array($recipients) && Utils::isAssoc($recipients)) {
|
||||
$list[] = $this->createAddress($recipients);
|
||||
if (is_array($recipients)) {
|
||||
if (Utils::isAssoc($recipients) || (count($recipients) ===2 && $this->isValidEmail($recipients[0]) && !$this->isValidEmail($recipients[1]))) {
|
||||
$list[] = $this->createAddress($recipients);
|
||||
} else {
|
||||
foreach ($recipients as $recipient) {
|
||||
$list[] = $this->createAddress($recipient);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_array($recipients)) {
|
||||
if (count($recipients) ===2 && $this->isValidEmail($recipients[0]) && is_string($recipients[1])) {
|
||||
$list[] = $this->createAddress($recipients);
|
||||
} else {
|
||||
foreach ($recipients as $recipient) {
|
||||
$list[] = $this->createAddress($recipient);
|
||||
}
|
||||
if (is_string($recipients) && Utils::contains($recipients, ',')) {
|
||||
$recipients = array_map('trim', explode(',', $recipients));
|
||||
foreach ($recipients as $recipient) {
|
||||
$list[] = $this->createAddress($recipient);
|
||||
}
|
||||
} else {
|
||||
if (is_string($recipients) && Utils::contains($recipients, ',')) {
|
||||
$recipients = array_map('trim', explode(',', $recipients));
|
||||
foreach ($recipients as $recipient) {
|
||||
$list[] = $this->createAddress($recipient);
|
||||
}
|
||||
} else {
|
||||
if (!Utils::contains($recipients, ['<','>']) && ($params[$type."_name"])) {
|
||||
$recipients = [$recipients, $params[$type."_name"]];
|
||||
}
|
||||
$list[] = $this->createAddress($recipients);
|
||||
if (!Utils::contains($recipients, ['<','>']) && (isset($params[$type."_name"]))) {
|
||||
$recipients = [$recipients, $params[$type."_name"]];
|
||||
}
|
||||
$list[] = $this->createAddress($recipients);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,12 @@ class Message
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setSubject($subject): self
|
||||
{
|
||||
$this->subject($subject);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function to($to): self
|
||||
{
|
||||
$this->email->to($to);
|
||||
|
|
|
@ -125,6 +125,7 @@ class EmailPlugin extends Plugin
|
|||
{
|
||||
// Build message
|
||||
$message = $this->email->buildMessage($params, $vars);
|
||||
$locator = $this->grav['locator'];
|
||||
|
||||
if (isset($params['attachments'])) {
|
||||
$filesToAttach = (array)$params['attachments'];
|
||||
|
@ -135,9 +136,11 @@ class EmailPlugin extends Plugin
|
|||
if (isset($fileValues['file'])) {
|
||||
$filename = $fileValues['file'];
|
||||
} else {
|
||||
$filename = ROOT_DIR . $fileValues['path'];
|
||||
$filename = $fileValues['path'];
|
||||
}
|
||||
|
||||
$filename = $locator->findResource($filename, true, true);
|
||||
|
||||
try {
|
||||
$message->attachFromPath($filename);
|
||||
} catch (\Exception $e) {
|
||||
|
|
|
@ -78,6 +78,7 @@ fr:
|
|||
PLUGIN_EMAIL:
|
||||
MAIL_ENGINE: "Moteur de messagerie"
|
||||
MAIL_ENGINE_DISABLED: "Désactivé"
|
||||
MAIL_ENGINE_DESC: "NOTE : Si vous sélectionnez un moteur fourni par un autre plugin, vous devez configurer les options dans ce même plugin."
|
||||
CONTENT_TYPE: "Type de contenu"
|
||||
CONTENT_TYPE_PLAIN_TEXT: "Texte brut"
|
||||
CHARSET: "Jeu de caractères"
|
||||
|
@ -130,7 +131,9 @@ fr:
|
|||
QUEUE_FLUSH_MSG_LIMIT: "Messages par Flush"
|
||||
QUEUE_FLUSH_MSG_LIMIT_APPEND: "Messages"
|
||||
QUEUE_FLUSH_TIME_LIMIT: "Délai de Flush"
|
||||
QUEUE_FLUSH_TIME_LIMIT_APPEND: "Seconds"
|
||||
QUEUE_FLUSH_TIME_LIMIT_APPEND: "Secondes"
|
||||
EMAIL_FORMAT: "Utilisez le format `addr` : `email@adresse.org` ou le format `name-addr` : `Votre nom <email@adresse.org>`. Séparer par des virgules pour plusieurs adresses."
|
||||
|
||||
|
||||
hr:
|
||||
PLUGIN_EMAIL:
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
# v7.2.1
|
||||
## 06/27/2023
|
||||
|
||||
1. [](#improved)
|
||||
* Added some optional debug output to help isolate form loading problems
|
||||
1. [](#bugfix)
|
||||
* More robust fix for multi-language form caching
|
||||
|
||||
# v7.2.0
|
||||
## 06/21/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed a long-standing bug with cached forms not working properly in multi-language scenarios
|
||||
|
||||
# v7.1.3
|
||||
## 05/09/2023
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: Form
|
||||
slug: form
|
||||
type: plugin
|
||||
version: 7.1.3
|
||||
version: 7.2.1
|
||||
description: Enables forms handling and processing
|
||||
icon: check-square
|
||||
author:
|
||||
|
@ -34,6 +34,17 @@ form:
|
|||
title: PLUGIN_FORM.GENERAL
|
||||
|
||||
fields:
|
||||
debug:
|
||||
type: toggle
|
||||
label: Debug
|
||||
highlight: 1
|
||||
default: 0
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
built_in_css:
|
||||
type: toggle
|
||||
label: PLUGIN_FORM.USE_BUILT_IN_CSS
|
||||
|
|
|
@ -26,6 +26,7 @@ use Grav\Plugin\Form\Form;
|
|||
use Grav\Plugin\Form\Forms;
|
||||
use Grav\Plugin\Form\TwigExtension;
|
||||
use Grav\Common\HTTP\Client;
|
||||
use Monolog\Logger;
|
||||
use ReCaptcha\ReCaptcha;
|
||||
use ReCaptcha\RequestMethod\CurlPost;
|
||||
use RecursiveArrayIterator;
|
||||
|
@ -65,8 +66,7 @@ class FormPlugin extends Plugin
|
|||
protected $active_forms = [];
|
||||
/** @var array */
|
||||
protected $json_response = [];
|
||||
/** @var bool */
|
||||
protected $recache_forms = false;
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
|
@ -149,6 +149,8 @@ class FormPlugin extends Plugin
|
|||
'onTwigSiteVariables' => ['onTwigVariables', 0],
|
||||
'onFormValidationProcessed' => ['onFormValidationProcessed', 0],
|
||||
]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -223,17 +225,11 @@ class FormPlugin extends Plugin
|
|||
$submitted = false;
|
||||
$this->json_response = [];
|
||||
|
||||
// Save cached forms.
|
||||
if ($this->recache_forms) {
|
||||
$this->saveCachedForms();
|
||||
}
|
||||
|
||||
/** @var PageInterface $page */
|
||||
$page = $this->grav['page'];
|
||||
|
||||
// Force rebuild form when form has not been built and form cache expired.
|
||||
// This happens when form cache expires before the page cache
|
||||
// and then does not trigger 'onPageProcessed' event.
|
||||
|
||||
// DEPRECATED: This should no longer ever happen
|
||||
if (!$this->forms) {
|
||||
$this->onPageProcessed(new Event(['page' => $page]));
|
||||
}
|
||||
|
@ -318,9 +314,11 @@ class FormPlugin extends Plugin
|
|||
/** @var Forms $forms */
|
||||
$forms = $this->grav['forms'];
|
||||
|
||||
$lang = $this->grav['language']->getLanguage();
|
||||
|
||||
/** @var Route $route */
|
||||
$route = $this->grav['route'];
|
||||
$pageForms = $this->forms[$route->getRoute()] ?? [];
|
||||
$pageForms = $this->forms[$lang][$route->getRoute()] ?? [];
|
||||
|
||||
/**
|
||||
* @var string $name
|
||||
|
@ -835,12 +833,12 @@ class FormPlugin extends Plugin
|
|||
public function addFormDefinition(PageInterface $page, string $name, array $form): void
|
||||
{
|
||||
$route = ($page->home() ? '/' : $page->route()) ?? '/';
|
||||
$lang = $this->grav['language']->getLanguage();
|
||||
|
||||
if (!isset($this->forms[$route][$name])) {
|
||||
if (!isset($this->forms[$lang][$route][$name])) {
|
||||
$form['_page_routable'] = !$page->isModule();
|
||||
|
||||
$this->forms[$route][$name] = $form;
|
||||
$this->recache_forms = true;
|
||||
$this->forms[$lang][$route][$name] = $form;
|
||||
$this->saveCachedForms();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -857,13 +855,14 @@ class FormPlugin extends Plugin
|
|||
return;
|
||||
}
|
||||
|
||||
$lang = $this->grav['language']->getLanguage();
|
||||
$name = $form->getName();
|
||||
|
||||
if (!isset($this->forms[$route][$name])) {
|
||||
if (!isset($this->forms[$lang][$route][$name])) {
|
||||
$form['_page_routable'] = true;
|
||||
|
||||
$this->forms[$route][$name] = $form;
|
||||
$this->recache_forms = true;
|
||||
$this->forms[$lang][$route][$name] = $form;
|
||||
$this->saveCachedForms();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -877,6 +876,7 @@ class FormPlugin extends Plugin
|
|||
{
|
||||
/** @var Pages $pages */
|
||||
$pages = $this->grav['pages'];
|
||||
$lang = $this->grav['language']->getLanguage();
|
||||
|
||||
// Handle parameters.
|
||||
if (is_array($data)) {
|
||||
|
@ -922,7 +922,7 @@ class FormPlugin extends Plugin
|
|||
|
||||
// Attempt to find the form from the page.
|
||||
if ('' !== $route) {
|
||||
$forms = $this->forms[$route] ?? [];
|
||||
$forms = $this->forms[$lang][$route] ?? [];
|
||||
|
||||
if (!$unnamed) {
|
||||
// Get form by the name.
|
||||
|
@ -938,9 +938,7 @@ class FormPlugin extends Plugin
|
|||
if (null === $form) {
|
||||
// First check if we requested a specific form which didn't exist.
|
||||
if ($route_provided || $unnamed) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = $this->grav['debugger'];
|
||||
$debugger->addMessage(sprintf('Form %s not found in page %s', $name ?? 'unnamed', $route), 'warning');
|
||||
$this->grav['debugger']->addMessage(sprintf('Form %s not found in page %s', $name ?? 'unnamed', $route), 'warning');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -954,8 +952,7 @@ class FormPlugin extends Plugin
|
|||
|
||||
// Check for naming conflicts.
|
||||
if (count($forms) > 1) {
|
||||
$debugger = $this->grav['debugger'];
|
||||
$debugger->addMessage(sprintf('Fetching form by its name, but there are multiple pages with the same form name %s', $name), 'warning');
|
||||
$this->grav['debugger']->addMessage(sprintf('Fetching form by its name, but there are multiple pages with the same form name %s', $name), 'warning');
|
||||
}
|
||||
|
||||
[$route, $name, $form] = $first;
|
||||
|
@ -967,9 +964,7 @@ class FormPlugin extends Plugin
|
|||
if (is_array($form)) {
|
||||
// Form was cached as an array, try to create the object.
|
||||
if (null === $page) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = $this->grav['debugger'];
|
||||
$debugger->addMessage(sprintf('Form %s cannot be created as page %s does not exist', $name, $route), 'warning');
|
||||
$this->grav['debugger']->addMessage(sprintf('Form %s cannot be created as page %s does not exist', $name, $route), 'warning');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -1104,7 +1099,10 @@ class FormPlugin extends Plugin
|
|||
protected function findFormByName(string $name): array
|
||||
{
|
||||
$list = [];
|
||||
foreach ($this->forms as $route => $forms) {
|
||||
$lang = $this->grav['language']->getLanguage();
|
||||
$lang_forms = $this->forms[$lang] ?? [];
|
||||
|
||||
foreach ($lang_forms as $route => $forms) {
|
||||
foreach ($forms as $key => $form) {
|
||||
if ($name === $key && !empty($form['_page_routable'])) {
|
||||
$list[] = [$route, $key, $form];
|
||||
|
@ -1241,12 +1239,9 @@ class FormPlugin extends Plugin
|
|||
/** @var Cache $cache */
|
||||
$cache = $this->grav['cache'];
|
||||
|
||||
[$forms] = $cache->fetch($this->getFormCacheId());
|
||||
$forms = $cache->fetch($this->getFormCacheId());
|
||||
} catch (Exception $e) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = Grav::instance()['debugger'];
|
||||
$debugger->addMessage(sprintf('Unserializing cached forms failed: %s', $e->getMessage()), 'error');
|
||||
|
||||
$this->grav['debugger']->addMessage(sprintf('Unserializing cached forms failed: %s', $e->getMessage()), 'error');
|
||||
$forms = null;
|
||||
}
|
||||
|
||||
|
@ -1256,7 +1251,11 @@ class FormPlugin extends Plugin
|
|||
|
||||
// Only update the forms if it's not empty
|
||||
if ($forms) {
|
||||
$this->forms = array_merge($this->forms, $forms);
|
||||
$this->forms = Utils::arrayMergeRecursiveUnique($this->forms, $forms);
|
||||
if ($this->config()['debug']) {
|
||||
$this->grav['log']->addDebug(sprintf("<<<< Loaded cached forms: %s\n%s", $this->getFormCacheId(), $this->arrayToString($this->forms)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1267,17 +1266,19 @@ class FormPlugin extends Plugin
|
|||
*/
|
||||
protected function saveCachedForms(): void
|
||||
{
|
||||
// Save the current state of the forms to cache
|
||||
if (!$this->recache_forms) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->recache_forms = false;
|
||||
|
||||
/** @var Cache $cache */
|
||||
$cache = $this->grav['cache'];
|
||||
$cache_id = $this->getFormCacheId();
|
||||
|
||||
$cache->save($this->getFormCacheId(), [$this->forms]);
|
||||
$forms = $cache->fetch($cache_id);
|
||||
if ($forms) {
|
||||
$this->forms = Utils::arrayMergeRecursiveUnique($this->forms, $forms);
|
||||
}
|
||||
|
||||
$cache->save($cache_id, $this->forms);
|
||||
if ($this->config()['debug']) {
|
||||
$this->grav['log']->addDebug(sprintf(">>>> Saved cached forms: %s\n%s", $this->getFormCacheId(), $this->arrayToString($this->forms)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1287,10 +1288,10 @@ class FormPlugin extends Plugin
|
|||
*/
|
||||
protected function getFormCacheId(): string
|
||||
{
|
||||
/** @var Pages $pages */
|
||||
$pages = $this->grav['pages'];
|
||||
|
||||
return $pages->getPagesCacheId() . '-form-plugin';
|
||||
/** @var \Grav\Common\Cache $cache */
|
||||
$cache = $this->grav['cache'];
|
||||
$cache_id = $cache->getKey() . '-form-plugin';
|
||||
return $cache_id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1323,4 +1324,25 @@ class FormPlugin extends Plugin
|
|||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
protected function arrayToString($array, $level = 2) {
|
||||
$result = $this->limitArrayLevels($array, $level);
|
||||
return json_encode($result, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
protected function limitArrayLevels($array, $levelsToKeep, $currentLevel = 0) {
|
||||
if ($currentLevel >= $levelsToKeep) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$value = $this->limitArrayLevels($value, $levelsToKeep, $currentLevel + 1);
|
||||
}
|
||||
$result[$key] = $value;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ built_in_css: true
|
|||
inline_css: true
|
||||
refresh_prevention: false
|
||||
client_side_validation: true
|
||||
debug: false
|
||||
inline_errors: false
|
||||
files:
|
||||
multiple: false # To allow multiple files, default is single
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
# v3.7.6
|
||||
## 06/29/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* Don't save an empty user file on password reset of non-existing user
|
||||
|
||||
# v3.7.5
|
||||
## 06/14/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* Sanitized `email` during the "forgot password" process to protect against XSS attacks
|
||||
* Fixed an account enumeration vulnerability in forgot password [#293](https://github.com/getgrav/grav-plugin-login/pull/293)
|
||||
|
||||
# v3.7.4
|
||||
## 05/09/2023
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: Login
|
||||
slug: login
|
||||
type: plugin
|
||||
version: 3.7.4
|
||||
version: 3.7.6
|
||||
testing: false
|
||||
description: Enables user authentication and login screen.
|
||||
icon: sign-in
|
||||
|
|
|
@ -347,80 +347,66 @@ class Controller
|
|||
$config = $this->grav['config'];
|
||||
$data = $this->post;
|
||||
|
||||
/** @var UserCollectionInterface $users */
|
||||
$users = $this->grav['accounts'];
|
||||
|
||||
$email = $data['email'] ?? '';
|
||||
$user = !empty($email) ? $users->find($email, ['email']) : null;
|
||||
|
||||
/** @var Language $language */
|
||||
$language = $this->grav['language'];
|
||||
$messages = $this->grav['messages'];
|
||||
|
||||
if (!isset($this->grav['Email'])) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
/** @var UserCollectionInterface $users */
|
||||
$users = $this->grav['accounts'];
|
||||
$email = $data['email'] ?? '';
|
||||
|
||||
return true;
|
||||
}
|
||||
// Sanitize $email
|
||||
$email = htmlspecialchars(strip_tags($email), ENT_QUOTES, 'UTF-8');
|
||||
|
||||
if (!$user || !$user->exists()) {
|
||||
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_USERNAME_DOES_NOT_EXIST', $email]), 'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
// Find user if they exist
|
||||
$user = $users->find($email, ['email']);
|
||||
|
||||
return true;
|
||||
}
|
||||
if ($user->exists()) {
|
||||
if (!isset($this->grav['Email'])) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
|
||||
if (empty($user->email)) {
|
||||
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL', $email]),
|
||||
'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
$from = $config->get('plugins.email.from');
|
||||
|
||||
if (empty($user->password) && empty($user->hashed_password)) {
|
||||
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_EMAIL_NO_PASSWORD', $email]),
|
||||
'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
if (empty($from)) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$from = $config->get('plugins.email.from');
|
||||
$userKey = $user->username;
|
||||
$rateLimiter = $this->login->getRateLimiter('pw_resets');
|
||||
$rateLimiter->registerRateLimitedAction($userKey);
|
||||
|
||||
if (empty($from)) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
if ($rateLimiter->isRateLimited($userKey)) {
|
||||
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $email, $rateLimiter->getInterval()]), 'error');
|
||||
$this->setRedirect($this->login->getRoute('login') ?? '/');
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$userKey = $user->username;
|
||||
$rateLimiter = $this->login->getRateLimiter('pw_resets');
|
||||
$rateLimiter->registerRateLimitedAction($userKey);
|
||||
$token = md5(uniqid((string)mt_rand(), true));
|
||||
$expire = time() + 604800; // next week
|
||||
|
||||
if ($rateLimiter->isRateLimited($userKey)) {
|
||||
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $email, $rateLimiter->getInterval()]), 'error');
|
||||
$this->setRedirect($this->login->getRoute('login') ?? '/');
|
||||
$user->reset = $token . '::' . $expire;
|
||||
$user->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$token = md5(uniqid((string)mt_rand(), true));
|
||||
$expire = time() + 604800; // next week
|
||||
|
||||
$user->reset = $token . '::' . $expire;
|
||||
$user->save();
|
||||
|
||||
try {
|
||||
Email::sendResetPasswordEmail($user);
|
||||
try {
|
||||
Email::sendResetPasswordEmail($user);
|
||||
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info');
|
||||
} catch (\Exception $e) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_FAILED_TO_EMAIL'), 'error');
|
||||
}
|
||||
} else {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info');
|
||||
} catch (\Exception $e) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_FAILED_TO_EMAIL'), 'error');
|
||||
}
|
||||
|
||||
|
||||
$this->setRedirect($this->login->getRoute('login') ?? '/');
|
||||
|
||||
return true;
|
||||
|
|
|
@ -21,9 +21,6 @@ PLUGIN_LOGIN:
|
|||
RESET_INVALID_LINK: "Es wurde ein ungültiger Link zum Zurücksetzen verwendet. Bitte erneut versuchen."
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Die Anweisungen zum Zurücksetzen Ihres Passworts wurden per E-Mail gesendet."
|
||||
FORGOT_FAILED_TO_EMAIL: "Das Versenden der Anweisung per E-Mail ist fehlgeschlagen. Bitte später erneut versuchen."
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "Das Passwort für %s kann nicht zurückgesetzt werden. Es ist keine E-Mail-Adresse hinterlegt."
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_PASSWORD: "Das Passwort für %s kann nicht zurückgesetzt werden. Diese E-Mail ist mit einem Remote-Account verknüpft."
|
||||
FORGOT_USERNAME_DOES_NOT_EXIST: "Der Benutzer mit dem Benutzername <b>%s</b> existiert nicht."
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "Das Passwort kann nicht zurückgesetzt werden, da die Website ist nicht zum Versenden von E-Mails konfiguriert."
|
||||
FORGOT_EMAIL_SUBJECT: "Passwort zurückzusetzen für %s"
|
||||
FORGOT_EMAIL_BODY: "<h1>Passwort Zurücksetzen</h1><p>Hallo %1$s,</p><p>Es wurde ein Anfrage auf <b>%4$s</b> gestellt, um Ihr Passwort zu ändern.</p><p><br /><a href=\"%2$s\" class=\"btn-primary\">Klicken Sie hier, um Ihr Passwort zurückzusetzen</a><br /><br /></p><p>Alternativ kopieren Sie die folgende URL in die Adresszeile Ihres Browsers:</p> <p class=\"word-break\"><a href=\"%2$s\">%2$s</a></p> <p><br />Mit freundlichen Grüßen,<br /><br />%3$s</p>"
|
||||
|
|
|
@ -18,11 +18,8 @@ PLUGIN_LOGIN:
|
|||
RESET_LINK_EXPIRED: "Reset link has expired, please try again"
|
||||
RESET_PASSWORD_RESET: "Password has been reset"
|
||||
RESET_INVALID_LINK: "Invalid reset link used, please try again"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Instructions to reset your password have been sent via email"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "If an account exists, instructions on resetting your password have been sent via email"
|
||||
FORGOT_FAILED_TO_EMAIL: "Failed to email instructions, please try again later"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "Cannot reset password for %s, no email address is set"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_PASSWORD: "Cannot reset password for %s, this email is associated with a remote account"
|
||||
FORGOT_USERNAME_DOES_NOT_EXIST: "User with username <b>%s</b> does not exist"
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "Cannot reset password. This site is not configured to send emails"
|
||||
FORGOT_EMAIL_SUBJECT: "%s Password Reset Request"
|
||||
FORGOT_EMAIL_BODY: "<h1>Password Reset</h1><p>Dear %1$s,</p><p>A request was made on <b>%4$s</b> to reset your password.</p><p><br /><a href=\"%2$s\" class=\"btn-primary\">Click this to reset your password</a><br /><br /></p><p>Alternatively, copy the following URL into your browser's address bar:</p> <p class=\"word-break\"><a href=\"%2$s\">%2$s</a></p> <p><br />Kind regards,<br /><br />%3$s</p>"
|
||||
|
|
|
@ -19,10 +19,8 @@ PLUGIN_LOGIN:
|
|||
RESET_LINK_EXPIRED: "El enlace para la restauración ha caducado, inténtelo de nuevo."
|
||||
RESET_PASSWORD_RESET: "La contraseña ha sido restaurada"
|
||||
RESET_INVALID_LINK: "Ha utilizado un enlace de restauración inválido, inténtelo de nuevo."
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Instructions to reset your password have been sent via email"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "If an account exists, instructions on resetting your password have been sent via email"
|
||||
FORGOT_FAILED_TO_EMAIL: "No se ha podido enviar el email con instrucciones, inténtelo de nuevo."
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "No se puede restaurar la contraseña para %s, no hay dirección de email."
|
||||
FORGOT_USERNAME_DOES_NOT_EXIST: "No existe ningún usuario con el nombre <b>%s</b>."
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "No se puede restaurar la contraseña. Este sitio no está configurado para enviar emails."
|
||||
FORGOT_EMAIL_SUBJECT: "%s solicitud de restauración de contraseña"
|
||||
FORGOT_EMAIL_BODY: "<h1>Restauración de contraseña</h1><p>Estimado/a %1$s,</p><p>Se ha realizado una petición de restauración de contraseña en <b>%4$s</b>.</p><p><br /><a href=\"%2$s\" class=\"btn-primary\">Pulse aquí para restaurar su contraseña</a><br /><br /></p><p>Como alternativa puede copiar la siguiente URL en la barra de direcciones de su navegador:</p> <p class=\"word-break\"><a href=\"%2$s\">%2$s</a></p> <p><br />Saludos cordiales,<br /><br />%3$s</p>"
|
||||
|
|
|
@ -19,8 +19,6 @@ PLUGIN_LOGIN:
|
|||
RESET_INVALID_LINK: "Le lien de réinitialisation utilisé n’est pas valide, veuillez réessayer"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Les instructions pour la réinitialisation de votre mot de passe ont été envoyées par e-mail"
|
||||
FORGOT_FAILED_TO_EMAIL: "Impossible d’envoyer les instructions, veuillez réessayer ultérieurement"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "Impossible de réinitialiser le mot de passe pour %s, aucune adresse e-mail n’a été paramétrée"
|
||||
FORGOT_USERNAME_DOES_NOT_EXIST: "L’utilisateur avec le nom d’utilisateur <b>%s</b> n’existe pas"
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "Impossible de réinitialiser le mot de passe. Ce site n’est pas configuré pour envoyer des e-mails"
|
||||
FORGOT_EMAIL_SUBJECT: "Demande de réinitialisation de mot de passe %s"
|
||||
FORGOT_EMAIL_BODY: "<h1>Réinitialisation de mot de passe</h1><p>%1$s,</p><p>Une demande a été faite sur <b>%4$s</b> pour la réinitialisation de votre mot de passe.</p><p><br /><a href=\"%2$s\" class=\"btn-primary\">Cliquez ici pour réinitialiser votre mot de passe</a><br /><br /></p><p>Vous pouvez également copier l’URL suivante dans la barre d’adresse de votre navigateur :</p> <p class=\"word-break\"><a href=\"%2$s\">%2$s</a></p> <p><br />Cordialement,<br /><br />%3$s</p>"
|
||||
|
|
|
@ -18,12 +18,9 @@ PLUGIN_LOGIN:
|
|||
RESET_LINK_EXPIRED: "Atstatymo nuoroda nebegalioja, bandykite dar kartą"
|
||||
RESET_PASSWORD_RESET: "Slaptažodis atstatytas"
|
||||
RESET_INVALID_LINK: "Panaudota neteisinga atstatymo nuoroda, bandykite dar kartą"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Slaptažodžio atstatymo instrukcijos buvo išsiųstos el. paštu"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Jeigu vartotojo paskyra egzistuoja, slaptažodžio atstatymo instrukcijos buvo išsiųstos el. paštu"
|
||||
FORGOT_FAILED_TO_EMAIL: "Instrukcijų išsiuntimas nepavyko, bandykite dar kartą"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "Negalima atstatyti %s slaptažodžio, nenurodytas el. paštas"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_PASSWORD: "Negalima atstatyti %s slaptažodžio, šis el. paštas susietas su nuotoline paskyra"
|
||||
FORGOT_USERNAME_DOES_NOT_EXIST: "Vartotojas vardu <b>%s</b> neegzistuoja"
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "Negalima tastatyti slaptažodžio. Ši svetainė nenustatyta siųsti el. laiškus"
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "Negalima atstatyti slaptažodžio. Ši svetainė nenustatyta siųsti el. laiškus"
|
||||
FORGOT_EMAIL_SUBJECT: "%s slaptažodžio atstatymo užklausa"
|
||||
FORGOT_EMAIL_BODY: "<h1>Slaptažodis atstatytas</h1><p>Miela(s) %1$s,</p><p><b>%4$s</b> buvo gauta užklausa jūsų slaptažodžio atstatymui.</p><p><br /><a href=\"%2$s\" class=\"btn-primary\">Paspauskite čia norėdami atstatyti slaptažodį</a><br /><br /></p><p>Taip pat galite nukopijuoti sekančią nuorodą į savo naršyklės adreso juostą:</p> <p class=\"word-break\"><a href=\"%2$s\">%2$s</a></p> <p><br />Linkėjimai,<br /><br />%3$s</p>"
|
||||
SESSION: "“Prisiminti mane”-sesija"
|
||||
|
|
|
@ -21,8 +21,6 @@ PLUGIN_LOGIN:
|
|||
RESET_INVALID_LINK: "Ugyldig ilbakestillingslenke, vennligst prøv igjen"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Instruksjoner for å tilbakestille passordet ditt er sendt via e-post"
|
||||
FORGOT_FAILED_TO_EMAIL: "Kunne ikke sende instruksjoner, prøv igjen senere"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "Kan ikke tilbakestille passord for %s, ingen e-postadresse er angitt"
|
||||
FORGOT_USERNAME_DOES_NOT_EXIST: "Bruker med brukernavn <b>%s</ b> eksisterer ikke"
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "Kan ikke tilbakestille passord. Dette nettstedet er ikke konfigurert til å sende e-post"
|
||||
FORGOT_EMAIL_SUBJECT: "Forespørsel om tilbakestilling av passord for %s"
|
||||
FORGOT_EMAIL_BODY: "<h1>Tilbekestilling av passord</h1><p>%1$s,</p><p>En forespørsel om tilbakestilling av passord ble gjort på <b>%4$s</b>.</p><p><br /><a href=\"%2$s\" class=\"btn-primary\">Klikk her for å tilbakestille passordet ditt</a><br /><br /></p><p>Du kan også kopiere følgende nettadresse til nettleserens adressefelt:</p> <p class=\"word-break\"><a href=\"%2$s\">%2$s</a></p> <p><br />Vennlig hilsen,<br /><br />%3$s</p>"
|
||||
|
|
|
@ -17,9 +17,6 @@ PLUGIN_LOGIN:
|
|||
RESET_INVALID_LINK: "Link de recuperação de senha inválido, tente novamente!"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "As instruções para recuperar sua senha foram enviadas para seu e-mail!"
|
||||
FORGOT_FAILED_TO_EMAIL: "Falha ao tentar recuperar a senha, tente novamente mais tarde!"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "Não é possível recuperar a senha para %s, nenhum e-mail inserido!"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_PASSWORD: "Não é possível recuperar a senha para %s, este e-mail já está em uso!"
|
||||
FORGOT_USERNAME_DOES_NOT_EXIST: "O usuário <b>%s</b> não existe!"
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "Não é possível recuperar a senha. Este site não está configurado para enviar e-mails!"
|
||||
FORGOT_EMAIL_SUBJECT: "%s requer recuperação da senha"
|
||||
FORGOT_EMAIL_BODY: "<h1>Recuperação da Senha</h1><p>Olá %1$s,</p><p>Foi feito um pedido no <b>%4$s</b> para recuperar sua senha.</p><p><br /><a href=\"%2$s\" class=\"btn btn-primary\">Clique aqui para recuperar sua senha</a><br /><br /></p><p>Como alternativa, copie a seguinte URL na barra de endereços do navegador:</p> <p class=\"word-break\"><a href=\"%2$s\">%2$s</a></p> <p><br />Atenciosamente,<br /><br />%3$s</p>"
|
||||
|
|
|
@ -19,11 +19,8 @@ PLUGIN_LOGIN:
|
|||
RESET_LINK_EXPIRED: "Время ссылки для сброса истекло, повторите попытку"
|
||||
RESET_PASSWORD_RESET: "Пароль был сброшен"
|
||||
RESET_INVALID_LINK: "Неверная ссылка сброса, повторите попытку"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Инструкции по сбросу пароля были отправлены по электронной почте"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Eсли имя пользователя существует, инструкции по сбросу пароля были отправлены по электронной почте"
|
||||
FORGOT_FAILED_TO_EMAIL: "Не удалось отправить инструкции по электронной почте, повторите попытку позже"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "Не удается сбросить пароль для %s, адресс электронной почты не установлен"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_PASSWORD: "Невозможно сбросить пароль для %s, этот email связан с удаленной учетной записью"
|
||||
FORGOT_USERNAME_DOES_NOT_EXIST: "Пользователь с именем <b>%s</b> не существует"
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "Невозможно сбросить пароль. Этот сайт не настроен для отправки писем"
|
||||
FORGOT_EMAIL_SUBJECT: "%s Запрос на сброс пароля"
|
||||
FORGOT_EMAIL_BODY: "<h1>Восстановление пароля</h1><p>Уважаемый %1$s,</p><p>Был сделан запрос для сброса пароля от <b>%4$s</b>.</p><p><br /><a href=\"%2$s\" class=\"btn-primary\">Нажмите, чтобы сбросить пароль</a><br /><br /></p><p>Или скопируйте следующий URL-адрес в адресную строку браузера:</p> <p class=\"word-break\"><a href=\"%2$s\">%2$s</a></p> <p><br />С уважением,<br /><br />%3$s</p>"
|
||||
|
|
|
@ -19,11 +19,8 @@ PLUGIN_LOGIN:
|
|||
RESET_LINK_EXPIRED: "Час посилання для скидання минув, спробуйте ще раз"
|
||||
RESET_PASSWORD_RESET: "Пароль був скинутий"
|
||||
RESET_INVALID_LINK: "Невірне посилання скидання, спробуйте ще раз"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Інструкції щодо скидання пароля були надіслані по електронній пошті"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Якщо ім'я користувача існує, iнструкції щодо скидання пароля були надіслані по електронній пошті"
|
||||
FORGOT_FAILED_TO_EMAIL: "Не вдалося надіслати інструкції електронною поштою, повторіть спробу пізніше"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "Не вдається скинути пароль для %s, адреса електронної пошти не встановлена"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_PASSWORD: "Неможливо скинути пароль для %s, цей email пов'язаний з віддаленим обліковим записом"
|
||||
FORGOT_USERNAME_DOES_NOT_EXIST: "Користувач з ім'ям <b>%s </b> не існує"
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "Неможливо скинути пароль. Цей сайт не налаштований для надіслання листів"
|
||||
FORGOT_EMAIL_SUBJECT: "%s Запит на скидання пароля"
|
||||
FORGOT_EMAIL_BODY: "<h1>Відновлення паролю</h1><p>Шановний %1$s,</p><p>Був зроблений запит для скидання пароля від <b>%4$s</b>.</p><p><br /><a href=\"%2$s\" class=\"btn-primary\">Нажмите, чтобы сбросить пароль</a><br /><br /></p><p>Или скопируйте следующий URL-адрес в адресную строку браузера:</p> <p class=\"word-break\"><a href=\"%2$s\">%2$s</a></p> <p><br />С уважением,<br /><br />%3$s</p>"
|
||||
|
|
|
@ -17,9 +17,6 @@ PLUGIN_LOGIN:
|
|||
RESET_INVALID_LINK: "重置链接已经使用,请重试"
|
||||
FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "重置密码指引已经发送到您的邮箱。"
|
||||
FORGOT_FAILED_TO_EMAIL: "发送指引邮件失败,请稍后重试。"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "因尚未设置邮箱,无法为 %s 重置密码"
|
||||
FORGOT_CANNOT_RESET_EMAIL_NO_PASSWORD: "因邮箱关联到一个外部帐号,无法为 %s 重置密码。"
|
||||
FORGOT_USERNAME_DOES_NOT_EXIST: "用户 <b>%s</b> 不存在。"
|
||||
FORGOT_EMAIL_NOT_CONFIGURED: "无法重置密码,本站点尚未配置邮件系统。"
|
||||
FORGOT_EMAIL_SUBJECT: "%s 的密码重置请求"
|
||||
FORGOT_EMAIL_BODY: "<h1>密码充值</h1><p>尊敬的 %1$s,</p><p>我们收到一个重置您的 <b>%4$s</b> 密码的请求。</p><p><br /><a href=\"%2$s\" class=\"btn-primary\">点击这里进行重置密码</a><br /><br /></p><p>另外,您也可以复制下面的链接到浏览器地址栏中访问:</p> <p class=\"word-break\"><a href=\"%2$s\">%2$s</a></p> <p><br />此致<br /><br />%3$s</p>"
|
||||
|
|
Loading…
Reference in a new issue