Skip to content

Commit

Permalink
feat(Contexts): API endpoint for Contexts ownership transfer
Browse files Browse the repository at this point in the history
- also emits an Event for admin_audit

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
  • Loading branch information
blizzz authored and juliusknorr committed Mar 6, 2024
1 parent 7df8939 commit 5a0d0b6
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 0 deletions.
1 change: 1 addition & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
['name' => 'Context#show', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'GET'],
['name' => 'Context#create', 'url' => '/api/2/contexts', 'verb' => 'POST'],
['name' => 'Context#update', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'PUT'],
['name' => 'Context#transfer', 'url' => '/api/2/contexts/{contextId}/transfer', 'verb' => 'PUT'],
['name' => 'Context#addNode', 'url' => '/api/2/contexts/{contextId}/nodes', 'verb' => 'POST'],
['name' => 'Context#removeNode', 'url' => '/api/2/contexts/{contextId}/nodes/{nodeRelId}', 'verb' => 'DELETE'],
['name' => 'Context#updateContentOrder', 'url' => '/api/2/contexts/{contextId}/pages/{pageId}', 'verb' => 'PUT'],
Expand Down
19 changes: 19 additions & 0 deletions lib/Controller/ContextController.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,25 @@ public function update(int $contextId, ?string $name, ?string $iconName, ?string
}
}

/**
* @NoAdminRequired
* @CanManageContext
*
* @psalm-param int<0, max> $contextId
* @psalm-param int<0, 0> $newOwnerType
*/
public function transfer(int $contextId, string $newOwnerId, int $newOwnerType = 0): DataResponse {
try {
return new DataResponse($this->contextService->transfer($contextId, $newOwnerId, $newOwnerType)->jsonSerialize());
} catch (Exception|MultipleObjectsReturnedException $e) {
return $this->handleError($e);
} catch (DoesNotExistException $e) {
return $this->handleNotFoundError(new NotFoundError($e->getMessage(), $e->getCode(), $e));
} catch (BadRequestError $e) {
return $this->handleBadRequestError($e);
}
}

/**
* @NoAdminRequired
* @CanManageNode
Expand Down
45 changes: 45 additions & 0 deletions lib/Service/ContextService.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@
use OCA\Tables\Db\PageContent;
use OCA\Tables\Db\PageContentMapper;
use OCA\Tables\Db\PageMapper;
use OCA\Tables\Errors\BadRequestError;
use OCA\Tables\Errors\InternalError;
use OCA\Tables\Errors\PermissionError;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\DB\Exception;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUserManager;
use OCP\Log\Audit\CriticalActionPerformedEvent;
use Psr\Log\LoggerInterface;

class ContextService {
Expand All @@ -30,6 +34,8 @@ class ContextService {
private PageMapper $pageMapper;
private PageContentMapper $pageContentMapper;
private PermissionsService $permissionsService;
private IUserManager $userManager;
private IEventDispatcher $eventDispatcher;

public function __construct(
ContextMapper $contextMapper,
Expand All @@ -38,6 +44,8 @@ public function __construct(
PageContentMapper $pageContentMapper,
LoggerInterface $logger,
PermissionsService $permissionsService,
IUserManager $userManager,
IEventDispatcher $eventDispatcher,
bool $isCLI,
) {
$this->contextMapper = $contextMapper;
Expand All @@ -47,6 +55,8 @@ public function __construct(
$this->pageMapper = $pageMapper;
$this->pageContentMapper = $pageContentMapper;
$this->permissionsService = $permissionsService;
$this->userManager = $userManager;
$this->eventDispatcher = $eventDispatcher;
}

/**
Expand Down Expand Up @@ -126,6 +136,41 @@ public function update(int $contextId, ?string $name, ?string $iconName, ?string
return $this->contextMapper->update($context);
}

/**
* @throws MultipleObjectsReturnedException
* @throws DoesNotExistException
* @throws Exception
* @throws BadRequestError
*/
public function transfer(int $contextId, string $newOwnerId, int $newOwnerType): Context {
$context = $this->contextMapper->findById($contextId);

// the owner type check can be dropped as soon as NC 29 is the lowest supported version,
// as the int range as defined in the Controller will be enforced by the Http/Dispatcher.
if ($newOwnerType !== Application::OWNER_TYPE_USER) {
throw new BadRequestError('Unsupported owner type');
}

if (!$this->userManager->userExists($newOwnerId)) {
throw new BadRequestError('User does not exist');
}

$context->setOwnerId($newOwnerId);
$context->setOwnerType($newOwnerType);

$context = $this->contextMapper->update($context);

$auditEvent = new CriticalActionPerformedEvent(
sprintf('Tables application with ID %d was transferred to user %s',
$contextId, $newOwnerId,
)
);

$this->eventDispatcher->dispatchTyped($auditEvent);

return $context;
}

/**
* @throws MultipleObjectsReturnedException
* @throws DoesNotExistException
Expand Down

0 comments on commit 5a0d0b6

Please sign in to comment.