Skip to content

Commit

Permalink
refactor: keep new methods in a single place, wrap some calls into tr…
Browse files Browse the repository at this point in the history
…ansaction
  • Loading branch information
shpran committed Oct 17, 2023
1 parent c84aa90 commit 9839ed7
Showing 1 changed file with 181 additions and 172 deletions.
353 changes: 181 additions & 172 deletions model/DataBaseAccess.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,187 @@ public function getResourceTree(core_kernel_classes_Resource $resource): array
);
}

public function getPermissionsByUsersAndResources(array $userIds, array $resourceIds): array
{
// Permissions for an empty set of resources must be an empty array
if (empty($resourceIds)) {
return [];
}

$inQueryResources = implode(',', array_fill(0, count($resourceIds), '?'));
$inQueryUsers = implode(',', array_fill(0, count($userIds), '?'));

$query = <<<SQL
SELECT
resource_id,
user_id,
privilege
FROM data_privileges
WHERE resource_id IN ($inQueryResources)
AND user_id IN ($inQueryUsers)
SQL;

$results = $this->fetchQuery($query, [...$resourceIds, ...$userIds]);

// If resource doesn't have permission don't return null
$data = array_fill_keys($resourceIds, []);

foreach ($results as $result) {
$data[$result[self::COLUMN_RESOURCE_ID]][$result[self::COLUMN_USER_ID]][] = $result[self::COLUMN_PRIVILEGE];
}

return $data;
}

public function addResourcesPermissions(array $resources): void
{
$insert = [];

foreach ($resources as $resource) {
foreach ($resource['permissions']['add'] as $userId => $addPermissions) {
if (empty($addPermissions)) {
continue;
}

foreach ($addPermissions as $permission) {
$insert[] = [
self::COLUMN_USER_ID => $userId,
self::COLUMN_RESOURCE_ID => $resource['id'],
self::COLUMN_PRIVILEGE => $permission,
];
}
}
}

$this->insertPermissions($insert);

foreach ($insert as $inserted) {
$this->getEventManager()->trigger(
new DacAddedEvent(
$inserted[self::COLUMN_USER_ID],
$inserted[self::COLUMN_RESOURCE_ID],
(array) $inserted[self::COLUMN_PRIVILEGE]
)
);
}
}

public function removeResourcesPermissions(array $resources): void
{
$groupedRemove = [];
$eventsData = [];

foreach ($resources as $resource) {
foreach ($resource['permissions']['remove'] as $userId => $removePermissions) {
if (empty($removePermissions)) {
continue;
}

$idString = implode($removePermissions);

$groupedRemove[$userId][$idString]['resources'][] = $resource['id'];
$groupedRemove[$userId][$idString]['privileges'] = $removePermissions;

$eventsData[] = [
'userId' => $userId,
'resourceId' => $resource['id'],
'privileges' => $removePermissions,
];
}
}

foreach ($groupedRemove as $userId => $priviligeGroups) {
foreach ($priviligeGroups as $privilegeGroup) {
$inQueryPrivilege = implode(',', array_fill(0, count($privilegeGroup['privileges']), ' ? '));
$inQueryResources = implode(',', array_fill(0, count($privilegeGroup['resources']), ' ? '));

$query = <<<SQL
DELETE
FROM data_privileges
WHERE resource_id IN ($inQueryResources)
AND privilege IN ($inQueryPrivilege)
AND user_id = ?
SQL;

$params = array_merge(
array_values($privilegeGroup['resources']),
array_values($privilegeGroup['privileges']),
[$userId]
);

$this->getPersistence()->exec($query, $params);
}
}

foreach ($eventsData as $eventData) {
$this->getEventManager()->trigger(new DacRemovedEvent(
$eventData['userId'],
$eventData['resourceId'],
$eventData['privileges']
));
}
}

public function addReadAccess(array $addAccessList): bool
{
if (empty($addAccessList)) {
return true;
}

$values = [];

try {
foreach ($addAccessList as $resourceId => $usersIds) {
foreach ($usersIds as $userId) {
$values[] = [
'user_id' => $userId,
'resource_id' => $resourceId,
'privilege' => PermissionProvider::PERMISSION_READ
];
}
}

$this->insertPermissions($values);

return true;
} catch (Throwable $exception) {
$this->logError('Error when adding READ access: ' . $exception->getMessage());

return false;
}
}

public function revokeAccess(array $revokeAccessList): bool
{
if (empty($revokeAccessList)) {
return true;
}

$persistence = $this->getPersistence();

try {
$persistence->transactional(static function () use ($revokeAccessList, $persistence): void {
foreach ($revokeAccessList as $resourceId => $usersIds) {
$inQueryUsers = implode(',', array_fill(0, count($usersIds), ' ? '));

$persistence->exec(
"DELETE FROM data_privileges WHERE resource_id = ? AND user_id IN ($inQueryUsers)",
[
$resourceId,
...$usersIds,
]
);
}
});

return true;
} catch (Throwable $exception) {
$this->logError('Error when revoking access: ' . $exception->getMessage());

return false;
}
}

/**
* Retrieve info on users having privileges on a set of resources
*
Expand Down Expand Up @@ -226,38 +407,6 @@ public function getPermissions(array $userIds, array $resourceIds): array
return $returnValue;
}

public function getPermissionsByUsersAndResources(array $userIds, array $resourceIds): array
{
// Permissions for an empty set of resources must be an empty array
if (empty($resourceIds)) {
return [];
}

$inQueryResources = implode(',', array_fill(0, count($resourceIds), '?'));
$inQueryUsers = implode(',', array_fill(0, count($userIds), '?'));

$query = <<<SQL
SELECT
resource_id,
user_id,
privilege
FROM data_privileges
WHERE resource_id IN ($inQueryResources)
AND user_id IN ($inQueryUsers)
SQL;

$results = $this->fetchQuery($query, [...$resourceIds, ...$userIds]);

// If resource doesn't have permission don't return null
$data = array_fill_keys($resourceIds, []);

foreach ($results as $result) {
$data[$result[self::COLUMN_RESOURCE_ID]][$result[self::COLUMN_USER_ID]][] = $result[self::COLUMN_PRIVILEGE];
}

return $data;
}

public function getResourcesPermissions(array $resourceIds)
{
// Return an empty array for resources not having permissions data
Expand Down Expand Up @@ -340,39 +489,6 @@ public function addMultiplePermissions(array $permissionData)
}
}

public function addResourcesPermissions(array $resources): void
{
$insert = [];

foreach ($resources as $resource) {
foreach ($resource['permissions']['add'] as $userId => $addPermissions) {
if (empty($addPermissions)) {
continue;
}

foreach ($addPermissions as $permission) {
$insert[] = [
self::COLUMN_USER_ID => $userId,
self::COLUMN_RESOURCE_ID => $resource['id'],
self::COLUMN_PRIVILEGE => $permission,
];
}
}
}

$this->insertPermissions($insert);

foreach ($insert as $inserted) {
$this->getEventManager()->trigger(
new DacAddedEvent(
$inserted[self::COLUMN_USER_ID],
$inserted[self::COLUMN_RESOURCE_ID],
(array) $inserted[self::COLUMN_PRIVILEGE]
)
);
}
}

/**
* Get the permissions to resource
*
Expand Down Expand Up @@ -432,57 +548,6 @@ public function removePermissions($user, $resourceId, $rights)
return true;
}

public function addReadAccess(array $addAccessList): bool
{
if (empty($addAccessList)) {
return true;
}

$values = [];
$valuesQuery = [];

foreach ($addAccessList as $resourceId => $usersIds) {
foreach ($usersIds as $userId) {
$values = array_merge($values, [$userId, $resourceId, PermissionProvider::PERMISSION_READ]);
$valuesQuery[] = '(?, ?, ?)';
}
}

$statement = sprintf(
'INSERT INTO data_privileges (user_id, resource_id, privilege) VALUES %s',
implode(', ', $valuesQuery)
);

return $this->getPersistence()->exec($statement, $values);
}

public function revokeAccess(array $revokeAccessList): bool
{
if (empty($revokeAccessList)) {
return true;
}

try {
foreach ($revokeAccessList as $resourceId => $usersIds) {
$inQueryUsers = implode(',', array_fill(0, count($usersIds), ' ? '));

$this->getPersistence()->exec(
"DELETE FROM data_privileges WHERE resource_id = ? AND user_id IN ($inQueryUsers)",
[
$resourceId,
...$usersIds,
]
);
}

return true;
} catch (Throwable $exception) {
$this->logError('Error when revoking access: ' . $exception->getMessage());

return false;
}
}

/**
* Remove batch permissions
*
Expand Down Expand Up @@ -546,62 +611,6 @@ public function removeMultiplePermissions(array $data)
}
}

public function removeResourcesPermissions(array $resources): void
{
$groupedRemove = [];
$eventsData = [];

foreach ($resources as $resource) {
foreach ($resource['permissions']['remove'] as $userId => $removePermissions) {
if (empty($removePermissions)) {
continue;
}

$idString = implode($removePermissions);

$groupedRemove[$userId][$idString]['resources'][] = $resource['id'];
$groupedRemove[$userId][$idString]['privileges'] = $removePermissions;

$eventsData[] = [
'userId' => $userId,
'resourceId' => $resource['id'],
'privileges' => $removePermissions,
];
}
}

foreach ($groupedRemove as $userId => $priviligeGroups) {
foreach ($priviligeGroups as $privilegeGroup) {
$inQueryPrivilege = implode(',', array_fill(0, count($privilegeGroup['privileges']), ' ? '));
$inQueryResources = implode(',', array_fill(0, count($privilegeGroup['resources']), ' ? '));

$query = <<<SQL
DELETE
FROM data_privileges
WHERE resource_id IN ($inQueryResources)
AND privilege IN ($inQueryPrivilege)
AND user_id = ?
SQL;

$params = array_merge(
array_values($privilegeGroup['resources']),
array_values($privilegeGroup['privileges']),
[$userId]
);

$this->getPersistence()->exec($query, $params);
}
}

foreach ($eventsData as $eventData) {
$this->getEventManager()->trigger(new DacRemovedEvent(
$eventData['userId'],
$eventData['resourceId'],
$eventData['privileges']
));
}
}

/**
* Remove all permissions from a resource
*
Expand Down

0 comments on commit 9839ed7

Please sign in to comment.