Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature redis user #89

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion src/RedisOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Laminas\Cache\Storage\Adapter;

use Laminas\Cache\Exception;
use Laminas\Cache\Storage\Adapter\RedisResourceManager;

use function sprintf;
use function strlen;
Expand Down Expand Up @@ -261,4 +260,26 @@
{
return $this->getResourceManager()->getPassword($this->getResourceId());
}

/**
* Set resource user
*
* @param string $user ACL User
* @return RedisOptions Provides a fluent interface
*/
public function setUser($user)

Check failure on line 270 in src/RedisOptions.php

View workflow job for this annotation

GitHub Actions / QA Checks (Psalm [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-action@v1, ...

PossiblyUnusedMethod

src/RedisOptions.php:270:21: PossiblyUnusedMethod: Cannot find any calls to method Laminas\Cache\Storage\Adapter\RedisOptions::setUser (see https://psalm.dev/087)
{
$this->getResourceManager()->setUser($this->getResourceId(), $user);
return $this;
}

/**
* Get resource user
*
* @return string
*/
public function getUser()

Check failure on line 281 in src/RedisOptions.php

View workflow job for this annotation

GitHub Actions / QA Checks (Psalm [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-action@v1, ...

PossiblyUnusedMethod

src/RedisOptions.php:281:21: PossiblyUnusedMethod: Cannot find any calls to method Laminas\Cache\Storage\Adapter\RedisOptions::getUser (see https://psalm.dev/087)
{
return $this->getResourceManager()->getUser($this->getResourceId());
}
}
80 changes: 78 additions & 2 deletions src/RedisResourceManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,22 @@
return $resource['password'];
}

/**
* Get redis resource user
*
* @param string $id
* @return string
*/
public function getUser($id)
{
if (! $this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}

$resource = &$this->resources[$id];
return $resource['user'];

Check failure on line 139 in src/RedisResourceManager.php

View workflow job for this annotation

GitHub Actions / QA Checks (Psalm [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-action@v1, ...

MixedArrayAccess

src/RedisResourceManager.php:139:16: MixedArrayAccess: Cannot access array value on mixed variable $resource (see https://psalm.dev/051)

Check failure on line 139 in src/RedisResourceManager.php

View workflow job for this annotation

GitHub Actions / QA Checks (Psalm [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-action@v1, ...

MixedReturnStatement

src/RedisResourceManager.php:139:16: MixedReturnStatement: Could not infer a return type (see https://psalm.dev/138)
}

/**
* Gets a redis resource
*
Expand Down Expand Up @@ -279,6 +295,36 @@
return $server['pass'] ?? null;
}

/**
* Extract password to be used on connection
*
* @param mixed $resource
* @param mixed $serverUri
* @return string|null

Check failure on line 303 in src/RedisResourceManager.php

View workflow job for this annotation

GitHub Actions / QA Checks (Psalm [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-action@v1, ...

MixedInferredReturnType

src/RedisResourceManager.php:303:16: MixedInferredReturnType: Could not verify return type 'null|string' for Laminas\Cache\Storage\Adapter\RedisResourceManager::extractUser (see https://psalm.dev/047)
*/
protected function extractUser($resource, $serverUri)
{
if (! empty($resource['user'])) {
return $resource['user'];

Check failure on line 308 in src/RedisResourceManager.php

View workflow job for this annotation

GitHub Actions / QA Checks (Psalm [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-action@v1, ...

MixedArrayAccess

src/RedisResourceManager.php:308:20: MixedArrayAccess: Cannot access array value on mixed variable $resource (see https://psalm.dev/051)

Check failure on line 308 in src/RedisResourceManager.php

View workflow job for this annotation

GitHub Actions / QA Checks (Psalm [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-action@v1, ...

MixedReturnStatement

src/RedisResourceManager.php:308:20: MixedReturnStatement: Could not infer a return type (see https://psalm.dev/138)
}

if (! is_string($serverUri)) {
return null;
}

// parse server from URI host{:?port}
$server = trim($serverUri);

if (strpos($server, '/') === 0) {
return null;
}

//non unix domain socket connection
$server = parse_url($server);

return $server['user'] ?? null;
}

/**
* Connects to redis server
*
Expand Down Expand Up @@ -315,7 +361,9 @@
}

$resource['initialized'] = true;
if ($resource['password']) {
if ($resource['user'] && $resource['password']) {
$redis->auth([$resource['user'], $resource['password']]);
} elseif ($resource['password']) {
$redis->auth($resource['password']);
}
$redis->select($resource['database']);
Expand All @@ -339,6 +387,7 @@
'persistent_id' => '',
'lib_options' => [],
'server' => [],
'user' => '',
'password' => '',
'database' => 0,
'resource' => null,
Expand All @@ -361,6 +410,7 @@
// #6495 note: order is important here, as `normalizeServer` applies destructive
// transformations on $resource['server']
$resource['password'] = $this->extractPassword($resource, $resource['server']);
$resource['user'] = $this->extractUser($resource, $resource['server']);

$this->normalizeServer($resource['server']);
} else {
Expand Down Expand Up @@ -426,7 +476,7 @@
* Get the persistent id
*
* @param string $id
* @return string

Check failure on line 479 in src/RedisResourceManager.php

View workflow job for this annotation

GitHub Actions / QA Checks (Psalm [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-action@v1, ...

MixedInferredReturnType

src/RedisResourceManager.php:479:16: MixedInferredReturnType: Could not verify return type 'string' for Laminas\Cache\Storage\Adapter\RedisResourceManager::getPersistentId (see https://psalm.dev/047)
* @throws Exception\RuntimeException
*/
public function getPersistentId($id)
Expand Down Expand Up @@ -624,12 +674,17 @@
$resource = &$this->resources[$id];
$resource['password'] = $this->extractPassword($resource, $server);

$resource['user'] = $this->extractUser($resource, $server);

Check failure on line 677 in src/RedisResourceManager.php

View workflow job for this annotation

GitHub Actions / QA Checks (Psalm [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-action@v1, ...

MixedArrayAssignment

src/RedisResourceManager.php:677:9: MixedArrayAssignment: Cannot access array value on mixed variable $resource['user'] (see https://psalm.dev/117)

if ($resource['resource'] instanceof RedisResource) {
$resourceParams = ['server' => $server];

if (! empty($resource['password'])) {
$resourceParams['password'] = $resource['password'];
}
if (! empty($resource['user'])) {
$resourceParams['user'] = $resource['user'];
}

$this->setResource($id, $resourceParams);
} else {
Expand All @@ -644,7 +699,7 @@
*
* @param string $id
* @param string $password
* @return RedisResource
* @return RedisResourceManager
*/
public function setPassword($id, $password)
{
Expand Down Expand Up @@ -677,7 +732,7 @@
]);
}

$resource = &$this->resources[$id];

Check failure on line 735 in src/RedisResourceManager.php

View workflow job for this annotation

GitHub Actions / QA Checks (Psalm [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-action@v1, ...

UnsupportedPropertyReferenceUsage

src/RedisResourceManager.php:735:9: UnsupportedPropertyReferenceUsage: This reference cannot be analyzed by Psalm. (see https://psalm.dev/321)
$redis = $resource['resource'];
if ($redis instanceof RedisResource && $resource['initialized']) {
try {
Expand Down Expand Up @@ -713,4 +768,25 @@

return $info;
}

/**
* Set redis user
*
* @param string $id
* @param string $user
* @return RedisResourceManager
*/
public function setUser($id, $user)
{
if (! $this->hasResource($id)) {
return $this->setResource($id, [
'user' => $user,
]);
}

$resource = &$this->resources[$id];
$resource['user'] = $user;
$resource['initialized'] = false;
return $this;
}
}
52 changes: 52 additions & 0 deletions test/unit/RedisResourceManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public function testSetServerWithPasswordInUri(): void
$this->assertEquals('testhost', $server['host']);
$this->assertEquals(1234, $server['port']);
$this->assertEquals('dummypass', $this->resourceManager->getPassword($dummyResId));
$this->assertEquals('dummyuser', $this->resourceManager->getUser($dummyResId));
}

/**
Expand All @@ -71,6 +72,27 @@ public function testSetServerWithPasswordInParameters(): void
$this->assertEquals('testhost', $server['host']);
$this->assertEquals(1234, $server['port']);
$this->assertEquals('abcd1234', $this->resourceManager->getPassword($dummyResId2));
$this->assertEquals('dummyuser', $this->resourceManager->getUser($dummyResId2));
}

public function testSetServerWithPasswordInParametersAndNoUser(): void
{
$server = 'redis://testhost:1234';
$dummyResId2 = '12345678901';
$resource = [
'persistent_id' => 'my_connection_name',
'server' => $server,
'password' => 'abcd1234',
];

$this->resourceManager->setResource($dummyResId2, $resource);

$server = $this->resourceManager->getServer($dummyResId2);

$this->assertEquals('testhost', $server['host']);
$this->assertEquals(1234, $server['port']);
$this->assertEquals('abcd1234', $this->resourceManager->getPassword($dummyResId2));
$this->assertEquals('', $this->resourceManager->getUser($dummyResId2));
}

/**
Expand Down Expand Up @@ -287,6 +309,36 @@ public function testWillCatchAuthDuringConnectException(): void
$this->resourceManager->getResource('default');
}

public function testWillCatchAuthDuringConnectExceptionWithUser(): void
{
$redis = $this->createMock(Redis::class);

$redis
->method('connect')
->willReturn(true);

$redis
->expects(self::atLeastOnce())
->method('auth')
->with(['dummyuser', 'secret'])
->willThrowException(new RedisException('test'));

$this->resourceManager->setResource(
'default',
[
'resource' => $redis,
'initialized' => false,
'server' => 'somewhere:6379',
'password' => 'secret',
'user' => 'dummyuser',
]
);

$this->expectException(RedisRuntimeException::class);
$this->expectExceptionMessage('test');
$this->resourceManager->getResource('default');
}

public function testWillCatchSelectDatabaseException(): void
{
$redis = $this->createMock(Redis::class);
Expand Down