mirror of
https://github.com/getgrav/grav.git
synced 2025-12-05 15:29:57 +01:00
Added support for case sensitive usernames
This commit is contained in:
@@ -2,7 +2,7 @@ title: Flex User Accounts
|
||||
description: Manage your User Accounts in Flex.
|
||||
type: flex-objects
|
||||
|
||||
# Deprecated in Grav 1.7.0-rc.4: file was renamed.
|
||||
# Deprecated in Grav 1.7.0-rc.4: file was renamed to user-accounts.yaml
|
||||
extends@:
|
||||
type: user-accounts
|
||||
context: blueprints://flex
|
||||
|
||||
@@ -113,6 +113,7 @@ config:
|
||||
pattern: '{FOLDER}/{KEY}{EXT}'
|
||||
indexed: true
|
||||
key: username
|
||||
case_sensitive: false
|
||||
search:
|
||||
options:
|
||||
contains: 1
|
||||
|
||||
@@ -15,6 +15,21 @@ use Grav\Framework\Flex\Storage\FileStorage;
|
||||
|
||||
class UserFileStorage extends FileStorage
|
||||
{
|
||||
public $caseSensitive;
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
public function normalizeKey(string $key): string
|
||||
{
|
||||
if ($this->caseSensitive === true) {
|
||||
return $key;
|
||||
}
|
||||
|
||||
return mb_strtolower($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @see FlexStorageInterface::getMediaPath()
|
||||
@@ -40,4 +55,15 @@ class UserFileStorage extends FileStorage
|
||||
$row['access'] = $access;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
protected function initOptions(array $options): void
|
||||
{
|
||||
parent::initOptions($options);
|
||||
|
||||
$this->caseSensitive = $options['case_sensitive'] ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,21 @@ use Grav\Framework\Flex\Storage\FolderStorage;
|
||||
|
||||
class UserFolderStorage extends FolderStorage
|
||||
{
|
||||
public $caseSensitive;
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
public function normalizeKey(string $key): string
|
||||
{
|
||||
if ($this->caseSensitive === true) {
|
||||
return $key;
|
||||
}
|
||||
|
||||
return mb_strtolower($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the row for saving and returns the storage key for the record.
|
||||
*
|
||||
@@ -30,4 +45,15 @@ class UserFolderStorage extends FolderStorage
|
||||
$row['access'] = $access;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
protected function initOptions(array $options): void
|
||||
{
|
||||
parent::initOptions($options);
|
||||
|
||||
$this->caseSensitive = $options['case_sensitive'] ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class UserCollection extends FlexCollection implements UserCollectionInterface
|
||||
public function load($username): UserInterface
|
||||
{
|
||||
if ($username !== '') {
|
||||
$key = mb_strtolower($username);
|
||||
$key = $this->filterUsername($username);
|
||||
$user = $this->get($key);
|
||||
if ($user) {
|
||||
return $user;
|
||||
@@ -84,7 +84,7 @@ class UserCollection extends FlexCollection implements UserCollectionInterface
|
||||
} elseif ($field === 'flex_key') {
|
||||
$user = $this->withKeyField('flex_key')->get($query);
|
||||
} elseif ($field === 'username') {
|
||||
$user = $this->get(mb_strtolower($query));
|
||||
$user = $this->get($this->filterUsername($query));
|
||||
} else {
|
||||
$user = parent::find($query, $field);
|
||||
}
|
||||
@@ -114,4 +114,18 @@ class UserCollection extends FlexCollection implements UserCollectionInterface
|
||||
|
||||
return $exists;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return bool|false|string|string[]|null
|
||||
*/
|
||||
protected function filterUsername(string $key)
|
||||
{
|
||||
$storage = $this->getFlexDirectory()->getStorage();
|
||||
if (method_exists($storage, 'normalizeKey')) {
|
||||
return $storage->normalizeKey($key);
|
||||
}
|
||||
|
||||
return mb_strtolower($key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,12 +53,13 @@ class UserIndex extends FlexIndex
|
||||
/**
|
||||
* @param array $meta
|
||||
* @param array $data
|
||||
* @param FlexStorageInterface $storage
|
||||
*/
|
||||
public static function updateObjectMeta(array &$meta, array $data)
|
||||
public static function updateObjectMeta(array &$meta, array $data, FlexStorageInterface $storage)
|
||||
{
|
||||
// Username can also be number and stored as such.
|
||||
$key = (string)($data['username'] ?? $meta['key'] ?? $meta['storage_key']);
|
||||
$meta['key'] = mb_strtolower($key);
|
||||
$meta['key'] = static::filterUsername($key, $storage);
|
||||
$meta['email'] = isset($data['email']) ? mb_strtolower($data['email']) : null;
|
||||
}
|
||||
|
||||
@@ -73,7 +74,7 @@ class UserIndex extends FlexIndex
|
||||
public function load($username): UserInterface
|
||||
{
|
||||
if ($username !== '') {
|
||||
$key = mb_strtolower($username);
|
||||
$key = static::filterUsername($username, $this->getFlexDirectory()->getStorage());
|
||||
$user = $this->get($key);
|
||||
if ($user) {
|
||||
return $user;
|
||||
@@ -116,7 +117,7 @@ class UserIndex extends FlexIndex
|
||||
} elseif ($field === 'email') {
|
||||
$user = $this->withKeyField('email')->get($query);
|
||||
} elseif ($field === 'username') {
|
||||
$user = $this->get(mb_strtolower($query));
|
||||
$user = $this->get(static::filterUsername($query, $this->getFlexDirectory()->getStorage()));
|
||||
} else {
|
||||
$user = $this->__call('find', [$query, $field]);
|
||||
}
|
||||
@@ -129,6 +130,20 @@ class UserIndex extends FlexIndex
|
||||
return $this->load('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param FlexStorageInterface $storage
|
||||
* @return string
|
||||
*/
|
||||
protected static function filterUsername(string $key, FlexStorageInterface $storage): string
|
||||
{
|
||||
if ($storage && \method_exists($storage, 'normalizeKey')) {
|
||||
return $storage->normalizeKey($key);
|
||||
}
|
||||
|
||||
return mb_strtolower($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FlexStorageInterface $storage
|
||||
* @return CompiledYamlFile|null
|
||||
|
||||
@@ -116,11 +116,11 @@ class User extends Data implements UserInterface
|
||||
}
|
||||
|
||||
if ($file) {
|
||||
$username = $this->get('username');
|
||||
$username = $this->filterUsername($this->get('username'));
|
||||
|
||||
if (!$file->filename()) {
|
||||
$locator = Grav::instance()['locator'];
|
||||
$file->filename($locator->findResource('account://' . mb_strtolower($username) . YAML_EXT, true, true));
|
||||
$file->filename($locator->findResource('account://' . $username . YAML_EXT, true, true));
|
||||
}
|
||||
|
||||
// if plain text password, hash it and remove plain text
|
||||
@@ -176,6 +176,8 @@ class User extends Data implements UserInterface
|
||||
|
||||
/**
|
||||
* Serialize user.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
@@ -272,6 +274,18 @@ class User extends Data implements UserInterface
|
||||
return parent::count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $username
|
||||
* @return string
|
||||
*/
|
||||
protected function filterUsername(string $username): string
|
||||
{
|
||||
return mb_strtolower($username);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getAvatarFile(): ?string
|
||||
{
|
||||
$avatars = $this->get('avatar');
|
||||
|
||||
@@ -45,8 +45,8 @@ class UserCollection implements UserCollectionInterface
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = $grav['locator'];
|
||||
|
||||
// force lowercase of username
|
||||
$username = mb_strtolower($username);
|
||||
// Filter username.
|
||||
$username = $this->filterUsername($username);
|
||||
|
||||
$filename = 'account://' . $username . YAML_EXT;
|
||||
$path = $locator->findResource($filename) ?: $locator->findResource($filename, true, true);
|
||||
@@ -138,4 +138,14 @@ class UserCollection implements UserCollectionInterface
|
||||
|
||||
return count($accounts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $username
|
||||
* @return string
|
||||
*/
|
||||
protected function filterUsername(string $username): string
|
||||
{
|
||||
return mb_strtolower($username);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ use Grav\Framework\Flex\Interfaces\FlexCollectionInterface;
|
||||
use Grav\Framework\Flex\Interfaces\FlexIndexInterface;
|
||||
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
|
||||
use Grav\Framework\Flex\Interfaces\FlexStorageInterface;
|
||||
use Grav\Framework\Object\Interfaces\ObjectCollectionInterface;
|
||||
use Grav\Framework\Object\Interfaces\ObjectInterface;
|
||||
use Grav\Framework\Object\ObjectIndex;
|
||||
use Monolog\Logger;
|
||||
@@ -77,8 +76,9 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
|
||||
*
|
||||
* @param array $meta
|
||||
* @param array $data
|
||||
* @param FlexStorageInterface $storage
|
||||
*/
|
||||
public static function updateObjectMeta(array &$meta, array $data)
|
||||
public static function updateObjectMeta(array &$meta, array $data, FlexStorageInterface $storage)
|
||||
{
|
||||
// For backwards compatibility, no need to call this method when you override this method.
|
||||
static::updateIndexData($meta, $data);
|
||||
@@ -709,7 +709,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
|
||||
if ($keyField !== 'storage_key' && isset($row[$keyField])) {
|
||||
$entry['key'] = $row[$keyField];
|
||||
}
|
||||
static::updateObjectMeta($entry, $row ?? []);
|
||||
static::updateObjectMeta($entry, $row ?? [], $storage);
|
||||
if (isset($row['__ERROR'])) {
|
||||
$entry['__ERROR'] = true;
|
||||
static::onException(new \RuntimeException(sprintf('Object failed to load: %s (%s)', $key,
|
||||
|
||||
@@ -623,7 +623,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
|
||||
if ($meta) {
|
||||
/** @var FlexIndex $indexClass */
|
||||
$indexClass = $this->getFlexDirectory()->getIndexClass();
|
||||
$indexClass::updateObjectMeta($meta, $value);
|
||||
$indexClass::updateObjectMeta($meta, $value, $storage);
|
||||
$this->_meta = $meta;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user