aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElmar Ludwig <elmar.ludwig@uni-osnabrueck.de>2023-11-06 15:15:21 +0000
committerElmar Ludwig <elmar.ludwig@uni-osnabrueck.de>2023-11-06 15:15:21 +0000
commit4b160476327ecb893c08ce4deb29ce1180f6e0ef (patch)
tree729dd07d746e78926566100a88ac01310222b76f
parent279363bcfb5887658956a09519be04387c37155d (diff)
add implementation for /institutes/{id}/memberships route, fixes #3429
Closes #3429 Merge request studip/studip!2334
-rw-r--r--lib/classes/JsonApi/RouteMap.php1
-rw-r--r--lib/classes/JsonApi/Routes/InstituteMemberships/InstituteMembershipsShow.php2
-rw-r--r--lib/classes/JsonApi/Routes/Institutes/Authority.php9
-rw-r--r--lib/classes/JsonApi/Routes/Institutes/InstituteMembershipsIndex.php80
-rw-r--r--lib/classes/JsonApi/Schemas/Institute.php7
-rw-r--r--tests/jsonapi/InstituteMembershipsIndexTest.php41
6 files changed, 139 insertions, 1 deletions
diff --git a/lib/classes/JsonApi/RouteMap.php b/lib/classes/JsonApi/RouteMap.php
index e779e8b..2eb33a8 100644
--- a/lib/classes/JsonApi/RouteMap.php
+++ b/lib/classes/JsonApi/RouteMap.php
@@ -253,6 +253,7 @@ class RouteMap
$group->get('/institutes/{id}', Routes\Institutes\InstitutesShow::class);
$group->get('/institutes', Routes\Institutes\InstitutesIndex::class);
+ $group->get('/institutes/{id}/memberships', Routes\Institutes\InstituteMembershipsIndex::class);
$group->get('/institutes/{id}/status-groups', Routes\Institutes\StatusGroupsOfInstitutes::class);
}
diff --git a/lib/classes/JsonApi/Routes/InstituteMemberships/InstituteMembershipsShow.php b/lib/classes/JsonApi/Routes/InstituteMemberships/InstituteMembershipsShow.php
index 7662af3..13e0dd4 100644
--- a/lib/classes/JsonApi/Routes/InstituteMemberships/InstituteMembershipsShow.php
+++ b/lib/classes/JsonApi/Routes/InstituteMemberships/InstituteMembershipsShow.php
@@ -22,7 +22,7 @@ class InstituteMembershipsShow extends JsonApiController
}
$user = $this->getUser($request);
- if ($user->id !== $membership->user_id) {
+ if ($user->id !== $membership->user_id && !get_visibility_by_id($membership->user_id)) {
throw new AuthorizationFailedException();
}
diff --git a/lib/classes/JsonApi/Routes/Institutes/Authority.php b/lib/classes/JsonApi/Routes/Institutes/Authority.php
index b3fe9b1..c6ee43b 100644
--- a/lib/classes/JsonApi/Routes/Institutes/Authority.php
+++ b/lib/classes/JsonApi/Routes/Institutes/Authority.php
@@ -2,6 +2,7 @@
namespace JsonApi\Routes\Institutes;
+use Institute;
use User;
class Authority
@@ -9,6 +10,14 @@ class Authority
/**
* @SuppressWarnings(PHPMD.Superglobals)
*/
+ public static function canEditInstitute(User $user, Institute $institute)
+ {
+ return $GLOBALS['perm']->have_studip_perm('admin', $institute->id, $user->id);
+ }
+
+ /**
+ * @SuppressWarnings(PHPMD.Superglobals)
+ */
public static function canIndexInstitutesOfUser(User $observer, User $user)
{
return $GLOBALS['perm']->have_perm('admin', $observer->id)
diff --git a/lib/classes/JsonApi/Routes/Institutes/InstituteMembershipsIndex.php b/lib/classes/JsonApi/Routes/Institutes/InstituteMembershipsIndex.php
new file mode 100644
index 0000000..9184fd9
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Institutes/InstituteMembershipsIndex.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace JsonApi\Routes\Institutes;
+
+use Psr\Http\Message\ServerRequestInterface as Request;
+use Psr\Http\Message\ResponseInterface as Response;
+use JsonApi\Errors\AuthorizationFailedException;
+use JsonApi\Errors\BadRequestException;
+use JsonApi\Errors\RecordNotFoundException;
+use JsonApi\JsonApiController;
+use JsonApi\Schemas\InstituteMember;
+
+/**
+ * Returns all institute-memberships of the institute.
+ */
+class InstituteMembershipsIndex extends JsonApiController
+{
+ protected $allowedFilteringParameters = ['permission'];
+
+ protected $allowedIncludePaths = [InstituteMember::REL_INSTITUTE, InstituteMember::REL_USER];
+
+ protected $allowedPagingParameters = ['offset', 'limit'];
+
+ /**
+ * @SuppressWarnings(PHPMD.UnusedFormalParameters)
+ */
+ public function __invoke(Request $request, Response $response, $args)
+ {
+ $institute = \Institute::find($args['id']);
+ if (!$institute) {
+ throw new RecordNotFoundException();
+ }
+
+ $this->validateFilters();
+
+ $user = $this->getUser($request);
+ $memberships = $this->getMemberships($institute, $user, $this->getFilters());
+
+ list($offset, $limit) = $this->getOffsetAndLimit();
+
+ return $this->getPaginatedContentResponse($memberships->limit($offset, $limit), count($memberships));
+ }
+
+ private function getMemberships(\Institute $institute, \User $user, array $filters)
+ {
+ $memberships = $institute->members;
+
+ $visibleMemberships = Authority::canEditInstitute($user, $institute)
+ ? $memberships
+ : $memberships->filter(function ($membership) use ($user) {
+ return $membership->user_id === $user->id || get_visibility_by_id($membership->user_id);
+ });
+
+ return isset($filters['permission'])
+ ? $visibleMemberships->filter(function ($membership) use ($filters) {
+ return $membership->inst_perms === $filters['permission'];
+ })
+ : $visibleMemberships;
+ }
+
+ private function validateFilters()
+ {
+ $filtering = $this->getQueryParameters()->getFilteringParameters() ?? [];
+
+ if (array_key_exists('permission', $filtering)) {
+ if (!in_array($filtering['permission'], ['user', 'autor', 'tutor', 'dozent', 'admin'])) {
+ throw new BadRequestException('Filter `permission` must be one of `user`, `autor`, `tutor`, `dozent`, `admin`.');
+ }
+ }
+ }
+
+ private function getFilters()
+ {
+ $filtering = $this->getQueryParameters()->getFilteringParameters() ?? [];
+
+ $filters['permission'] = $filtering['permission'] ?? null;
+
+ return $filters;
+ }
+}
diff --git a/lib/classes/JsonApi/Schemas/Institute.php b/lib/classes/JsonApi/Schemas/Institute.php
index d3eda4a..c1775b1 100644
--- a/lib/classes/JsonApi/Schemas/Institute.php
+++ b/lib/classes/JsonApi/Schemas/Institute.php
@@ -12,6 +12,7 @@ class Institute extends SchemaProvider
const REL_BLUBBER = 'blubber-threads';
const REL_FILES = 'file-refs';
const REL_FOLDERS = 'folders';
+ const REL_MEMBERSHIPS = 'memberships';
const REL_STATUS_GROUPS = 'status-groups';
public function getId($institute): ?string
@@ -60,6 +61,12 @@ class Institute extends SchemaProvider
],
];
+ $relationships[self::REL_MEMBERSHIPS] = [
+ self::RELATIONSHIP_LINKS => [
+ Link::RELATED => $this->getRelationshipRelatedLink($resource, self::REL_MEMBERSHIPS),
+ ],
+ ];
+
$relationships = $this->addStatusGroupsRelationship(
$relationships,
$resource,
diff --git a/tests/jsonapi/InstituteMembershipsIndexTest.php b/tests/jsonapi/InstituteMembershipsIndexTest.php
new file mode 100644
index 0000000..f9ddf9d
--- /dev/null
+++ b/tests/jsonapi/InstituteMembershipsIndexTest.php
@@ -0,0 +1,41 @@
+<?php
+
+use JsonApi\Routes\Institutes\InstituteMembershipsIndex;
+
+class InstituteMembershipsIndexTest extends \Codeception\Test\Unit
+{
+ /**
+ * @var \UnitTester
+ */
+ protected $tester;
+
+ protected function _before()
+ {
+ \DBManager::getInstance()->setConnection('studip', $this->getModule('\\Helper\\StudipDb')->dbh);
+ }
+
+ protected function _after()
+ {
+ }
+
+ public function testIndexMemberships()
+ {
+ $credentials = $this->tester->getCredentialsForTestAutor();
+ $instituteId = '2560f7c7674942a7dce8eeb238e15d93';
+
+ $institute = \Institute::find($instituteId);
+
+ $app = $this->tester->createApp($credentials, 'get', '/institutes/{id}/memberships', InstituteMembershipsIndex::class);
+
+ $requestBuilder = $this->tester->createRequestBuilder($credentials);
+ $requestBuilder->setUri('/institutes/'.$instituteId.'/memberships')->fetch();
+
+ $response = $this->tester->sendMockRequest($app, $requestBuilder->getRequest());
+
+ $this->tester->assertTrue($response->isSuccessfulDocument([200]));
+ $document = $response->document();
+ $this->tester->assertTrue($document->isResourceCollectionDocument());
+ $resources = $document->primaryResources();
+ $this->tester->assertCount(count($institute->members), $resources);
+ }
+}