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 #90

Closed
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 @@ public function getPassword()
{
return $this->getResourceManager()->getPassword($this->getResourceId());
}

/**
* Set resource user
*
* @param string $user ACL User
* @return RedisOptions Provides a fluent interface
*/
public function setUser($user)
{
$this->getResourceManager()->setUser($this->getResourceId(), $user);
return $this;
}

/**
* Get resource user
*
* @return string
*/
public function getUser()
{
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];

Check failure on line 787 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:787:9: UnsupportedPropertyReferenceUsage: This reference cannot be analyzed by Psalm. (see https://psalm.dev/321)
$resource['user'] = $user;

Check failure on line 788 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:788:9: MixedArrayAssignment: Cannot access array value on mixed variable $resource['user'] (see https://psalm.dev/117)
$resource['initialized'] = false;
return $this;
}
}
11 changes: 11 additions & 0 deletions test/integration/Laminas/RedisTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,17 @@
'Password was set incorrectly using RedisOptions'
);
}

Check failure on line 331 in test/integration/Laminas/RedisTest.php

View workflow job for this annotation

GitHub Actions / QA Checks (PHPCodeSniffer [8.1, locked], ubuntu-latest, laminas/laminas-continuous-integration-ac...

Whitespace found at end of line
public function testOptionsGetSetUser(): void
{
$user = 'dummyuser';
$this->options->setUser($user);
$this->assertEquals(
$user,
$this->options->getUser(),
'User was set incorrectly using RedisOptions'
);
}

public function testTouchItem(): void
{
Expand Down
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