manage remote exception

Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
This commit is contained in:
Maxence Lange 2021-03-04 12:07:03 -01:00
parent ba1ee86044
commit 91e88ec6f0
62 changed files with 1537 additions and 555 deletions

View file

@ -1,128 +0,0 @@
imports:
- php
- javascript
filter:
excluded_paths:
- 'appinfo/application.php'
- 'appinfo/info.xml'
- 'l10n/*'
- 'vendor/*'
- 'js/vendor/*'
- 'templates/*'
- 'css/*'
- 'img/*'
- 'tests/*'
- 'build/*'
- 'documentation/*'
tools:
sensiolabs_security_checker: true
php_sim: true
php_pdepend: true
php_analyzer: true
checks:
php:
line_length:
max_length: '100'
verify_access_scope_valid: true
require_scope_for_methods: true
no_underscore_prefix_in_methods: true
missing_arguments: true
method_calls_on_non_object: true
deprecated_code_usage: true
no_eval: true
parameter_doc_comments: true
return_doc_comments: true
fix_doc_comments: true
return_doc_comments: true
parameter_doc_comments: true
more_specific_types_in_doc_comments: true
code_rating: true
duplication: true
variable_existence: true
useless_calls: true
use_statement_alias_conflict: true
unused_variables: true
unused_properties: true
unused_parameters: true
unused_methods: true
unreachable_code: true
sql_injection_vulnerabilities: true
security_vulnerabilities: true
precedence_mistakes: true
precedence_in_conditions: true
parameter_non_unique: true
no_property_on_interface: true
no_non_implemented_abstract_methods: true
deprecated_code_usage: true
closure_use_not_conflicting: true
closure_use_modifiable: true
avoid_useless_overridden_methods: true
avoid_conflicting_incrementers: true
assignment_of_null_return: true
php5_style_constructor: true
one_class_per_file: true
require_php_tag_first: true
uppercase_constants: true
require_braces_around_control_structures: true
psr2_switch_declaration: true
psr2_control_structure_declaration: true
properties_in_camelcaps: true
parameters_in_camelcaps: true
optional_parameters_at_the_end: true
no_underscore_prefix_in_properties: true
no_space_inside_cast_operator: true
no_space_before_semicolon: true
no_short_open_tag: true
no_goto: true
lowercase_php_keywords: true
lowercase_basic_constants: true
function_in_camel_caps: true
classes_in_camel_caps: true
avoid_space_indentation: true
overriding_private_members: true
no_unnecessary_function_call_in_for_loop: true
simplify_boolean_return: true
javascript:
wrap_iife: true
no_process_exit: true
no_process_env: true
no_extra_semi: true
no_extra_bind: true
no_eval: true
no_else_return: true
dot_notation: true
camelcase: true
wrap_regex: true
valid_typeof: true
no_wrap_func: true
no_use_before_define: true
no_unreachable: true
no_undefined: true
no_trailing_spaces: true
no_reserved_keys: true
no_redeclare: true
no_obj_calls: true
no_loop_func: true
no_lonely_if: true
no_lone_blocks: true
no_inner_declarations: true
no_floating_decimal: true
no_extra_boolean_cast: true
no_empty: true
no_dupe_keys: true
coding_style:
php:
indentation:
general:
use_tabs: true
size: 4
spaces:
other:
after_type_cast: false
braces:
classes_functions:
class: end-of-line

View file

@ -1,9 +1,5 @@
# Nextcloud Circles
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/nextcloud/circles/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/nextcloud/circles/?branch=master)
[![codecov](https://codecov.io/gh/nextcloud/circles/branch/master/graph/badge.svg)](https://codecov.io/gh/nextcloud/circles)
[![Build Status](https://drone.nextcloud.com/api/badges/nextcloud/circles/status.svg)](https://drone.nextcloud.com/nextcloud/circles)
**Bring cloud-users closer together.**
![](https://raw.githubusercontent.com/nextcloud/circles/master/screenshots/0.12.0.png)
@ -12,34 +8,6 @@ Circles allows your users to create their own groups of users/colleagues/friends
Those groups of users (or circles) can then be used by any other app for sharing purpose
(files, social feed, status update, messaging, …) through the Circles API
Different types of circles can be created:
- A **Personal Circle** is a list of users known only to the owner.
This is the right option if you want to do recurrent sharing with the same list of local users.
- A **Public Circle** is an open group visible to anyone willing to join.
Anyone can see the circle, can join the circle and access the items shared to the circle.
- Joining a **Closed Circle** requires an invitation or a confirmation by a moderator.
Anyone can find the circle and request an invitation; but only members will see who's in it and get access to shared items.
- A **Secret Circle** is an hidden group that can only be seen by its members or by people knowing the exact name of the circle.
Non-members won't be able to find your secret circle using the search bar.
### Membership levels
Circle members can have different levels with different rights over the circle:
- **Member**: lowest level, user is a member of the circle
- **Moderator**: can add/remove/acccept/reject members from the circle and edit their user levels
- **Admin**: all of _Moderator_ + edit the circle's settings
- **Owner**: all of _Admin_ + delete the circle
In case the account of the Owner gets deleted, the oldest Admin will be promoted to Owner.
***
# API (PHP & Javascript)

8
composer.lock generated
View file

@ -12,12 +12,12 @@
"source": {
"type": "git",
"url": "https://github.com/daita/my-small-php-tools.git",
"reference": "22b1f104891706bb750fe13402d0d4645c66e399"
"reference": "87f4c4006b5e7cd339606120bcfb406c8aa46159"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/daita/my-small-php-tools/zipball/22b1f104891706bb750fe13402d0d4645c66e399",
"reference": "22b1f104891706bb750fe13402d0d4645c66e399",
"url": "https://api.github.com/repos/daita/my-small-php-tools/zipball/87f4c4006b5e7cd339606120bcfb406c8aa46159",
"reference": "87f4c4006b5e7cd339606120bcfb406c8aa46159",
"shasum": ""
},
"require": {
@ -45,7 +45,7 @@
"issues": "https://github.com/daita/my-small-php-tools/issues",
"source": "https://github.com/daita/my-small-php-tools/tree/master"
},
"time": "2021-02-24T19:31:24+00:00"
"time": "2021-03-04T12:23:04+00:00"
}
],
"packages-dev": [],

View file

@ -10,7 +10,7 @@ declare(strict_types=1);
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2017
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
@ -35,26 +35,14 @@ use daita\MySmallPhpTools\Exceptions\InvalidItemException;
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
use daita\MySmallPhpTools\Exceptions\SignatoryException;
use OC\Core\Command\Base;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedEventDSyncException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\FederatedUserException;
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\InitiatorNotFoundException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteInstanceException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\Exceptions\UserTypeNotFoundException;
use OCA\Circles\Model\Circle;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\FederatedUserService;
use OCP\IL10N;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@ -70,6 +58,9 @@ use Symfony\Component\Console\Output\OutputInterface;
class CirclesConfig extends Base {
/** @var IL10N */
private $l10n;
/** @var FederatedUserService */
private $federatedUserService;
@ -83,15 +74,18 @@ class CirclesConfig extends Base {
/**
* CirclesConfig constructor.
*
* @param IL10N $l10n
* @param FederatedUserService $federatedUserService
* @param CircleService $circlesService
* @param ConfigService $configService
*/
public function __construct(
FederatedUserService $federatedUserService, CircleService $circlesService,
IL10N $l10n, FederatedUserService $federatedUserService, CircleService $circlesService,
ConfigService $configService
) {
parent::__construct();
$this->l10n = $l10n;
$this->federatedUserService = $federatedUserService;
$this->circleService = $circlesService;
$this->configService = $configService;
@ -110,7 +104,8 @@ class CirclesConfig extends Base {
'config', InputArgument::IS_ARRAY,
'list of value to change in the configuration of the Circle'
)
->addOption('initiator', '', InputOption::VALUE_REQUIRED, 'set an initiator to the request', '');
->addOption('initiator', '', InputOption::VALUE_REQUIRED, 'set an initiator to the request', '')
->addOption('status-code', '', InputOption::VALUE_NONE, 'display status code on exception');
}
@ -119,43 +114,42 @@ class CirclesConfig extends Base {
* @param OutputInterface $output
*
* @return int
* @throws CircleNotFoundException
* @throws FederatedUserException
* @throws FederatedUserNotFoundException
* @throws InitiatorNotFoundException
* @throws InvalidIdException
* @throws InvalidItemException
* @throws MemberNotFoundException
* @throws OwnerNotFoundException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
* @throws UserTypeNotFoundException
* @throws FederatedEventDSyncException
* @throws FederatedEventException
* @throws FederatedItemException
* @throws InitiatorNotConfirmedException
* @throws InitiatorNotFoundException
* @throws InvalidItemException
* @throws RequestNetworkException
* @throws SignatoryException
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$circleId = (string)$input->getArgument('circle_id');
$this->federatedUserService->commandLineInitiator($input->getOption('initiator'), $circleId, false);
$circle = $this->circleService->getCircle($circleId);
if (empty($input->getArgument('config'))) {
$output->writeln(
json_encode(Circle::getCircleTypes($circle, Circle::TYPES_LONG), JSON_PRETTY_PRINT)
try {
$this->federatedUserService->commandLineInitiator(
$input->getOption('initiator'), $circleId, false
);
return 0;
}
$circle = $this->circleService->getCircle($circleId);
$new = $this->generateConfig($circle, $input->getArgument('config'));
$outcome = $this->circleService->updateConfig($circleId, $new);
if (empty($input->getArgument('config'))) {
$output->writeln(
json_encode(Circle::getCircleTypes($circle, Circle::TYPES_LONG), JSON_PRETTY_PRINT)
);
return 0;
}
$new = $this->generateConfig($circle, $input->getArgument('config'));
$outcome = $this->circleService->updateConfig($circleId, $new);
} catch (FederatedItemException $e) {
if ($input->getOption('status-code')) {
throw new FederatedItemException(
' [' . get_class($e) . ', ' . $e->getStatus() . ']' . "\n" . $e->getMessage()
);
}
throw $e;
}
$output->writeln(json_encode($outcome, JSON_PRETTY_PRINT));

View file

@ -30,18 +30,16 @@
namespace OCA\Circles\Command;
use OC\Core\Command\Base;
use OC\User\NoUserException;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\InitiatorNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\SingleCircleNotFoundException;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\FederatedUserService;
use OCP\IL10N;
use OCP\IUserManager;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -92,7 +90,8 @@ class CirclesCreate extends Base {
$this->setName('circles:manage:create')
->setDescription('create a new circle')
->addArgument('owner', InputArgument::REQUIRED, 'owner of the circle')
->addArgument('name', InputArgument::REQUIRED, 'name of the circle');
->addArgument('name', InputArgument::REQUIRED, 'name of the circle')
->addOption('status-code', '', InputOption::VALUE_NONE, 'display status code on exception');
}
@ -101,21 +100,29 @@ class CirclesCreate extends Base {
* @param OutputInterface $output
*
* @return int
* @throws CircleNotFoundException
* @throws NoUserException
* @throws FederatedEventException
* @throws FederatedItemException
* @throws InitiatorNotFoundException
* @throws OwnerNotFoundException
* @throws InitiatorNotConfirmedException
* @throws SingleCircleNotFoundException
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$ownerId = $input->getArgument('owner');
$name = $input->getArgument('name');
$this->federatedUserService->bypassCurrentUserCondition(true);
try {
$this->federatedUserService->bypassCurrentUserCondition(true);
$owner = $this->federatedUserService->getLocalFederatedUser($ownerId);
$outcome = $this->circleService->create($name, $owner);
$owner = $this->federatedUserService->getLocalFederatedUser($ownerId);
$outcome = $this->circleService->create($name, $owner);
} catch (FederatedItemException $e) {
if ($input->getOption('status-code')) {
throw new FederatedItemException(
' [' . get_class($e) . ', ' . $e->getStatus() . ']' . "\n" . $e->getMessage()
);
}
throw $e;
}
echo json_encode($outcome, JSON_PRETTY_PRINT) . "\n";

View file

@ -41,11 +41,13 @@ use daita\MySmallPhpTools\Model\Request;
use Exception;
use OC\Core\Command\Base;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\GSStatusException;
use OCA\Circles\Model\Member;
use OCA\Circles\Service\ConfigService;
use OCA\Circles\Service\FederatedUserService;
use OCA\Circles\Service\MemberService;
use OCP\IL10N;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@ -60,6 +62,9 @@ use Symfony\Component\Console\Output\OutputInterface;
class MembersAdd extends Base {
/** @var IL10N */
private $l10n;
/** @var FederatedUserService */
private $federatedUserService;
@ -76,17 +81,19 @@ class MembersAdd extends Base {
/**
* MembersCreate constructor.
*
* @param IL10N $l10n
* @param CircleRequest $circleRequest
* @param FederatedUserService $federatedUserService
* @param MemberService $memberService
* @param ConfigService $configService
*/
public function __construct(
CircleRequest $circleRequest, FederatedUserService $federatedUserService,
MemberService $memberService,
ConfigService $configService
IL10N $l10n, CircleRequest $circleRequest, FederatedUserService $federatedUserService,
MemberService $memberService, ConfigService $configService
) {
parent::__construct();
$this->l10n = $l10n;
$this->federatedUserService = $federatedUserService;
$this->circleRequest = $circleRequest;
@ -102,6 +109,7 @@ class MembersAdd extends Base {
->addArgument('circle_id', InputArgument::REQUIRED, 'ID of the circle')
->addArgument('user', InputArgument::REQUIRED, 'username of the member')
->addOption('initiator', '', InputOption::VALUE_REQUIRED, 'set an initiator to the request', '')
->addOption('status-code', '', InputOption::VALUE_NONE, 'display status code on exception')
->addOption('type', '', InputOption::VALUE_REQUIRED, 'type of the user', '0');
}
@ -117,13 +125,26 @@ class MembersAdd extends Base {
$circleId = $input->getArgument('circle_id');
$userId = $input->getArgument('user');
$type = $input->getOption('type');
if ($type !== '0') {
$type = Member::parseTypeString($type);
}
$this->federatedUserService->commandLineInitiator($input->getOption('initiator'), $circleId, false);
$federatedUser = $this->federatedUserService->generateFederatedUser($userId, (int)$type);
$outcome = $this->memberService->addMember($circleId, $federatedUser);
try {
$this->federatedUserService->commandLineInitiator(
$input->getOption('initiator'), $circleId, false
);
$federatedUser = $this->federatedUserService->generateFederatedUser($userId, (int)$type);
$outcome = $this->memberService->addMember($circleId, $federatedUser);
} catch (FederatedItemException $e) {
if ($input->getOption('status-code')) {
throw new FederatedItemException(
' [' . get_class($e) . ', ' . $e->getStatus() . ']' . "\n" . $e->getMessage()
);
}
throw $e;
}
$output->writeln(json_encode($outcome, JSON_PRETTY_PRINT));

View file

@ -31,31 +31,19 @@ declare(strict_types=1);
namespace OCA\Circles\Command;
use daita\MySmallPhpTools\Exceptions\InvalidItemException;
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
use daita\MySmallPhpTools\Exceptions\SignatoryException;
use OC\Core\Command\Base;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedEventDSyncException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\FederatedUserException;
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\InitiatorNotFoundException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\Exceptions\MemberLevelException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteInstanceException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\Exceptions\UserTypeNotFoundException;
use OCA\Circles\Model\Member;
use OCA\Circles\Service\FederatedUserService;
use OCA\Circles\Service\MemberService;
use OCP\IL10N;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@ -70,6 +58,10 @@ use Symfony\Component\Console\Output\OutputInterface;
class MembersLevel extends Base {
/** @var IL10N */
private $l10n;
/** @var MemberRequest */
private $memberRequest;
/** @var FederatedUserService */
@ -82,15 +74,18 @@ class MembersLevel extends Base {
/**
* MembersLevel constructor.
*
* @param IL10N $l10n
* @param MemberRequest $memberRequest
* @param FederatedUserService $federatedUserService
* @param MemberService $memberService
*/
public function __construct(
MemberRequest $memberRequest, FederatedUserService $federatedUserService, MemberService $memberService
IL10N $l10n, MemberRequest $memberRequest, FederatedUserService $federatedUserService,
MemberService $memberService
) {
parent::__construct();
$this->l10n = $l10n;
$this->memberRequest = $memberRequest;
$this->federatedUserService = $federatedUserService;
$this->memberService = $memberService;
@ -104,6 +99,7 @@ class MembersLevel extends Base {
->addArgument('member_id', InputArgument::REQUIRED, 'ID of the member from the Circle')
->addOption('circle', '', InputOption::VALUE_REQUIRED, 'ID of the circle', '')
->addOption('initiator', '', InputOption::VALUE_REQUIRED, 'set an initiator to the request', '')
->addOption('status-code', '', InputOption::VALUE_NONE, 'display status code on exception')
->addArgument('level', InputArgument::REQUIRED, 'new level');
}
@ -113,41 +109,37 @@ class MembersLevel extends Base {
* @param OutputInterface $output
*
* @return int
* @throws CircleNotFoundException
* @throws FederatedEventException
* @throws FederatedItemException
* @throws FederatedUserException
* @throws FederatedUserNotFoundException
* @throws InitiatorNotConfirmedException
* @throws InitiatorNotFoundException
* @throws InvalidIdException
* @throws MemberLevelException
* @throws MemberNotFoundException
* @throws OwnerNotFoundException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws UnknownRemoteException
* @throws UserTypeNotFoundException
* @throws InvalidItemException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws FederatedEventDSyncException
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$memberId = $input->getArgument('member_id');
$circleId = $input->getOption('circle');
if ($circleId === '') {
$circleId = $this->memberRequest->getMember($memberId)->getCircleId();
try {
if ($circleId === '') {
$circleId = $this->memberRequest->getMember($memberId)->getCircleId();
}
$this->federatedUserService->commandLineInitiator($input->getOption('initiator'), $circleId);
$this->memberService->getMember($memberId, $circleId);
$level = Member::parseLevelString($input->getArgument('level'));
$outcome = $this->memberService->memberLevel($memberId, $level);
} catch (FederatedItemException $e) {
if ($input->getOption('status-code')) {
throw new FederatedItemException(
' [' . get_class($e) . ', ' . $e->getStatus() . ']' . "\n" . $e->getMessage()
);
}
throw $e;
}
$this->federatedUserService->commandLineInitiator($input->getOption('initiator'), $circleId);
$this->memberService->getMember($memberId, $circleId);
$level = Member::parseLevelString($input->getArgument('level'));
$outcome = $this->memberService->memberLevel($memberId, $level);
echo json_encode($outcome, JSON_PRETTY_PRINT) . "\n";
return 0;

View file

@ -108,6 +108,7 @@ class MembersList extends Base {
CircleService $circleService, MemberService $memberService, ConfigService $configService
) {
parent::__construct();
$this->federatedUserService = $federatedUserService;
$this->remoteService = $remoteService;
$this->circleService = $circleService;
@ -158,6 +159,7 @@ class MembersList extends Base {
if ($input->getOption('tree')) {
$this->federatedUserService->commandLineInitiator($initiator, $circleId, true);
$circle = $this->circleService->getCircle($circleId);
$output->writeln('<info>Name</info>: ' . $circle->getName());
$owner = $circle->getOwner();
$output->writeln('<info>Owner</info>: ' . $owner->getUserId() . '@' . $owner->getInstance());

View file

@ -32,12 +32,27 @@ declare(strict_types=1);
namespace OCA\Circles\Controller;
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
use daita\MySmallPhpTools\Exceptions\SignatoryException;
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Deserialize;
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Logger;
use Exception;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedEventDSyncException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\FederatedUserException;
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\InitiatorNotFoundException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\Exceptions\MemberNotFoundException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\ParseMemberLevelException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\SingleCircleNotFoundException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\Model\Member;
use OCA\Circles\Service\CircleService;
use OCA\Circles\Service\ConfigService;
@ -111,16 +126,24 @@ class LocalController extends OcsController {
* @return DataResponse
*/
public function circles(): DataResponse {
$debug = ['action' => 'localController::circles()'];
try {
$this->setCurrentFederatedUser();
} catch (Exception $e) {
$this->e($e, array_merge($debug, [Http::STATUS_INTERNAL_SERVER_ERROR]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
}
try {
$data = $this->circleService->getCircles();
$this->debug('success LocalController::circles()', ['data' => $data]);
$this->debug('success', array_merge($debug, ['data' => $data]));
return new DataResponse(json_decode(json_encode($data), true));
} catch (Exception $e) {
$this->e($e, ['fail localController::circles()']);
} catch (InitiatorNotFoundException $e) {
$this->e($e, array_merge($debug, [Http::STATUS_FORBIDDEN]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_FORBIDDEN);
}
}
@ -134,21 +157,48 @@ class LocalController extends OcsController {
* @return DataResponse
*/
public function create(string $name, bool $personal = false): DataResponse {
$debug = ['name' => $name, 'personal' => $personal];
$debug = ['action' => 'localController::create()', 'name' => $name, 'personal' => $personal];
try {
$this->setCurrentFederatedUser();
} catch (Exception $e) {
$this->e($e, array_merge($debug, [Http::STATUS_INTERNAL_SERVER_ERROR]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
}
try {
$circle = $this->circleService->create($name);
$this->debug('success LocalController::create()', array_merge($debug, ['circle' => $circle]));
$this->debug('success', array_merge($debug, ['circle' => $circle]));
return new DataResponse(json_decode(json_encode($circle), true));
} catch (Exception $e) {
$this->e($e, array_merge(['fail localController::create()', $debug]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
} catch (FederatedEventException $e) {
// 500
} catch (InitiatorNotConfirmedException $e) {
// 403
} catch (RemoteNotFoundException $e) {
// 403
} catch (FederatedItemException $e) {
} catch (InitiatorNotFoundException $e) {
} catch (OwnerNotFoundException $e) {
// 500
} catch (RemoteResourceNotFoundException $e) {
} catch (UnknownRemoteException $e) {
} catch (RequestNetworkException $e) {
} catch (SignatoryException $e) {
// $this->e($e, array_merge(['fail localController::create()', $debug]));
//
// return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
}
}
// 500 - soucis server
// 403 - soucis de droit
// 404 - soucis item (member, circle ou remote n'existe pas)
// 400 - bad request
// 408 - soucis federated
/**
* @NoAdminRequired
@ -158,18 +208,24 @@ class LocalController extends OcsController {
* @return DataResponse
*/
public function members(string $circleId): DataResponse {
$debug = ['circleId' => $circleId];
$debug = ['action' => 'localController::members()', 'circleId' => $circleId];
try {
$this->setCurrentFederatedUser();
} catch (Exception $e) {
$this->e($e, array_merge($debug, [Http::STATUS_INTERNAL_SERVER_ERROR]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
}
try {
$members = $this->memberService->getMembers($circleId);
$this->debug('success LocalController::members()', array_merge($debug, ['members' => $members]));
$this->debug('success', array_merge($debug, ['members' => $members]));
return new DataResponse(json_decode(json_encode($members), true));
} catch (Exception $e) {
$this->e($e, array_merge(['fail localController::members()', $debug]));
} catch (InitiatorNotFoundException $e) {
$this->e($e, array_merge($debug, [Http::STATUS_FORBIDDEN]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_FORBIDDEN);
}
}
@ -184,23 +240,41 @@ class LocalController extends OcsController {
* @return DataResponse
*/
public function memberAdd(string $circleId, string $userId, int $type): DataResponse {
$debug = ['circleId' => $circleId, 'userId' => $userId, 'type' => $type];
$debug = [
'action' => 'localController::memberAdd()',
'circleId' => $circleId,
'userId' => $userId,
'type' => $type
];
try {
$this->setCurrentFederatedUser();
} catch (Exception $e) {
$this->e($e, array_merge($debug, [Http::STATUS_INTERNAL_SERVER_ERROR]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
}
try {
$member = $this->federatedUserService->generateFederatedUser($userId, (int)$type);
$result = $this->memberService->addMember($circleId, $member);
$this->debug(
'success LocalController::memberAdd()',
array_merge($debug, ['member' => $member, 'result' => $result])
);
$this->debug('success', array_merge($debug, ['result' => $result]));
return new DataResponse(json_decode(json_encode($result), true));
} catch (Exception $e) {
$this->e($e, array_merge(['fail localController::memberAdd()', $debug]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
} catch (CircleNotFoundException $e) {
} catch (FederatedEventDSyncException $e) {
} catch (FederatedEventException $e) {
} catch (InitiatorNotConfirmedException $e) {
} catch (RemoteNotFoundException $e) {
} catch (FederatedItemException $e) {
} catch (InitiatorNotFoundException $e) {
} catch (OwnerNotFoundException $e) {
} catch (RemoteResourceNotFoundException $e) {
} catch (UnknownRemoteException $e) {
} catch (RequestNetworkException $e) {
} catch (SignatoryException $e) {
// $this->e($e, array_merge(['fail localController::memberAdd()', $debug]));
//
// return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
}
}
@ -215,23 +289,50 @@ class LocalController extends OcsController {
* @return DataResponse
*/
public function memberLevel(string $circleId, string $memberId, string $level): DataResponse {
$debug = ['circleId' => $circleId, 'memberId' => $memberId, 'level' => $level];
$debug = [
'action' => 'localController::memberLevel()',
'circleId' => $circleId,
'memberId' => $memberId,
'level' => $level
];
try {
$this->setCurrentFederatedUser();
} catch (Exception $e) {
$this->e($e, array_merge($debug, [Http::STATUS_INTERNAL_SERVER_ERROR]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
}
try {
$level = Member::parseLevelString($level);
$this->memberService->getMember($memberId, $circleId);
$result = $this->memberService->memberLevel($memberId, $level);
$this->debug(
'success LocalController::memberLevel()', array_merge($debug, ['result' => $result])
);
$this->debug('success', array_merge($debug, ['result' => $result]));
return new DataResponse(json_decode(json_encode($result), true));
} catch (Exception $e) {
$this->e($e, array_merge(['fail localController::memberLevel()', $debug]));
} catch (ParseMemberLevelException $e) {
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
$this->e($e, array_merge([Http::STATUS_BAD_REQUEST, $debug]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
} catch (InitiatorNotFoundException | MemberNotFoundException $e) {
$this->e($e, array_merge([Http::STATUS_FORBIDDEN, $debug]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_FORBIDDEN);
} catch (FederatedEventDSyncException $e) {
} catch (FederatedEventException $e) {
} catch (InitiatorNotConfirmedException $e) {
} catch (RemoteNotFoundException $e) {
} catch (FederatedItemException $e) {
} catch (OwnerNotFoundException $e) {
} catch (RemoteResourceNotFoundException $e) {
} catch (UnknownRemoteException $e) {
} catch (RequestNetworkException $e) {
} catch (SignatoryException $e) {
// $this->e($e, array_merge(['fail localController::memberLevel()', $debug]));
//
// return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
}
}
@ -245,30 +346,53 @@ class LocalController extends OcsController {
* @return DataResponse
*/
public function memberRemove(string $circleId, string $memberId): DataResponse {
$debug = ['circleId' => $circleId, 'memberId' => $memberId];
$debug = [
'action' => 'localController::memberRemove()',
'circleId' => $circleId,
'memberId' => $memberId
];
try {
$this->setCurrentFederatedUser();
} catch (Exception $e) {
$this->e($e, array_merge($debug, [Http::STATUS_INTERNAL_SERVER_ERROR]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
}
try {
$this->memberService->getMember($memberId, $circleId);
$result = $this->memberService->removeMember($memberId);
$this->debug(
'success LocalController::memberRemove()', array_merge($debug, ['result' => $result])
);
$this->debug('success', array_merge($debug, ['result' => $result]));
return new DataResponse(json_decode(json_encode($result), true));
} catch (Exception $e) {
$this->e($e, array_merge(['fail localController::memberRemove()', $debug]));
} catch (InitiatorNotFoundException | MemberNotFoundException $e) {
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
$this->e($e, array_merge([Http::STATUS_FORBIDDEN, $debug]));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_FORBIDDEN);
} catch (FederatedEventDSyncException $e) {
} catch (FederatedEventException $e) {
} catch (InitiatorNotConfirmedException $e) {
} catch (RemoteNotFoundException $e) {
} catch (FederatedItemException $e) {
} catch (OwnerNotFoundException $e) {
} catch (RemoteResourceNotFoundException $e) {
} catch (UnknownRemoteException $e) {
} catch (RequestNetworkException $e) {
} catch (SignatoryException $e) {
//
// $this->e($e, array_merge(['fail localController::memberRemove()', $debug]));
//
// return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
}
}
/**
* @throws CircleNotFoundException
* @throws FederatedUserNotFoundException
* @throws InvalidIdException
* @throws FederatedUserException
* @throws SingleCircleNotFoundException
*/
private function setCurrentFederatedUser() {
$user = $this->userSession->getUser();

View file

@ -48,9 +48,13 @@ use OC\AppFramework\Middleware\Security\Exceptions\NotLoggedInException;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedEventDSyncException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\FederatedItemBadRequestException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\FederatedUserException;
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Federated\RemoteInstance;
use OCA\Circles\Model\FederatedUser;
@ -142,8 +146,6 @@ class RemoteController extends Controller {
* @throws SignatoryException
*/
public function appService(): DataResponse {
$this->setup('app', 'circles');
try {
$this->publicPageJsonLimited();
} catch (JsonNotRequestedException $e) {
@ -166,23 +168,20 @@ class RemoteController extends Controller {
try {
$event = $this->extractEventFromRequest();
} catch (Exception $e) {
return $this->fail($e, [], Http::STATUS_BAD_REQUEST);
return $this->eventResponse($e, null, Http::STATUS_UNAUTHORIZED);
}
try {
$this->remoteDownstreamService->requestedEvent($event);
} catch (FederatedEventException $e) {
return $this->eventResponse($e, $event, Http::STATUS_INTERNAL_SERVER_ERROR);
} catch (FederatedItemException $e) {
$this->e($e, ['event' => $event]);
$event->setReadingOutcome($e->getMessage(), $e->getParams(), true);
} catch (FederatedEventDSyncException $e) {
return $this->fail($e, [], Http::STATUS_CONFLICT);
return $this->eventResponse($e, $event, $e->getStatus());
} catch (Exception $e) {
$this->e($e);
return $this->fail($e, [], Http::STATUS_BAD_REQUEST);
return $this->eventResponse($e, $event, Http::STATUS_BAD_REQUEST);
}
return $this->successObj($event->getOutcome());
return $this->eventResponse(null, $event);
}
@ -197,9 +196,11 @@ class RemoteController extends Controller {
$event = $this->extractEventFromRequest();
$this->remoteDownstreamService->incomingEvent($event);
return $this->success(['result' => $event->getResult()]);
return new DataResponse(json_decode(json_encode($event->getResult()), true), Http::STATUS_OK);
} catch (Exception $e) {
return $this->fail($e);
$this->e($e);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
}
}
@ -217,7 +218,7 @@ class RemoteController extends Controller {
public function test(): DataResponse {
$test = $this->remoteStreamService->incomingSignedRequest($this->configService->getFrontalInstance());
return $this->successObj($test);
return new DataResponse(json_decode(json_encode($test), true));
}
@ -235,9 +236,11 @@ class RemoteController extends Controller {
$filter = $data->gObj('filter');
$circles = $this->circleService->getCircles($filter);
return $this->success($circles, false);
return new DataResponse($circles);
} catch (Exception $e) {
return $this->fail($e);
$this->e($e);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
}
}
@ -255,11 +258,15 @@ class RemoteController extends Controller {
$this->extractDataFromFromRequest();
$circle = $this->circleService->getCircle($circleId);
return $this->successObj($circle);
return new DataResponse(json_decode(json_encode($circle), true));
} catch (CircleNotFoundException $e) {
return $this->success([], false);
$this->e($e);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
} catch (Exception $e) {
return $this->fail($e);
$this->e($e);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
}
@ -277,9 +284,11 @@ class RemoteController extends Controller {
$this->extractDataFromFromRequest();
$members = $this->memberService->getMembers($circleId);
return $this->success($members, false);
return new DataResponse($members);
} catch (Exception $e) {
return $this->fail($e);
$this->e($e);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
}
@ -310,11 +319,15 @@ class RemoteController extends Controller {
throw new FederatedUserNotFoundException();
}
return $this->successObj($federatedUser);
return new DataResponse(json_decode(json_encode($federatedUser), true));
} catch (FederatedUserNotFoundException $e) {
return $this->success([], false);
$this->e($e);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_FOUND);
} catch (Exception $e) {
return $this->fail($e);
$this->e($e);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
}
@ -353,7 +366,8 @@ class RemoteController extends Controller {
* @throws InvalidItemException
*/
private function extractEventFromRequest(): FederatedEvent {
$signed = $this->remoteStreamService->incomingSignedRequest($this->configService->getFrontalInstance());
$signed =
$this->remoteStreamService->incomingSignedRequest($this->configService->getFrontalInstance());
$this->confirmRemoteInstance($signed);
$event = new FederatedEvent();
@ -366,16 +380,17 @@ class RemoteController extends Controller {
/**
* @return SimpleDataStore
* @throws FederatedUserNotFoundException
* @throws FederatedItemBadRequestException
* @throws FederatedUserException
* @throws InvalidOriginException
* @throws MalformedArrayException
* @throws SignatoryException
* @throws SignatureException
* @throws UnknownTypeException
* @throws FederatedUserException
*/
private function extractDataFromFromRequest(): SimpleDataStore {
$signed = $this->remoteStreamService->incomingSignedRequest($this->configService->getFrontalInstance());
$signed =
$this->remoteStreamService->incomingSignedRequest($this->configService->getFrontalInstance());
$remoteInstance = $this->confirmRemoteInstance($signed);
// There should be no need to confirm the need or the origin of the initiator as $remoteInstance
@ -389,26 +404,58 @@ class RemoteController extends Controller {
try {
/** @var FederatedUser $initiator */
$initiator = $store->gObj('initiator', FederatedUser::class);
if (is_null($initiator)) {
throw new InvalidItemException();
if (!is_null($initiator)) {
$this->federatedUserService->setCurrentUser($initiator);
}
$this->federatedUserService->setCurrentUser($initiator);
} catch (InvalidItemException | ItemNotFoundException $e) {
} catch (InvalidItemException $e) {
}
try {
/** @var FederatedUser $initiator */
$filter = $store->gObj('filter', Member::class);
if (is_null($filter)) {
throw new InvalidItemException();
if (!is_null($filter)) {
$data->aObj('filter', $filter);
}
$data->aObj('filter', $filter);
} catch (InvalidItemException | ItemNotFoundException $e) {
} catch (InvalidItemException $e) {
}
return $data;
}
/**
* @param Exception|null $e
* @param FederatedEvent|null $event
* @param int $status
*
* @return DataResponse
*/
public function eventResponse(
?Exception $e = null,
?FederatedEvent $event = null,
int $status = Http::STATUS_OK
): DataResponse {
$params = [];
if (!is_null($e)) {
if ($e instanceof FederatedItemException) {
$params = array_merge($e->getParams(), ['_exception' => $e]);
}
if (!is_null($event)) {
$event->setReadingOutcome(
$e->getMessage(),
$params,
true
);
}
$this->e($e, ['event' => $event]);
}
return new DataResponse(json_decode(json_encode($event->getOutcome()), true), $status);
}
}

View file

@ -35,6 +35,7 @@ namespace OCA\Circles\Db;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\SingleCircleNotFoundException;
use OCA\Circles\IFederatedUser;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\Federated\RemoteInstance;
@ -62,7 +63,7 @@ class CircleRequest extends CircleRequestBuilder {
$qb->setValue('unique_id', $qb->createNamedParameter($circle->getId()))
->setValue('long_id', $qb->createNamedParameter($circle->getId()))
->setValue('name', $qb->createNamedParameter($circle->getName()))
->setValue('alt_name', $qb->createNamedParameter($circle->getAltName()))
->setValue('alt_name', $qb->createNamedParameter($circle->getDisplayName()))
->setValue('description', $qb->createNamedParameter($circle->getDescription()))
->setValue('contact_addressbook', $qb->createNamedParameter($circle->getContactAddressBook()))
->setValue('contact_groupname', $qb->createNamedParameter($circle->getContactGroupName()))
@ -80,7 +81,7 @@ class CircleRequest extends CircleRequestBuilder {
public function update(Circle $circle) {
$qb = $this->getCircleUpdateSql();
$qb->set('name', $qb->createNamedParameter($circle->getName()))
->set('alt_name', $qb->createNamedParameter($circle->getAltName()))
->set('alt_name', $qb->createNamedParameter($circle->getDisplayName()))
->set('description', $qb->createNamedParameter($circle->getDescription()))
->set('settings', $qb->createNamedParameter(json_encode($circle->getSettings())))
->set('config', $qb->createNamedParameter($circle->getConfig()));
@ -237,15 +238,19 @@ class CircleRequest extends CircleRequestBuilder {
* @param IFederatedUser $initiator
*
* @return Circle
* @throws CircleNotFoundException
* @throws SingleCircleNotFoundException
*/
public function getInitiatorCircle(IFederatedUser $initiator): Circle {
public function getSingleCircle(IFederatedUser $initiator): Circle {
$qb = $this->getCircleSelectSql();
$qb->leftJoinOwner();
$qb->limitToMembership($initiator, Member::LEVEL_OWNER);
$qb->limitToConfig(Circle::CFG_SINGLE);
return $this->getItemFromRequest($qb);
try {
return $this->getItemFromRequest($qb);
} catch (CircleNotFoundException $e) {
throw new SingleCircleNotFoundException();
}
}

View file

@ -65,7 +65,7 @@ class MemberRequest extends MemberRequestBuilder {
->setValue('member_id', $qb->createNamedParameter($member->getId()))
->setValue('user_id', $qb->createNamedParameter($member->getUserId()))
->setValue('user_type', $qb->createNamedParameter($member->getUserType()))
->setValue('cached_name', $qb->createNamedParameter($member->getCachedName()))
->setValue('cached_name', $qb->createNamedParameter($member->getDisplayName()))
->setValue('cached_update', $qb->createNamedParameter($this->timezoneService->getUTCDate()))
->setValue('instance', $qb->createNamedParameter($qb->getInstance($member)))
->setValue('level', $qb->createNamedParameter($member->getLevel()))
@ -89,7 +89,7 @@ class MemberRequest extends MemberRequestBuilder {
$qb = $this->getMemberUpdateSql();
$qb->set('member_id', $qb->createNamedParameter($member->getId()))
->set('cached_name', $qb->createNamedParameter($member->getCachedName()))
->set('cached_name', $qb->createNamedParameter($member->getDisplayName()))
->set('cached_update', $qb->createNamedParameter($this->timezoneService->getUTCDate()))
->set('level', $qb->createNamedParameter($member->getLevel()))
->set('status', $qb->createNamedParameter($member->getStatus()))

View file

@ -30,10 +30,8 @@ declare(strict_types=1);
namespace OCA\Circles\Exceptions;
use Exception;
class CircleNotFoundException extends Exception {
class CircleNotFoundException extends FederatedItemNotFoundException {
}

View file

@ -36,7 +36,7 @@ use Exception;
*
* @package OCA\Circles\Exceptions
*/
class FederatedEventDSyncException extends Exception {
class FederatedEventDSyncException extends FederatedItemConflictException {
}

View file

@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@pontapreta.net>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
use OCP\AppFramework\Http;
use Throwable;
/**
* Class FederatedItemBadRequestException
*
* @package OCA\Circles\Exceptions
*/
class FederatedItemBadRequestException extends FederatedItemException {
const STATUS = Http::STATUS_FORBIDDEN;
/**
* FederatedItemBadRequestException constructor.
*
* @param string $message
* @param array $params
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(
string $message = '',
array $params = [],
int $code = 0,
?Throwable $previous = null
) {
parent::__construct($message, $params, $code, $previous);
$this->setStatus(self::STATUS);
}
}

View file

@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@pontapreta.net>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
use OCP\AppFramework\Http;
use Throwable;
/**
* Class FederatedItemConflictException
*
* @package OCA\Circles\Exceptions
*/
class FederatedItemConflictException extends FederatedItemException {
const STATUS = Http::STATUS_CONFLICT;
/**
* FederatedItemConflictException constructor.
*
* @param string $message
* @param array $params
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(
string $message = '',
array $params = [],
int $code = 0,
?Throwable $previous = null
) {
parent::__construct($message, $params, $code, $previous);
$this->setStatus(self::STATUS);
}
}

View file

@ -1,5 +1,9 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
@ -7,7 +11,7 @@
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2017
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
@ -28,25 +32,44 @@
namespace OCA\Circles\Exceptions;
use Exception;
use JsonSerializable;
use OCA\Circles\Service\ExceptionService;
use OCP\AppFramework\Http;
use Throwable;
/**
* Class FederatedEventException
* Class FederatedItemException
*
* @package OCA\Circles\Exceptions
*/
class FederatedItemException extends Exception implements JsonSerializable {
static $CHILDREN = [
FederatedItemBadRequestException::class,
FederatedItemConflictException::class,
FederatedItemForbiddenException::class,
FederatedItemNotFoundException::class,
FederatedItemRemoteException::class,
FederatedItemServerException::class
];
/** @var string */
private $rawMessage;
/** @var array */
private $params;
/** @var int */
private $status = Http::STATUS_INTERNAL_SERVER_ERROR;
/**
* FederatedEventException constructor.
* FederatedItemException constructor.
*
* @param string $message
* @param array $params
@ -54,8 +77,23 @@ class FederatedItemException extends Exception implements JsonSerializable {
* @param Throwable|null $previous
*/
public function __construct(
string $message = '', array $params = [], int $code = 0, ?Throwable $previous = null
string $message = '',
array $params = [],
int $code = 0,
?Throwable $previous = null
) {
$this->setRawMessage($message);
if ($message !== '') {
try {
/** @var ExceptionService $exceptionService */
$exceptionService = \OC::$server->get(ExceptionService::class);
$l10n = $exceptionService->getL10n();
$message = $l10n->t($message, $params);
} catch (Throwable $t) {
}
}
parent::__construct($message, $code, $previous);
$this->setParams($params);
}
@ -74,12 +112,45 @@ class FederatedItemException extends Exception implements JsonSerializable {
return $this->params;
}
/**
* @param string $message
*/
private function setRawMessage(string $message): void {
$this->rawMessage = $message;
}
/**
* @return string
*/
public function getRawMessage(): string {
return $this->rawMessage;
}
/**
* @param int $status
*/
protected function setStatus(int $status): void {
$this->status = $status;
}
/**
* @return int
*/
public function getStatus(): int {
return $this->status;
}
/**
* @return mixed|void
*/
public function jsonSerialize(): array {
return [
'message' => $this->getMessage(),
'class' => get_class($this),
'status' => $this->getStatus(),
'message' => $this->getRawMessage(),
'params' => $this->getParams()
];
}

View file

@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@pontapreta.net>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
use OCP\AppFramework\Http;
use Throwable;
/**
* Class FederatedItemForbiddenException
*
* @package OCA\Circles\Exceptions
*/
class FederatedItemForbiddenException extends FederatedItemException {
const STATUS = Http::STATUS_FORBIDDEN;
/**
* FederatedItemForbiddenException constructor.
*
* @param string $message
* @param array $params
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(
string $message = '',
array $params = [],
int $code = 0,
?Throwable $previous = null
) {
parent::__construct($message, $params, $code, $previous);
$this->setStatus(self::STATUS);
}
}

View file

@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@pontapreta.net>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
use OCP\AppFramework\Http;
use Throwable;
/**
* Class FederatedItemNotFoundException
*
* @package OCA\Circles\Exceptions
*/
class FederatedItemNotFoundException extends FederatedItemException {
const STATUS = Http::STATUS_NOT_FOUND;
/**
* FederatedItemNotFoundException constructor.
*
* @param string $message
* @param array $params
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(
string $message = '',
array $params = [],
int $code = 0,
?Throwable $previous = null
) {
parent::__construct($message, $params, $code, $previous);
$this->setStatus(self::STATUS);
}
}

View file

@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@pontapreta.net>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
use OCP\AppFramework\Http;
use Throwable;
/**
* Class FederatedItemRemoteException
*
* @package OCA\Circles\Exceptions
*/
class FederatedItemRemoteException extends FederatedItemException {
const STATUS = Http::STATUS_REQUEST_TIMEOUT;
/**
* FederatedItemRemoteException constructor.
*
* @param string $message
* @param array $params
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(
string $message = '',
array $params = [],
int $code = 0,
?Throwable $previous = null
) {
parent::__construct($message, $params, $code, $previous);
$this->setStatus(self::STATUS);
}
}

View file

@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@pontapreta.net>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
use OCP\AppFramework\Http;
use Throwable;
/**
* Class FederatedItemForbiddenException
*
* @package OCA\Circles\Exceptions
*/
class FederatedItemServerException extends FederatedItemException {
const STATUS = Http::STATUS_INTERNAL_SERVER_ERROR;
/**
* FederatedItemForbiddenException constructor.
*
* @param string $message
* @param array $params
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(
string $message = '',
array $params = [],
int $code = 0,
?Throwable $previous = null
) {
parent::__construct($message, $params, $code, $previous);
$this->setStatus(self::STATUS);
}
}

View file

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@pontapreta.net>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
class FederatedShareBelongingException extends FederatedItemException {
}

View file

@ -28,12 +28,11 @@ declare(strict_types=1);
*
*/
namespace OCA\Circles\Exceptions;
use Exception;
class FederatedUserException extends Exception {
class FederatedUserException extends FederatedItemServerException {
}

View file

@ -28,13 +28,11 @@ declare(strict_types=1);
*
*/
namespace OCA\Circles\Exceptions;
use Exception;
class FederatedUserNotFoundException extends Exception {
class FederatedUserNotFoundException extends FederatedItemNotFoundException {
}

View file

@ -30,10 +30,8 @@ declare(strict_types=1);
namespace OCA\Circles\Exceptions;
use Exception;
class InitiatorNotConfirmedException extends FederatedItemException {
class InitiatorNotConfirmedException extends FederatedItemForbiddenException {
}

View file

@ -36,7 +36,7 @@ use Exception;
*
* @package OCA\Circles\Exceptions
*/
class InvalidIdException extends Exception {
class InvalidIdException extends FederatedItemServerException {
}

View file

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@pontapreta.net>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
/**
* Class MemberLevelException
*
* @package OCA\Circles\Exceptions
*/
class InvalidModelException extends FederatedItemBadRequestException {
}

View file

@ -37,7 +37,7 @@ namespace OCA\Circles\Exceptions;
*
* @package OCA\Circles\Exceptions
*/
class MemberAlreadyExistsException extends FederatedItemException {
class MemberAlreadyExistsException extends FederatedItemBadRequestException {
}

View file

@ -37,7 +37,7 @@ namespace OCA\Circles\Exceptions;
*
* @package OCA\Circles\Exceptions
*/
class MemberHelperException extends FederatedItemException {
class MemberHelperException extends FederatedItemBadRequestException {
}

View file

@ -37,7 +37,7 @@ namespace OCA\Circles\Exceptions;
*
* @package OCA\Circles\Exceptions
*/
class MemberLevelException extends FederatedItemException {
class MemberLevelException extends FederatedItemBadRequestException {
}

View file

@ -30,15 +30,13 @@ declare(strict_types=1);
namespace OCA\Circles\Exceptions;
use Exception;
/**
* Class MemberNotFoundException
*
* @package OCA\Circles\Exceptions
*/
class MemberNotFoundException extends FederatedItemException {
class MemberNotFoundException extends FederatedItemNotFoundException {
}

View file

@ -27,7 +27,7 @@
namespace OCA\Circles\Exceptions;
class MembersLimitException extends \Exception {
class MembersLimitException extends FederatedItemForbiddenException {
}

View file

@ -28,13 +28,11 @@ declare(strict_types=1);
*
*/
namespace OCA\Circles\Exceptions;
use Exception;
class OwnerNotFoundException extends Exception {
class OwnerNotFoundException extends FederatedItemServerException {
}

View file

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@pontapreta.net>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
/**
* Class MemberLevelException
*
* @package OCA\Circles\Exceptions
*/
class ParseMemberLevelException extends FederatedItemBadRequestException {
}

View file

@ -28,9 +28,8 @@ declare(strict_types=1);
*
*/
namespace OCA\Circles\Exceptions;
use Exception;
namespace OCA\Circles\Exceptions;
/**
@ -38,8 +37,7 @@ use Exception;
*
* @package OCA\Circles\Exceptions
*/
class RemoteInstanceException extends Exception {
class RemoteInstanceException extends FederatedItemRemoteException {
}

View file

@ -36,7 +36,7 @@ namespace OCA\Circles\Exceptions;
*
* @package OCA\Circles\Exceptions
*/
class RemoteNotFoundException extends FederatedItemException {
class RemoteNotFoundException extends FederatedItemNotFoundException {
}

View file

@ -30,11 +30,8 @@ declare(strict_types=1);
namespace OCA\Circles\Exceptions;
use Exception;
class RemoteResourceNotFoundException extends Exception {
class RemoteResourceNotFoundException extends FederatedItemRemoteException {
}

View file

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@pontapreta.net>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
use Exception;
class SingleCircleNotFoundException extends Exception {
}

View file

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2017
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Exceptions;
use Exception;
use JsonSerializable;
use Throwable;
/**
* Class UnknownFederatedItemException
*
* @package OCA\Circles\Exceptions
*/
class UnknownFederatedItemException extends Exception {
}

View file

@ -28,12 +28,11 @@ declare(strict_types=1);
*
*/
namespace OCA\Circles\Exceptions;
use Exception;
class UnknownRemoteException extends Exception {
class UnknownRemoteException extends FederatedItemRemoteException {
}

View file

@ -28,12 +28,11 @@ declare(strict_types=1);
*
*/
namespace OCA\Circles\Exceptions;
use Exception;
class UserTypeNotFoundException extends Exception {
class UserTypeNotFoundException extends FederatedItemBadRequestException {
}

View file

@ -34,6 +34,7 @@ namespace OCA\Circles\FederatedItems;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\FederatedItemBadRequestException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\Model\Circle;
@ -110,7 +111,7 @@ class CircleConfig implements IFederatedItem {
}
if (!$confirmed || $config > Circle::$DEF_CFG_MAX) {
throw new FederatedItemException('Configuration value is not valid');
throw new FederatedItemBadRequestException('Configuration value is not valid');
}
$new = clone $circle;

View file

@ -36,6 +36,7 @@ use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleAlreadyExistsException;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedEventDSyncException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\Exceptions\MemberAlreadyExistsException;
use OCA\Circles\Exceptions\MemberNotFoundException;
@ -84,7 +85,7 @@ class CircleCreate implements
/**
* Circles are created on the original instance, using IFederatedItemMustBeLocal
* Circles are created on the original instance, using IFederatedItemInitiatorMustBeLocal
*
* @param FederatedEvent $event
*/
@ -99,9 +100,8 @@ class CircleCreate implements
/**
* @param FederatedEvent $event
*
* @throws FederatedEventDSyncException
* @throws InvalidIdException
* @throws MemberAlreadyExistsException
* @throws CircleAlreadyExistsException
*/
public function manage(FederatedEvent $event): void {
$circle = $event->getCircle();
@ -109,13 +109,13 @@ class CircleCreate implements
try {
$this->circleRequest->getCircle($circle->getId());
throw new CircleAlreadyExistsException();
throw new FederatedEventDSyncException('circle already exist');
} catch (CircleNotFoundException $e) {
}
try {
$this->memberRequest->getMember($owner->getId());
throw new MemberAlreadyExistsException();
throw new FederatedEventDSyncException('owner already exist');
} catch (MemberNotFoundException $e) {
}

View file

@ -41,6 +41,11 @@ use Exception;
use OC\User\NoUserException;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedItemBadRequestException;
use OCA\Circles\Exceptions\FederatedItemForbiddenException;
use OCA\Circles\Exceptions\FederatedItemNotFoundException;
use OCA\Circles\Exceptions\FederatedItemRemoteException;
use OCA\Circles\Exceptions\FederatedItemServerException;
use OCA\Circles\Exceptions\FederatedUserException;
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
use OCA\Circles\Exceptions\InvalidIdException;
@ -138,21 +143,11 @@ class MemberAdd implements
/**
* @param FederatedEvent $event
*
* @throws CircleNotFoundException
* @throws FederatedUserException
* @throws FederatedUserNotFoundException
* @throws InvalidItemException
* @throws MemberAlreadyExistsException
* @throws MemberNotFoundException
* @throws MembersLimitException
* @throws OwnerNotFoundException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
* @throws UserTypeNotFoundException
* @throws FederatedItemBadRequestException
* @throws FederatedItemForbiddenException
* @throws FederatedItemNotFoundException
* @throws FederatedItemServerException
* @throws FederatedItemRemoteException
*/
public function verify(FederatedEvent $event): void {
$member = $event->getMember();
@ -165,13 +160,12 @@ class MemberAdd implements
$initiatorHelper->mustBeModerator();
$federatedId = $member->getUserId() . '@' . $member->getInstance();
try {
$federatedUser =
$this->federatedUserService->getFederatedUser($federatedId, $member->getUserType());
} catch (MemberNotFoundException $e) {
throw new MemberNotFoundException(
ucfirst(Member::$DEF_TYPE[$member->getUserType()]) . ' %s not found',
ucfirst(Member::$DEF_TYPE[$member->getUserType()]) . ' \'%s\' not found',
['member' => $member->getUserId() . '@' . $member->getInstance()]
);
}

View file

@ -34,12 +34,14 @@ namespace OCA\Circles\FederatedItems;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\FederatedItemBadRequestException;
use OCA\Circles\Exceptions\MemberLevelException;
use OCA\Circles\IFederatedItem;
use OCA\Circles\IFederatedItemMemberRequired;
use OCA\Circles\Model\Federated\FederatedEvent;
use OCA\Circles\Model\Helpers\MemberHelper;
use OCA\Circles\Model\Member;
use OCP\AppFramework\Http;
/**
@ -70,6 +72,8 @@ class MemberLevel implements
* @param FederatedEvent $event
*
* @throws FederatedItemException
* @throws FederatedItemBadRequestException
* @throws MemberLevelException
*/
public function verify(FederatedEvent $event): void {
$circle = $event->getCircle();
@ -78,11 +82,12 @@ class MemberLevel implements
$level = $event->getData()->gInt('level');
if ($level === 0) {
throw new FederatedItemException('invalid level');
// TODO check all level
throw new FederatedItemBadRequestException('invalid level');
}
if ($member->getLevel() === $level) {
throw new FederatedItemException('This member already have the selected level');
throw new FederatedItemBadRequestException('This member already have the selected level');
}
$initiatorHelper = new MemberHelper($initiator);

View file

@ -0,0 +1,139 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles;
use OCA\Circles\Model\Federated\FederatedEvent;
/**
* Interface IFederatedItemShareManagement
*
* @package OCA\Circles
*/
interface IFederatedItemShareManagement {
/**
* /!\ un Item est sharable a un Federated Circle seulement depuis l'instance qui lock l'Item.
*
*
* | Instance A | Instance B | Instance C | Instance D | Instance E |
* | | | | | |
* | --- Circle A --- | ---------------- | | | |
* | | ---------------- | --- Circle C --- | ---------------- | |
* | ---------------- | --- Circle B --- | ---------------- | | |
* | | ---------------- | ---------------- | --- Circle D --- | ---------------- |
* | | | | | |
* | | | | | |
* | Create Item1 | | | | |
* | Lock Item1 | | | | |
* | Share I1, Ca | Lock I1, Ia, Ca | | | |
* | get I1 local | get I1 on Ia | | | | OK: Get Item1 pour Circle A sur Instance A
* | | | | | |
* | Reshare I1, Cb | Lock I1, Ia, Cb | Lock I1, Ia, Cb | | |
* | get I1 local | get I1 on Ia | | | | OK: Get Item1 pour Circle B sur Instance A, via Instance B
* | | | | | |
* | Create Item2 | | | | |
* | Lock Item2 | | | | |
* | Share I2, CB | Lock I2, Ia, Cb | Lock I2, Ia, Cb | | |
* | get I2 local | get I2 on Ia | get I2 on Ia | | | OK: Get Item2 pour Circle B sur Instance A, via Instance B
* | | | | | |
* | Create Item3 | | | | |
* | Lock Item3 | | | | |
* | Share I3, Ca | | | | |
* | get I3 local | get I3 on Ia | | | | OK: Get Item3 pour Circle A sur Instance A
* | | | | | |
* | | Reshare I3, Cb | | | | ERROR
* | | Reshare I2, Cc | | | | ERROR
* | | | | | |
* | | | | | Create Item1 | (spoof, as Item must be unique)
* | | | | | Lock Item1 |
* | | I1 already exist | I1 already exist | Lock I1, Ie, Cd | Share I1, Cd | fail on Ib
* | | ERROR | ERROR | get I1 on Ie | get I1 local |
* | | | | | |
* | | | | * Join Circle B | |
* | ---------------- | --- Circle B --- | ---------------- | ---------------- | |
* | | | | shares from Ib | |
* | | | | I1 already exist | | fail on I1
* | | | | Lock I2, Ia, Cb | | OK: Get Item2 pour Circle B sur Instance A, via Instance B
* | | | | | |
* | | | | | |
* | | | | | |
* | | | | | |
*
*
*
*
*
* (on all instances) ShareLocks: itemId, singleId, instanceId, appId, circleId
*
* FederatedItem implements shareCreate(), shareUpdate(), shareDelete()
* FederatedEvent have isSharable()
*
*
* ////
* ////
* ///
* seulement aux circles qui on un membre dont on ne peut pas reshare un object deja share a un federated circle,
* si le owner de l'item n'est pas sur la meme instance
*
* instance A cree un circle A et invite instance B et instance C
* instance B cree un circle B et invite instance A et instance C
* instance C cree un item et le share a Circle A et a Circle B
* instance A et instance B possede chacun 2 locks vers instance C pour le meme item via 2 Circles.
*
* instance A cree un circle A2 et invite instance B et instance D
* instance A reshare item vers Circle A2 et cree un 3eme lock vers instance C via Circle A2.
*
* instance D tente de reshare et request instance A qui request instance C
*
*
*/
/**
* @param FederatedEvent $event
*/
public function shareCreate(FederatedEvent $event): void;
/**
* @param FederatedEvent $event
*/
public function shareUpdate(FederatedEvent $event): void;
/**
* @param FederatedEvent $event
*/
public function shareDelete(FederatedEvent $event): void;
}

View file

@ -39,5 +39,7 @@ namespace OCA\Circles;
*/
interface IFederatedItemSharedItem {
// meaning that the verify() will be run on the instance that locked the item, not on the main instance of the Circle.
}

View file

@ -82,7 +82,7 @@ class Version0021Date20210105123456 extends SimpleMigrationStep {
if (!$circles->hasColumn('instance')) {
$circles->addColumn(
'instance', 'string', [
'notnull' => true,
'notnull' => false,
'default' => '',
'length' => 255
]

View file

@ -71,6 +71,9 @@ class FederatedEvent implements JsonSerializable {
/** @var string */
private $itemId = '';
/** @var string */
private $itemSource = '';
/** @var Member */
private $member;
@ -352,7 +355,6 @@ class FederatedEvent implements JsonSerializable {
}
/**
* @param string $itemId
*
@ -372,6 +374,25 @@ class FederatedEvent implements JsonSerializable {
}
/**
* @param string $itemSource
*
* @return self
*/
public function setItemSource(string $itemSource): self {
$this->itemSource = $itemSource;
return $this;
}
/**
* @return string
*/
public function getItemSource(): string {
return $this->itemSource;
}
/**
* @return Member
*/
@ -525,12 +546,11 @@ class FederatedEvent implements JsonSerializable {
$this->setData(new SimpleDataStore($this->getArray('data', $data)));
$this->setResult(new SimpleDataStore($this->getArray('result', $data)));
$this->setSource($this->get('source', $data));
$this->setItemId($this->get('itemId', $data));
if (array_key_exists('circle', $data)) {
$circle = new Circle();
$circle->import($this->getArray('circle', $data));
$this->setCircle($circle);
}
$circle = new Circle();
$circle->import($this->getArray('circle', $data));
$this->setCircle($circle);
if (array_key_exists('member', $data)) {
$member = new Member();
@ -552,7 +572,9 @@ class FederatedEvent implements JsonSerializable {
'data' => $this->getData(),
'result' => $this->getResult(),
'source' => $this->getSource(),
'outcome' => [
'itemId' => $this->getItemId(),
'outcome' => [
'message' => $this->getReadingOutcome(),
'data' => $this->getDataOutcome()
]

View file

@ -33,6 +33,7 @@ namespace OCA\Circles\Model\Federated;
use daita\MySmallPhpTools\Db\Nextcloud\nc21\INC21QueryRow;
use daita\MySmallPhpTools\Exceptions\InvalidItemException;
use daita\MySmallPhpTools\Traits\TArrayTools;
use JsonSerializable;
@ -202,6 +203,7 @@ class RemoteWrapper implements INC21QueryRow, JsonSerializable {
* @param array $data
*
* @return self
* @throws InvalidItemException
*/
public function import(array $data): self {
$this->setToken($this->get('token', $data));
@ -238,6 +240,7 @@ class RemoteWrapper implements INC21QueryRow, JsonSerializable {
* @param array $data
*
* @return INC21QueryRow
* @throws InvalidItemException
*/
public function importFromDatabase(array $data): INC21QueryRow {
$this->setToken($this->get('token', $data));

View file

@ -36,7 +36,6 @@ use daita\MySmallPhpTools\Exceptions\InvalidItemException;
use daita\MySmallPhpTools\IDeserializable;
use daita\MySmallPhpTools\Traits\TArrayTools;
use JsonSerializable;
use OCA\Circles\IFederatedModel;
use OCA\Circles\IFederatedUser;

View file

@ -34,21 +34,21 @@ namespace OCA\Circles\Model\Helpers;
use daita\MySmallPhpTools\Traits\TArrayTools;
use OCA\Circles\Exceptions\MemberHelperException;
use OCA\Circles\Exceptions\MemberLevelException;
use OCA\Circles\Exceptions\ParseMemberLevelException;
use OCA\Circles\Model\Member;
/**
* Class MemberHelper
*
*
* @method void mustBeMember() @throws MemberHelperException
* @method void mustBeModerator() @throws MemberHelperException
* @method void mustBeAdmin() @throws MemberHelperException
* @method void mustBeOwner() @throws MemberHelperException
* @method void cannotBeMember() @throws MemberHelperException
* @method void cannotBeModerator() @throws MemberHelperException
* @method void cannotBeAdmin() @throws MemberHelperException
* @method void cannotBeOwner() @throws MemberHelperException
* @method void mustBeMember() @throws MemberHelperException, MemberLevelException
* @method void mustBeModerator() @throws MemberHelperException, MemberLevelException
* @method void mustBeAdmin() @throws MemberHelperException, MemberLevelException
* @method void mustBeOwner() @throws MemberHelperException, MemberLevelException
* @method void cannotBeMember() @throws MemberHelperException, MemberLevelException
* @method void cannotBeModerator() @throws MemberHelperException, MemberLevelException
* @method void cannotBeAdmin() @throws MemberHelperException, MemberLevelException
* @method void cannotBeOwner() @throws MemberHelperException, MemberLevelException
*
* @package OCA\Circles\Model\Helpers
*/
@ -103,7 +103,7 @@ class MemberHelper {
private function mustBe(string $levelString, array $arguments): void {
try {
$level = Member::parseLevelString($levelString);
} catch (MemberLevelException $e) {
} catch (ParseMemberLevelException $e) {
throw new MemberHelperException('method ' . $levelString . ' not found');
}
@ -121,7 +121,7 @@ class MemberHelper {
private function cannotBe(string $levelString, array $arguments): void {
try {
$level = Member::parseLevelString($levelString);
} catch (MemberLevelException $e) {
} catch (ParseMemberLevelException $e) {
throw new MemberHelperException('method ' . $levelString . ' not found');
}

View file

@ -123,17 +123,8 @@ class CircleService {
* @param string $name
* @param FederatedUser|null $owner
*
* @return Circle
* @throws FederatedEventException
* @throws InitiatorNotConfirmedException
* @return SimpleDataStore
* @throws InitiatorNotFoundException
* @throws OwnerNotFoundException
* @throws FederatedItemException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws UnknownRemoteException
* @throws RequestNetworkException
* @throws SignatoryException
*/
public function create(string $name, ?FederatedUser $owner = null): SimpleDataStore {
$this->federatedUserService->mustHaveCurrentUser();
@ -188,7 +179,7 @@ class CircleService {
$event->setData(new SimpleDataStore(['config' => $config]));
$this->federatedEventService->newEvent($event);
return $event->getOutcome();
}
@ -236,9 +227,9 @@ class CircleService {
* @throws MembersLimitException
*/
public function confirmCircleNotFull(Circle $circle): void {
if ($this->isCircleFull($circle)) {
throw new MembersLimitException('circle is full');
}
// if ($this->isCircleFull($circle)) {
// throw new MembersLimitException('Circle \'%s\' is full and cannot accept more members', ['circleName' => $circle->getDisplayName()]);
// }
}
/**

View file

@ -70,7 +70,6 @@ class ConfigService {
const INTERNAL_CLOUD_SCHEME = 'internal_cloud_scheme';
const FORCE_NC_BASE = 'force_nc_base';
const TEST_NC_BASE = 'test_nc_base';
@ -101,8 +100,8 @@ class ConfigService {
self::CIRCLES_SELF_SIGNED => '0',
self::FRONTAL_CLOUD_ID => '',
self::FRONTAL_CLOUD_SCHEME => 'https',
self::INTERNAL_CLOUD_ID => '',
self::INTERNAL_CLOUD_SCHEME => 'https',
self::INTERNAL_CLOUD_ID => '',
self::INTERNAL_CLOUD_SCHEME => 'https',
self::FORCE_NC_BASE => '',
self::TEST_NC_BASE => '',
self::CIRCLES_ACTIVITY_ON_CREATION => '1',
@ -669,6 +668,7 @@ class ConfigService {
}
$request->setVerifyPeer($this->getAppValue(ConfigService::CIRCLES_SELF_SIGNED) !== '1');
$request->setHttpErrorsAllowed(true);
$request->setLocalAddressAllowed(true);
$request->setFollowLocation(true);
$request->setTimeout(5);

View file

@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2021
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Service;
use OCP\IL10N;
/**
* Class ExceptionService
*
* @package OCA\Circles\Service
*/
class ExceptionService {
/** @var IL10N */
private $l10n;
/**
* ExceptionService constructor.
*
* @param IL10N $l10n
*/
public function __construct(IL10N $l10n) {
$this->l10n = $l10n;
}
/**
* @return IL10N
*/
public function getL10n(): IL10N {
return $this->l10n;
}
}

View file

@ -44,9 +44,9 @@ use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Db\RemoteRequest;
use OCA\Circles\Db\RemoteWrapperRequest;
use OCA\Circles\Db\ShareLockRequest;
use OCA\Circles\Exceptions\FederatedEventDSyncException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\FederatedShareBelongingException;
use OCA\Circles\Exceptions\FederatedShareNotFoundException;
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
use OCA\Circles\Exceptions\JsonException;
@ -150,38 +150,28 @@ class FederatedEventService extends NC21Signature {
* @param FederatedEvent $event
*
* @return SimpleDataStore
* @throws FederatedEventException
* @throws FederatedItemException
* @throws InitiatorNotConfirmedException
* @throws OwnerNotFoundException
* @throws FederatedEventException
* @throws RequestNetworkException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws UnknownRemoteException
* @throws SignatoryException
* @throws FederatedItemException
* @throws FederatedEventDSyncException
*/
public function newEvent(FederatedEvent $event): SimpleDataStore {
$event->setSource($this->configService->getFrontalInstance());
try {
$federatedItem = $this->getFederatedItem($event, false);
} catch (FederatedEventException $e) {
$this->e($e);
throw $e;
}
$federatedItem = $this->getFederatedItem($event, false);
$this->confirmInitiator($event, true);
if ($this->configService->isLocalInstance($event->getCircle()->getInstance())) {
$event->setIncomingOrigin($event->getCircle()->getInstance());
try {
$federatedItem->verify($event);
$reading = $event->getReadingOutcome();
$reading->s('translated', $this->l10n->t($reading->g('message'), $reading->gArray('params')));
} catch (FederatedItemException $e) {
throw new FederatedItemException($this->l10n->t($e->getMessage(), $e->getParams()));
}
$federatedItem->verify($event);
$reading = $event->getReadingOutcome();
$reading->s('translated', $this->l10n->t($reading->g('message'), $reading->gArray('params')));
if ($event->isDataRequestOnly()) {
return $event->getDataOutcome();
@ -272,9 +262,10 @@ class FederatedEventService extends NC21Signature {
$this->setFederatedEventBypass($event, $item);
$this->confirmRequiredCondition($event, $item, $checkLocalOnly);
$this->confirmSharedItem($event, $item);
$this->configureEvent($event, $item);
// $this->confirmSharedItem($event, $item);
return $item;
}
@ -344,8 +335,10 @@ class FederatedEventService extends NC21Signature {
* @param FederatedEvent $event
* @param IFederatedItem $item
*
* @throws FederatedShareNotFoundException
* @throws FederatedEventException
* @throws FederatedShareBelongingException
* @throws FederatedShareNotFoundException
* @throws OwnerNotFoundException
*/
private function confirmSharedItem(FederatedEvent $event, IFederatedItem $item): void {
if (!$item instanceof IFederatedItemSharedItem) {
@ -356,9 +349,11 @@ class FederatedEventService extends NC21Signature {
throw new FederatedEventException('FederatedItem must contains ItemId');
}
$shareLock = $this->shareLockRequest->getShare($event->getItemId());
if ($shareLock->getInstance() !== $event->getIncomingOrigin()) {
throw new FederatedEventException('ShareLock belongs to another instance');
if ($this->configService->isLocalInstance($event->getCircle()->getInstance())) {
$shareLock = $this->shareLockRequest->getShare($event->getItemId());
if ($shareLock->getInstance() !== $event->getIncomingOrigin()) {
throw new FederatedShareBelongingException('ShareLock belongs to another instance');
}
}
}

View file

@ -52,6 +52,7 @@ use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteInstanceException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\SingleCircleNotFoundException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\Exceptions\UserTypeNotFoundException;
use OCA\Circles\IFederatedUser;
@ -132,9 +133,10 @@ class FederatedUserService {
/**
* @param IUser|null $user
*
* @throws CircleNotFoundException
* @throws FederatedUserException
* @throws FederatedUserNotFoundException
* @throws InvalidIdException
* @throws SingleCircleNotFoundException
*/
public function setLocalCurrentUser(?IUser $user) {
if ($user === null) {
@ -231,9 +233,10 @@ class FederatedUserService {
* @param string $userId
*
* @return FederatedUser
* @throws CircleNotFoundException
* @throws FederatedUserNotFoundException
* @throws InvalidIdException
* @throws SingleCircleNotFoundException
* @throws FederatedUserException
*/
public function getLocalFederatedUser(string $userId): FederatedUser {
$user = $this->userManager->get($userId);
@ -367,7 +370,7 @@ class FederatedUserService {
&& ($instance === '' || $this->configService->isLocalInstance($instance))) {
return $this->getLocalFederatedUser($userId);
}
} catch (CircleNotFoundException | FederatedUserNotFoundException | InvalidIdException $e) {
} catch (Exception $e) {
}
try {
@ -415,16 +418,13 @@ class FederatedUserService {
* @throws CircleNotFoundException
* @throws FederatedUserException
* @throws FederatedUserNotFoundException
* @throws InvalidItemException
* @throws MemberNotFoundException
* @throws OwnerNotFoundException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
* @throws UserTypeNotFoundException
* @throws RemoteInstanceException
*/
public function getFederatedUser(string $federatedId, int $userType = Member::TYPE_USER): FederatedUser {
list($singleId, $instance) = $this->extractIdAndInstance($federatedId);
@ -456,13 +456,10 @@ class FederatedUserService {
* @return FederatedUser
* @throws FederatedUserException
* @throws FederatedUserNotFoundException
* @throws InvalidItemException
* @throws MemberNotFoundException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
*/
private function getFederatedUser_SingleId(string $singleId, string $instance): FederatedUser {
@ -487,16 +484,13 @@ class FederatedUserService {
* @param string $instance
*
* @return FederatedUser
* @throws CircleNotFoundException
* @throws FederatedUserException
* @throws FederatedUserNotFoundException
* @throws InvalidIdException
* @throws InvalidItemException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws SingleCircleNotFoundException
* @throws UnknownRemoteException
*/
private function getFederatedUser_User(string $userId, string $instance): FederatedUser {
@ -522,13 +516,10 @@ class FederatedUserService {
* @throws CircleNotFoundException
* @throws FederatedUserException
* @throws FederatedUserNotFoundException
* @throws InvalidItemException
* @throws OwnerNotFoundException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
*/
private function getFederatedUser_Circle(string $circleId, string $instance): FederatedUser {
@ -571,8 +562,9 @@ class FederatedUserService {
/**
* @param FederatedUser $federatedUser
*
* @throws CircleNotFoundException
* @throws InvalidIdException
* @throws SingleCircleNotFoundException
* @throws FederatedUserException
*/
private function fillSingleCircleId(FederatedUser $federatedUser): void {
if ($federatedUser->getSingleId() !== '') {
@ -590,9 +582,9 @@ class FederatedUserService {
* @param FederatedUser $federatedUser
*
* @return Circle
* @throws CircleNotFoundException
* @throws InvalidIdException
* @throws FederatedUserException
* @throws SingleCircleNotFoundException
*/
private function getSingleCircle(FederatedUser $federatedUser): Circle {
if (!$this->configService->isLocalInstance($federatedUser->getInstance())) {
@ -600,8 +592,8 @@ class FederatedUserService {
}
try {
return $this->circleRequest->getInitiatorCircle($federatedUser);
} catch (CircleNotFoundException $e) {
return $this->circleRequest->getSingleCircle($federatedUser);
} catch (SingleCircleNotFoundException $e) {
$circle = new Circle();
$id = $this->token(ManagedModel::ID_LENGTH);
@ -616,12 +608,12 @@ class FederatedUserService {
->setCircleId($id)
->setSingleId($id)
->setId($id)
->setCachedName($owner->getUserId())
->setDisplayName($owner->getUserId())
->setStatus('Member');
$this->memberRequest->save($owner);
}
return $this->circleRequest->getInitiatorCircle($federatedUser);
return $this->circleRequest->getSingleCircle($federatedUser);
}

View file

@ -131,14 +131,12 @@ class MemberService {
*
* @return Member
* @throws InitiatorNotFoundException
* @throws MemberLevelException
* @throws MemberNotFoundException
*/
public function getMember(string $memberId, string $circleId = ''): Member {
$this->federatedUserService->mustHaveCurrentUser();
try {
$member =
$this->memberRequest->getMember($memberId, $this->federatedUserService->getCurrentUser());
$member = $this->memberRequest->getMember($memberId, $this->federatedUserService->getCurrentUser());
if ($circleId !== '' && $member->getCircle()->getId() !== $circleId) {
throw new MemberNotFoundException();
}
@ -153,10 +151,10 @@ class MemberService {
// }
return $member;
} catch (Exception $e) {
$this->e($e, ['id' => $memberId, 'initiator' => $this->federatedUserService->getCurrentUser()]);
throw new MemberLevelException('insufficient rights');
}
// } catch (Exception $e) {
// $this->e($e, ['id' => $memberId, 'initiator' => $this->federatedUserService->getCurrentUser()]);
// throw new MemberLevelException('insufficient rights');
// }
}

View file

@ -129,13 +129,13 @@ class RemoteDownstreamService {
$item = $this->federatedEventService->getFederatedItem($event, true);
if (!$this->configService->isLocalInstance($event->getCircle()->getInstance())) {
throw new FederatedEventException('Circle is not from this instance');
throw new FederatedEventDSyncException('Circle is not from this instance');
}
if ($event->isLimitedToInstanceWithMember()) {
$instances = $this->memberRequest->getMemberInstances($event->getCircle()->getId());
if (!in_array($event->getIncomingOrigin(), $instances)) {
throw new FederatedItemException('Instance have no members in this Circle');
throw new FederatedEventException('Instance have no members in this Circle');
}
}

View file

@ -40,6 +40,7 @@ use daita\MySmallPhpTools\Model\SimpleDataStore;
use OCA\Circles\Db\CircleRequest;
use OCA\Circles\Db\MemberRequest;
use OCA\Circles\Exceptions\CircleNotFoundException;
use OCA\Circles\Exceptions\FederatedUserException;
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
use OCA\Circles\Exceptions\InvalidIdException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
@ -303,14 +304,12 @@ class RemoteService extends NC21Signature {
* @param int $type
*
* @return FederatedUser
* @throws InvalidItemException
* @throws FederatedUserNotFoundException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
* @throws RemoteInstanceException
* @throws FederatedUserNotFoundException
* @throws FederatedUserException
*/
public function getFederatedUserFromInstance(
string $userId,
@ -331,9 +330,13 @@ class RemoteService extends NC21Signature {
}
$federatedUser = new FederatedUser();
$federatedUser->import($result);
try {
$federatedUser->import($result);
} catch (InvalidItemException $e) {
throw new FederatedUserException('incorrect federated user returned from instance');
}
if ($federatedUser->getInstance() !== $instance) {
throw new InvalidItemException('incorrect instance');
throw new FederatedUserException('incorrect instance on returned federated user');
}
return $federatedUser;

View file

@ -55,7 +55,6 @@ use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
use OCA\Circles\Exceptions\RemoteUidException;
use OCA\Circles\Exceptions\UnknownRemoteException;
use OCA\Circles\Model\Federated\RemoteInstance;
use OCP\AppFramework\Http;
use OCP\IURLGenerator;
@ -184,12 +183,10 @@ class RemoteStreamService extends NC21Signature {
* @param array $params
*
* @return array
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
* @throws RemoteInstanceException
*/
public function resultRequestRemoteInstance(
string $instance,
@ -200,13 +197,13 @@ class RemoteStreamService extends NC21Signature {
): array {
$signedRequest = $this->requestRemoteInstance($instance, $item, $type, $object, $params);
if (!$signedRequest->getOutgoingRequest()->hasResult()) {
throw new RequestNetworkException();
throw new RemoteInstanceException();
}
$result = $signedRequest->getOutgoingRequest()->getResult();
if ($result->getStatusCode() !== Http::STATUS_OK) {
throw new RemoteInstanceException();
}
// if ($result->getStatusCode() !== Http::STATUS_OK) {
// throw new RemoteInstanceException();
// }
return $result->getAsArray();
}
@ -227,9 +224,8 @@ class RemoteStreamService extends NC21Signature {
* @return NC21SignedRequest
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
* @throws RemoteInstanceException
*/
public function requestRemoteInstance(
string $instance,
@ -248,7 +244,7 @@ class RemoteStreamService extends NC21Signature {
$request->basedOnUrl($link);
}
// TODO: on local, if object is empty, request takes 10s. check on other configuration
// TODO: Work Around: on local, if object is empty, request takes 10s. check on other configuration
if (is_null($object) || empty(json_decode(json_encode($object), true))) {
$object = new SimpleDataStore(['empty' => 1]);
}
@ -257,10 +253,14 @@ class RemoteStreamService extends NC21Signature {
$request->setDataSerialize($object);
}
$app = $this->getAppSignatory();
try {
$app = $this->getAppSignatory();
// $app->setAlgorithm(NC21Signatory::SHA512);
$signedRequest = $this->signOutgoingRequest($request, $app);
$this->doRequest($signedRequest->getOutgoingRequest(), false);
$signedRequest = $this->signOutgoingRequest($request, $app);
$this->doRequest($signedRequest->getOutgoingRequest(), false);
} catch (RequestNetworkException | SignatoryException $e) {
throw new RemoteInstanceException($e->getMessage());
}
return $signedRequest;
}

View file

@ -34,6 +34,7 @@ namespace OCA\Circles\Service;
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
use daita\MySmallPhpTools\Exceptions\SignatoryException;
use daita\MySmallPhpTools\Model\Nextcloud\nc21\NC21RequestResult;
use daita\MySmallPhpTools\Model\Request;
use daita\MySmallPhpTools\Model\SimpleDataStore;
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Request;
@ -41,6 +42,7 @@ use Exception;
use OCA\Circles\Db\RemoteWrapperRequest;
use OCA\Circles\Exceptions\FederatedEventDSyncException;
use OCA\Circles\Exceptions\FederatedEventException;
use OCA\Circles\Exceptions\FederatedItemException;
use OCA\Circles\Exceptions\OwnerNotFoundException;
use OCA\Circles\Exceptions\RemoteInstanceException;
use OCA\Circles\Exceptions\RemoteNotFoundException;
@ -53,6 +55,8 @@ use OCA\Circles\Model\GlobalScale\GSEvent;
use OCA\Circles\Model\GlobalScale\GSWrapper;
use OCP\AppFramework\Http;
use OCP\IL10N;
use ReflectionClass;
use ReflectionException;
/**
@ -159,14 +163,15 @@ class RemoteUpstreamService {
/**
* @param FederatedEvent $event
*
* @throws FederatedEventDSyncException
* @throws FederatedEventException
* @throws OwnerNotFoundException
* @throws RemoteInstanceException
* @throws RemoteNotFoundException
* @throws RemoteResourceNotFoundException
* @throws RequestNetworkException
* @throws SignatoryException
* @throws UnknownRemoteException
* @throws OwnerNotFoundException
* @throws RequestNetworkException
* @throws FederatedEventException
* @throws FederatedEventDSyncException
*/
public function confirmEvent(FederatedEvent $event): void {
$data = $this->remoteStreamService->requestRemoteInstance(
@ -178,23 +183,17 @@ class RemoteUpstreamService {
// TODO: check what is happening if website is down...
if (!$data->getOutgoingRequest()->hasResult()) {
throw new RequestNetworkException();
throw new RemoteInstanceException();
}
$result = $data->getOutgoingRequest()->getResult();
$this->manageRequestOutcome($event, $result->getAsArray());
$reading = $event->getReadingOutcome();
if ($result->getStatusCode() === Http::STATUS_CONFLICT) {
throw new FederatedEventDSyncException($reading->g('translated'));
}
if ($result->getStatusCode() === Http::STATUS_OK && !$reading->gBool('fail')) {
if ($result->getStatusCode() === Http::STATUS_OK) {
return;
}
throw new FederatedEventException($reading->g('translated'));
throw $this->getFederatedItemExceptionFromResult($result, $event->getReadingOutcome());
}
@ -376,13 +375,77 @@ class RemoteUpstreamService {
$event->setDataOutcome($outcome->gArray('data'));
$event->setReadingOutcome(
$outcome->g('reading.message'),
$outcome->gArray('reading.params'),
$outcome->gBool('reading.fail')
$outcome->gArray('reading.params')
);
$reading = $event->getReadingOutcome();
$reading->s('translated', $this->l10n->t($reading->g('message'), $reading->gArray('params')));
}
private function getFederatedItemExceptionFromResult(
NC21RequestResult $result,
SimpleDataStore $reading
): FederatedItemException {
$exception = $reading->gArray('params._exception');
if (empty($exception)) {
$e = $this->getFederatedItemExceptionFromStatus($result->getStatusCode());
return new $e($reading->g('message'));
}
$class = $this->get('class', $exception);
$message = $this->get('message', $exception);
$params = $this->getArray('params', $exception);
try {
$test = new ReflectionClass($class);
$this->confirmFederatedItemExceptionFromClass($test);
$e = $class;
echo $e;
} catch (ReflectionException | FederatedItemException $_e) {
$e = $this->getFederatedItemExceptionFromStatus($result->getStatusCode());
}
return new $e($message, $params);
}
/**
* @param int $statusCode
*
* @return string
*/
private function getFederatedItemExceptionFromStatus(int $statusCode): string {
foreach (FederatedItemException::$CHILDREN as $e) {
if ($e::STATUS === $statusCode) {
return $e;
}
}
return FederatedItemException::class;
}
/**
* @param ReflectionClass $class
*
* @return void
* @throws FederatedItemException
*/
private function confirmFederatedItemExceptionFromClass(ReflectionClass $class): void {
while (true) {
foreach (FederatedItemException::$CHILDREN as $e) {
if ($class->getName() === $e) {
return;
}
}
$class = $class->getParentClass();
if (!$class) {
throw new FederatedItemException();
}
}
}
}