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

Contexts API #861

Merged
merged 15 commits into from
Mar 12, 2024
Merged
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
2 changes: 2 additions & 0 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Have a good time and manage whatever you want.
<command>OCA\Tables\Command\RemoveTable</command>
<command>OCA\Tables\Command\RenameTable</command>
<command>OCA\Tables\Command\ChangeOwnershipTable</command>
<command>OCA\Tables\Command\ListContexts</command>
<command>OCA\Tables\Command\ShowContext</command>
<command>OCA\Tables\Command\Clean</command>
<command>OCA\Tables\Command\CleanLegacy</command>
<command>OCA\Tables\Command\TransferLegacyRows</command>
Expand Down
8 changes: 8 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,13 @@

['name' => 'ApiFavorite#create', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'POST', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']],
['name' => 'ApiFavorite#destroy', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'DELETE', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']],
['name' => 'Context#index', 'url' => '/api/2/contexts', 'verb' => 'GET'],
blizzz marked this conversation as resolved.
Show resolved Hide resolved
['name' => 'Context#show', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'GET'],
blizzz marked this conversation as resolved.
Show resolved Hide resolved
['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'],
]
];
5 changes: 5 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use OCA\Tables\Listener\LoadAdditionalListener;
use OCA\Tables\Listener\TablesReferenceListener;
use OCA\Tables\Listener\UserDeletedListener;
use OCA\Tables\Middleware\PermissionMiddleware;
use OCA\Tables\Reference\ContentReferenceProvider;
use OCA\Tables\Reference\LegacyReferenceProvider;
use OCA\Tables\Reference\ReferenceProvider;
Expand All @@ -32,6 +33,8 @@ class Application extends App implements IBootstrap {
public const NODE_TYPE_TABLE = 0;
public const NODE_TYPE_VIEW = 1;

public const OWNER_TYPE_USER = 0;

public function __construct() {
parent::__construct(self::APP_ID);
}
Expand Down Expand Up @@ -65,6 +68,8 @@ public function register(IRegistrationContext $context): void {
}

$context->registerCapability(Capabilities::class);

$context->registerMiddleware(PermissionMiddleware::class);
}

public function boot(IBootContext $context): void {
Expand Down
89 changes: 89 additions & 0 deletions lib/Command/ListContexts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

declare(strict_types=1);

namespace OCA\Tables\Command;

use OC\Core\Command\Base;
use OCA\Tables\Errors\InternalError;
use OCA\Tables\Service\ContextService;
use OCP\DB\Exception;
use OCP\IConfig;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use function json_decode;
use function json_encode;

class ListContexts extends Base {
protected ContextService $contextService;
protected LoggerInterface $logger;
private IConfig $config;

public function __construct(
ContextService $contextService,
LoggerInterface $logger,
IConfig $config,
) {
parent::__construct();
$this->contextService = $contextService;
$this->logger = $logger;
$this->config = $config;
}

protected function configure(): void {
parent::configure();
$this
->setName('tables:contexts:list')
->setDescription('Get all contexts or contexts available to a specified user')
->addArgument(
'user-id',
InputArgument::OPTIONAL,
'User ID of the user'
)
;
}

protected function execute(InputInterface $input, OutputInterface $output): int {
$userId = trim($input->getArgument('user-id'));
if ($userId === '') {
$userId = null;
}

try {
$contexts = $this->contextService->findAll($userId);
} catch (InternalError|Exception $e) {
$output->writeln('Error while reading contexts from DB.');
$this->logger->warning('Following error occurred during executing occ command "{class}"',
[
'app' => 'tables',
'class' => self::class,
'exception' => $e,
]
);
if ($this->config->getSystemValueBool('debug', false)) {
$output->writeln(sprintf('<warning>%s</warning>', $e->getMessage()));
$output->writeln('<error>');
debug_print_backtrace();
$output->writeln('</error>');
}
return 1;
}

foreach ($contexts as $context) {
$contextArray = json_decode(json_encode($context), true);

$contextArray['ownerType'] = match ($contextArray['ownerType']) {
1 => 'group',
default => 'user',
};

$out = ['ID ' . $contextArray['id'] => $contextArray];
unset($out[$contextArray['id']]['id']);
$this->writeArrayInOutputFormat($input, $output, $out);
}

return 0;
}
}
98 changes: 98 additions & 0 deletions lib/Command/ShowContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

declare(strict_types=1);

namespace OCA\Tables\Command;

use OC\Core\Command\Base;
use OCA\Tables\Errors\InternalError;
use OCA\Tables\Service\ContextService;
use OCP\DB\Exception;
use OCP\IConfig;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use function json_decode;
use function json_encode;

class ShowContext extends Base {
protected ContextService $contextService;
protected LoggerInterface $logger;
private IConfig $config;

public function __construct(
ContextService $contextService,
LoggerInterface $logger,
IConfig $config,
) {
parent::__construct();
$this->contextService = $contextService;
$this->logger = $logger;
$this->config = $config;
}

protected function configure(): void {
parent::configure();
$this
->setName('tables:contexts:show')
->setDescription('Get all contexts or contexts available to a specified user')
->addArgument(
'context-id',
InputArgument::REQUIRED,
'The ID of the context to show'
)
->addArgument(
'user-id',
InputArgument::OPTIONAL,
'Optionally, showing the context from the perspective of the given user'
)
;
}

protected function execute(InputInterface $input, OutputInterface $output): int {
$contextId = trim($input->getArgument('context-id'));
if ($contextId === '' || !is_numeric($contextId)) {
$output->writeln('<error>Invalid Context ID</error>');
return 1;
}

$userId = trim($input->getArgument('user-id'));
if ($userId === '') {
$userId = null;
}

try {
$context = $this->contextService->findById($contextId, $userId);
} catch (InternalError|Exception $e) {
$output->writeln('Error while reading contexts from DB.');
$this->logger->warning('Following error occurred during executing occ command "{class}"',
[
'app' => 'tables',
'class' => self::class,
'exception' => $e,
]
);
if ($this->config->getSystemValueBool('debug', false)) {
$output->writeln(sprintf('<warning>%s</warning>', $e->getMessage()));
$output->writeln('<error>');
debug_print_backtrace();
$output->writeln('</error>');
}
return 1;
}

$contextArray = json_decode(json_encode($context), true);

$contextArray['ownerType'] = match ($contextArray['ownerType']) {
1 => 'group',
default => 'user',
};

$out = ['ID ' . $contextArray['id'] => $contextArray];
unset($out[$contextArray['id']]['id']);
$this->writeArrayInOutputFormat($input, $output, $out);

return 0;
}
}
10 changes: 10 additions & 0 deletions lib/Controller/AOCSController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Exception;
use OCA\Tables\AppInfo\Application;
use OCA\Tables\Errors\BadRequestError;
use OCA\Tables\Errors\InternalError;
use OCA\Tables\Errors\NotFoundError;
use OCA\Tables\Errors\PermissionError;
Expand Down Expand Up @@ -59,4 +60,13 @@ protected function handleNotFoundError(NotFoundError $e): DataResponse {
return new DataResponse(['message' => $this->n->t('A not found error occurred. More details can be found in the logs. Please reach out to your administration.')], Http::STATUS_NOT_FOUND);
}

/**
* @param BadRequestError $e
* @return DataResponse<Http::STATUS_BAD_REQUEST, array{message: string}, array{}>
*/
protected function handleBadRequestError(BadRequestError $e): DataResponse {
$this->logger->warning('An bad request was encountered: ['. $e->getCode() . ']' . $e->getMessage());
return new DataResponse(['message' => $this->n->t('An error caused by an invalid request occurred. More details can be found in the logs. Please reach out to your administration.')], Http::STATUS_BAD_REQUEST);
}

}
Loading
Loading