mirror of
https://github.com/netzbegruenung/circles.git
synced 2024-05-11 07:36:07 +02:00
multi instance
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
This commit is contained in:
parent
50999214c9
commit
6eb868f210
1
Makefile
1
Makefile
|
@ -37,6 +37,7 @@ clean:
|
|||
# composer packages
|
||||
composer:
|
||||
composer install --prefer-dist
|
||||
composer upgrade --prefer-dist
|
||||
|
||||
appstore: clean composer
|
||||
mkdir -p $(sign_dir)
|
||||
|
|
|
@ -66,7 +66,7 @@ return [
|
|||
// ['name' => 'EventWrapper#status', 'url' => '/v1/gs/status', 'verb' => 'POST'],
|
||||
|
||||
['name' => 'Remote#appService', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'Remote#test', 'url' => '/test/', 'verb' => 'GET'],
|
||||
['name' => 'Remote#test', 'url' => '/test', 'verb' => 'GET'],
|
||||
['name' => 'Remote#event', 'url' => '/event/', 'verb' => 'POST'],
|
||||
['name' => 'Remote#incoming', 'url' => '/incoming/', 'verb' => 'POST'],
|
||||
['name' => 'Remote#circles', 'url' => '/circles/', 'verb' => 'GET'],
|
||||
|
@ -75,3 +75,4 @@ return [
|
|||
['name' => 'Remote#member', 'url' => '/member/{type}/{userId}/', 'verb' => 'GET']
|
||||
]
|
||||
];
|
||||
|
||||
|
|
|
@ -34,19 +34,31 @@ use daita\MySmallPhpTools\Model\Nextcloud\nc22\NC22Request;
|
|||
use daita\MySmallPhpTools\Model\Request;
|
||||
use daita\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Request;
|
||||
use daita\MySmallPhpTools\Traits\TArrayTools;
|
||||
use daita\MySmallPhpTools\Traits\TStringTools;
|
||||
use Exception;
|
||||
use OC\Core\Command\Base;
|
||||
use OCA\Circles\AppInfo\Application;
|
||||
use OCA\Circles\AppInfo\Capabilities;
|
||||
use OCA\Circles\Model\GlobalScale\GSEvent;
|
||||
use OCA\Circles\Exceptions\FederatedEventException;
|
||||
use OCA\Circles\Exceptions\FederatedItemException;
|
||||
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
|
||||
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\FederatedItems\LoopbackTest;
|
||||
use OCA\Circles\Model\Federated\FederatedEvent;
|
||||
use OCA\Circles\Service\ConfigService;
|
||||
use OCA\Circles\Service\GlobalScaleService;
|
||||
use OCA\Circles\Service\GSUpstreamService;
|
||||
use OCA\Circles\Service\FederatedEventService;
|
||||
use OCA\Circles\Service\RemoteService;
|
||||
use OCA\Circles\Service\RemoteStreamService;
|
||||
use OCA\Circles\Service\RemoteUpstreamService;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -57,18 +69,31 @@ use Symfony\Component\Process\Process;
|
|||
class CirclesCheck extends Base {
|
||||
|
||||
|
||||
use TStringTools;
|
||||
use TArrayTools;
|
||||
use TNC22Request;
|
||||
|
||||
|
||||
static $checks = [
|
||||
'internal',
|
||||
'frontal',
|
||||
'loopback'
|
||||
];
|
||||
|
||||
/** @var Capabilities */
|
||||
private $capabilities;
|
||||
|
||||
/** @var GlobalScaleService */
|
||||
private $globalScaleService;
|
||||
/** @var FederatedEventService */
|
||||
private $federatedEventService;
|
||||
|
||||
/** @var GSUpstreamService */
|
||||
private $gsUpstreamService;
|
||||
/** @var RemoteService */
|
||||
private $remoteService;
|
||||
|
||||
/** @var RemoteStreamService */
|
||||
private $remoteStreamService;
|
||||
|
||||
/** @var RemoteUpstreamService */
|
||||
private $remoteUpstreamService;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
@ -80,23 +105,32 @@ class CirclesCheck extends Base {
|
|||
/** @var array */
|
||||
private $sessions = [];
|
||||
|
||||
|
||||
/**
|
||||
* CirclesCheck constructor.
|
||||
*
|
||||
* @param Capabilities $capabilities
|
||||
* @param GlobalScaleService $globalScaleService
|
||||
* @param GSUpstreamService $gsUpstreamService
|
||||
* @param FederatedEvent $federatedEventService
|
||||
* @param RemoteService $remoteService
|
||||
* @param RemoteStreamService $remoteStreamService
|
||||
* @param RemoteUpstreamService $remoteUpstreamService
|
||||
* @param ConfigService $configService
|
||||
*/
|
||||
public function __construct(
|
||||
Capabilities $capabilities, GlobalScaleService $globalScaleService,
|
||||
GSUpstreamService $gsUpstreamService, ConfigService $configService
|
||||
Capabilities $capabilities,
|
||||
FederatedEventService $federatedEventService,
|
||||
RemoteService $remoteService,
|
||||
RemoteStreamService $remoteStreamService,
|
||||
RemoteUpstreamService $remoteUpstreamService,
|
||||
ConfigService $configService
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
$this->capabilities = $capabilities;
|
||||
$this->gsUpstreamService = $gsUpstreamService;
|
||||
$this->globalScaleService = $globalScaleService;
|
||||
$this->federatedEventService = $federatedEventService;
|
||||
$this->remoteService = $remoteService;
|
||||
$this->remoteStreamService = $remoteStreamService;
|
||||
$this->remoteUpstreamService = $remoteUpstreamService;
|
||||
$this->configService = $configService;
|
||||
}
|
||||
|
||||
|
@ -107,7 +141,8 @@ class CirclesCheck extends Base {
|
|||
->setDescription('Checking your configuration')
|
||||
->addOption('delay', 'd', InputOption::VALUE_REQUIRED, 'delay before checking result')
|
||||
->addOption('capabilities', '', InputOption::VALUE_NONE, 'listing app\'s capabilities')
|
||||
->addOption('url', '', InputOption::VALUE_REQUIRED, 'specify a source url', '');
|
||||
->addOption('type', '', InputOption::VALUE_REQUIRED, 'configuration to check', '')
|
||||
->addOption('test', '', InputOption::VALUE_REQUIRED, 'specify an url to test', '');
|
||||
}
|
||||
|
||||
|
||||
|
@ -131,61 +166,455 @@ class CirclesCheck extends Base {
|
|||
}
|
||||
|
||||
$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
|
||||
$this->configService->setAppValue(ConfigService::TEST_NC_BASE, $input->getOption('url'));
|
||||
$test = $input->getOption('test');
|
||||
$type = $input->getOption('type');
|
||||
if ($test !== '' && $type === '') {
|
||||
throw new Exception('Please specify a --type for the test');
|
||||
}
|
||||
if ($test !== '' && !in_array($type, self::$checks)) {
|
||||
throw new Exception('Unknown type: ' . implode(', ', self::$checks));
|
||||
}
|
||||
|
||||
// $this->configService->setAppValue(ConfigService::TEST_NC_BASE, $test);
|
||||
|
||||
if ($type === '' || $type === 'loopback') {
|
||||
$output->writeln('### Checking <info>loopback</info> address.');
|
||||
$this->checkLoopback($input, $output, $test);
|
||||
$output->writeln('');
|
||||
$output->writeln('');
|
||||
}
|
||||
if ($type === '' || $type === 'internal') {
|
||||
$output->writeln('### Testing <info>internal</info> address.');
|
||||
$this->checkInternal($input, $output, $test);
|
||||
$output->writeln('');
|
||||
$output->writeln('');
|
||||
}
|
||||
if ($type === '' || $type === 'frontal') {
|
||||
$output->writeln('### Testing <info>frontal</info> address.');
|
||||
$this->checkFrontal($input, $output, $test);
|
||||
$output->writeln('');
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// if (!$this->testRequest($output, 'GET', 'core.CSRFToken.index')) {
|
||||
// $this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// if (!$this->testRequest(
|
||||
// $output, 'POST', 'circles.EventWrapper.asyncBroadcast',
|
||||
// ['token' => 'test-dummy-token']
|
||||
// )) {
|
||||
// $this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// $test = new GSEvent(GSEvent::TEST, true, true);
|
||||
// $test->setAsync(true);
|
||||
// $token = $this->gsUpstreamService->newEvent($test);
|
||||
//
|
||||
// $output->writeln('- Async request is sent, now waiting ' . $this->delay . ' seconds');
|
||||
// sleep($this->delay);
|
||||
// $output->writeln('- Pause is over, checking results for ' . $token);
|
||||
//
|
||||
// $wrappers = $this->gsUpstreamService->getEventsByToken($token);
|
||||
//
|
||||
// $result = [];
|
||||
// $instances = array_merge($this->globalScaleService->getInstances(true));
|
||||
// foreach ($wrappers as $wrapper) {
|
||||
// $result[$wrapper->getInstance()] = $wrapper->getEvent();
|
||||
// }
|
||||
//
|
||||
// $localLooksGood = false;
|
||||
// foreach ($instances as $instance) {
|
||||
// $output->write($instance . ' ');
|
||||
// if (array_key_exists($instance, $result)
|
||||
// && $result[$instance]->getResult()
|
||||
// ->gInt('status') === 1) {
|
||||
// $output->writeln('<info>ok</info>');
|
||||
// if ($this->configService->isLocalInstance($instance)) {
|
||||
// $localLooksGood = true;
|
||||
// }
|
||||
// } else {
|
||||
// $output->writeln('<error>fail</error>');
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// $this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
|
||||
//
|
||||
// if ($localLooksGood) {
|
||||
// $this->saveUrl($input, $output, $input->getOption('url'));
|
||||
// }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @param string $test
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function checkLoopback(InputInterface $input, OutputInterface $output, string $test = ''): void {
|
||||
$output->writeln('. The <info>loopback</info> setting is mandatory and can be checked locally.');
|
||||
$output->writeln(
|
||||
'. The address you need to define here must be a reachable url of your Nextcloud from the hosting server itself.'
|
||||
);
|
||||
$output->writeln(
|
||||
'. By default, the App will use the entry \'overwrite.cli.url\' from \'config/config.php\'.'
|
||||
);
|
||||
|
||||
if ($test === '') {
|
||||
$test = $this->configService->getLoopbackPath();
|
||||
}
|
||||
|
||||
$output->writeln('');
|
||||
$output->writeln('* testing current address: ' . $test);
|
||||
|
||||
try {
|
||||
$this->setupLoopback($input, $output, $test);
|
||||
$output->writeln('* <info>Loopback</info> address looks good');
|
||||
$output->writeln('saving');
|
||||
} catch (Exception $e) {
|
||||
$output->writeln('<error>' . $e->getMessage() . '</error>');
|
||||
}
|
||||
|
||||
$output->writeln('- You do not have a valid <info>loopback</info> address setup right now.');
|
||||
|
||||
$helper = $this->getHelper('question');
|
||||
while (true) {
|
||||
$question = new Question(
|
||||
'<info>Please write down a new loopback address to test</info>: ', ''
|
||||
);
|
||||
|
||||
$loopback = $helper->ask($input, $output, $question);
|
||||
if (is_null($loopback) || $loopback === '') {
|
||||
$output->writeln('exiting.');
|
||||
throw new Exception('Your Circles App is not fully configured.');
|
||||
}
|
||||
|
||||
try {
|
||||
[$scheme, $cloudId] = $this->parseAddress($loopback);
|
||||
} catch (Exception $e) {
|
||||
$output->writeln('<error>format must be http[s]://domain.name[:post]</error>');
|
||||
continue;
|
||||
}
|
||||
|
||||
$loopback = $scheme . '://' . $cloudId;
|
||||
$output->write('* testing address: ' . $loopback . ' ');
|
||||
|
||||
if ($this->testLoopback($input, $output, $loopback)) {
|
||||
$output->writeln('<info>ok</info>');
|
||||
$output->writeln('saving.');
|
||||
$this->configService->setAppValue(ConfigService::LOOPBACK_CLOUD_SCHEME, $scheme);
|
||||
$this->configService->setAppValue(ConfigService::LOOPBACK_CLOUD_ID, $cloudId);
|
||||
$output->writeln(
|
||||
'- Address <info>' . $loopback . '</info> is now used as <info>loopback</info>'
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$output->writeln('<error>fail</error>');
|
||||
}
|
||||
// while(true) {
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function setupLoopback(InputInterface $input, OutputInterface $output, string $address): void {
|
||||
$e = null;
|
||||
try {
|
||||
[$scheme, $cloudId] = $this->parseAddress($address);
|
||||
|
||||
$this->configService->setAppValue(ConfigService::LOOPBACK_TMP_SCHEME, $scheme);
|
||||
$this->configService->setAppValue(ConfigService::LOOPBACK_TMP_ID, $cloudId);
|
||||
if (!$this->testLoopback($input, $output, $address)) {
|
||||
throw new Exception('fail');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
$this->configService->setAppValue(ConfigService::LOOPBACK_TMP_SCHEME, '');
|
||||
$this->configService->setAppValue(ConfigService::LOOPBACK_TMP_ID, '');
|
||||
|
||||
if (!is_null($e)) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @param string $address
|
||||
*
|
||||
* @return bool
|
||||
* @throws RequestNetworkException
|
||||
* @throws FederatedEventException
|
||||
* @throws FederatedItemException
|
||||
* @throws InitiatorNotConfirmedException
|
||||
* @throws OwnerNotFoundException
|
||||
* @throws RemoteInstanceException
|
||||
* @throws RemoteNotFoundException
|
||||
* @throws RemoteResourceNotFoundException
|
||||
* @throws UnknownRemoteException
|
||||
*/
|
||||
private function testLoopback(InputInterface $input, OutputInterface $output, string $address): bool {
|
||||
if (!$this->testRequest($output, 'GET', 'core.CSRFToken.index')) {
|
||||
$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->testRequest(
|
||||
$output, 'POST', 'circles.EventWrapper.asyncBroadcast',
|
||||
['token' => 'test-dummy-token']
|
||||
)) {
|
||||
$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
$test = new GSEvent(GSEvent::TEST, true, true);
|
||||
$test = new FederatedEvent(LoopbackTest::class);
|
||||
$test->setAsync(true);
|
||||
$token = $this->gsUpstreamService->newEvent($test);
|
||||
$this->federatedEventService->newEvent($test);
|
||||
|
||||
$output->writeln('- Async request is sent, now waiting ' . $this->delay . ' seconds');
|
||||
sleep($this->delay);
|
||||
$output->writeln('- Pause is over, checking results for ' . $token);
|
||||
//
|
||||
// $output->writeln('- Async request is sent, now waiting ' . $this->delay . ' seconds');
|
||||
// sleep($this->delay);
|
||||
// $output->writeln('- Pause is over, checking results for ' . $token);
|
||||
//
|
||||
// $wrappers = $this->gsUpstreamService->getEventsByToken($token);
|
||||
//
|
||||
// $result = [];
|
||||
// $instances = array_merge($this->globalScaleService->getInstances(true));
|
||||
// foreach ($wrappers as $wrapper) {
|
||||
// $result[$wrapper->getInstance()] = $wrapper->getEvent();
|
||||
// }
|
||||
//
|
||||
// $localLooksGood = false;
|
||||
// foreach ($instances as $instance) {
|
||||
// $output->write($instance . ' ');
|
||||
// if (array_key_exists($instance, $result)
|
||||
// && $result[$instance]->getResult()
|
||||
// ->gInt('status') === 1) {
|
||||
// $output->writeln('<info>ok</info>');
|
||||
// if ($this->configService->isLocalInstance($instance)) {
|
||||
// $localLooksGood = true;
|
||||
// }
|
||||
// } else {
|
||||
// $output->writeln('<error>fail</error>');
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// $this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
|
||||
//
|
||||
// if ($localLooksGood) {
|
||||
// $this->saveUrl($input, $output, $input->getOption('url'));
|
||||
// }
|
||||
|
||||
$wrappers = $this->gsUpstreamService->getEventsByToken($token);
|
||||
|
||||
$result = [];
|
||||
$instances = array_merge($this->globalScaleService->getInstances(true));
|
||||
foreach ($wrappers as $wrapper) {
|
||||
$result[$wrapper->getInstance()] = $wrapper->getEvent();
|
||||
if ($address === 'http://orange.local') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$localLooksGood = false;
|
||||
foreach ($instances as $instance) {
|
||||
$output->write($instance . ' ');
|
||||
if (array_key_exists($instance, $result)
|
||||
&& $result[$instance]->getResult()
|
||||
->gInt('status') === 1) {
|
||||
$output->writeln('<info>ok</info>');
|
||||
if ($this->configService->isLocalInstance($instance)) {
|
||||
$localLooksGood = true;
|
||||
}
|
||||
} else {
|
||||
$output->writeln('<error>fail</error>');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @param string $test
|
||||
*/
|
||||
private function checkInternal(InputInterface $input, OutputInterface $output, string $test): void {
|
||||
$output->writeln(
|
||||
'. The <info>internal</info> setting is mandatory only if you are willing to use Circles in a GlobalScale setup on a local network.'
|
||||
);
|
||||
$output->writeln(
|
||||
'. The address you need to define here is the local address of your Nextcloud, reachable by all other instances of our GlobalScale.'
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @param string $test
|
||||
*/
|
||||
private function checkFrontal(InputInterface $input, OutputInterface $output, string $test): void {
|
||||
$output->writeln('. The <info>frontal</info> setting is optional.');
|
||||
$output->writeln(
|
||||
'. The purpose of this address is for your Federated Circle to reach other instances of Nextcloud over the Internet.'
|
||||
);
|
||||
$output->writeln(
|
||||
'. The address you need to define here must be reachable from the Internet.'
|
||||
);
|
||||
$output->writeln(
|
||||
'. By default, this feature is disabled (and is considered ALPHA in Nextcloud 22).'
|
||||
);
|
||||
|
||||
$question = new ConfirmationQuestion(
|
||||
'- <comment>Do you want to enable this feature ?</comment> (y/N) ', false, '/^(y|Y)/i'
|
||||
);
|
||||
|
||||
$helper = $this->getHelper('question');
|
||||
if (!$helper->ask($input, $output, $question)) {
|
||||
$output->writeln('skipping.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
while (true) {
|
||||
|
||||
$question = new Question(
|
||||
'<info>Please write down a new frontal address to test</info>: ', ''
|
||||
);
|
||||
|
||||
$frontal = $helper->ask($input, $output, $question);
|
||||
if (is_null($frontal) || $frontal === '') {
|
||||
$output->writeln('skipping.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
[$scheme, $cloudId] = $this->parseAddress($frontal);
|
||||
} catch (Exception $e) {
|
||||
$output->writeln('<error>format must be http[s]://domain.name[:post]</error>');
|
||||
continue;
|
||||
}
|
||||
|
||||
$frontal = $scheme . '://' . $cloudId;
|
||||
break;
|
||||
}
|
||||
|
||||
$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
|
||||
$question = new ConfirmationQuestion(
|
||||
'<comment>Do you want to check the validity of this frontal address?</comment> (y/N) ', false,
|
||||
'/^(y|Y)/i'
|
||||
);
|
||||
|
||||
if ($localLooksGood) {
|
||||
$this->saveUrl($input, $output, $input->getOption('url'));
|
||||
if ($helper->ask($input, $output, $question)) {
|
||||
$output->writeln(
|
||||
'You will need to run this <info>curl</info> command from a remote terminal and paste its result: '
|
||||
);
|
||||
$output->writeln(
|
||||
' curl ' . $frontal . '/.well-known/webfinger?resource=http://nextcloud.com/'
|
||||
);
|
||||
|
||||
$question = new Question('result: ', '');
|
||||
$pasteWebfinger = $helper->ask($input, $output, $question);
|
||||
|
||||
echo '__ ' . $pasteWebfinger;
|
||||
|
||||
$output->writeln('TESTING !!');
|
||||
$output->writeln('TESTING !!');
|
||||
$output->writeln('TESTING !!');
|
||||
}
|
||||
|
||||
return 0;
|
||||
$output->writeln('saved');
|
||||
|
||||
|
||||
// $output->writeln('. 1) The automatic way, requiring a valid remote instance of Nextcloud.');
|
||||
// $output->writeln(
|
||||
// '. 2) The manual way, using the <comment>curl</comment> command from a remote terminal.'
|
||||
// );
|
||||
// $output->writeln(
|
||||
// '. If you prefer the automatic way, you will need to enter the valid remote instance of Nextcloud you want to use.'
|
||||
// );
|
||||
// $output->writeln('. If you want the manual way, just enter an empty field.');
|
||||
// $output->writeln('');
|
||||
// $output->writeln(
|
||||
// '. If you do not known a valid remote instance of Nextcloud, you can use <comment>\'https://circles.artificial-owl.com/\'</comment>'
|
||||
// );
|
||||
// $output->writeln(
|
||||
// '. Please note that no critical information will be shared during the process, and any data (ie. public key and address)'
|
||||
// );
|
||||
// $output->writeln(
|
||||
// ' generated during the process will be wiped of the remote instance after few minutes.'
|
||||
// );
|
||||
// $output->writeln('');
|
||||
|
||||
// $question = new Question(
|
||||
// '- <comment>Which remote instance of Nextcloud do you want to use in order to test your setup:</comment> (empty to bypass this step): '
|
||||
// );
|
||||
// $helper = $this->getHelper('question');
|
||||
// $remote = $helper->ask($input, $output, $question);
|
||||
// if (is_null($frontal) || $frontal === '') {
|
||||
// $output->writeln('skipping.');
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// $output->writeln('. The confirmation step is optional and can be done in 2 different ways:');
|
||||
//
|
||||
//
|
||||
// $output->writeln('');
|
||||
// $question = new Question(
|
||||
// '- <comment>Enter the <info>frontal</info> address you want to be used to identify your instance of Nextcloud over the Internet</comment>: '
|
||||
// );
|
||||
// $helper = $this->getHelper('question');
|
||||
// $frontal = $helper->ask($input, $output, $question);
|
||||
|
||||
// while (true) {
|
||||
// $question = new Question(
|
||||
// '<info>Please write down a new frontal address to test</info>: ', ''
|
||||
// );
|
||||
//
|
||||
// $frontal = $helper->ask($input, $output, $question);
|
||||
// if (is_null($frontal) || $frontal === '') {
|
||||
// $output->writeln('skipping.');
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// [$scheme, $cloudId] = $this->parseAddress($test);
|
||||
// } catch (Exception $e) {
|
||||
// $output->writeln('<error>format must be http[s]://domain.name[:post]</error>');
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// $frontal = $scheme . '://' . $cloudId;
|
||||
//
|
||||
// $output->write('* testing address: ' . $frontal . ' ');
|
||||
//
|
||||
// if ($remote === '') {
|
||||
// $output->writeln('remote empty, please run this curl request and paste the result in here');
|
||||
// $output->writeln(
|
||||
// ' curl ' . $frontal . '/.well-known/webfinger?resource=http://nextcloud.com/'
|
||||
// );
|
||||
// $question = new Question('result: ', '');
|
||||
//
|
||||
// $resultWebfinger = $helper->ask($input, $output, $question);
|
||||
//
|
||||
// } else {
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// if ($remote === '') {
|
||||
// $output->writeln('');
|
||||
// }
|
||||
|
||||
// $output->writeln('');
|
||||
// $output->writeln(
|
||||
// '. By default, this feature is disabled. You will need to setup a valid entry to enabled it.'
|
||||
// );
|
||||
|
||||
// $output->writeln('');
|
||||
// $output->write('* testing current address: ' . $this->configService->getLoopbackPath() . ' ');
|
||||
|
||||
|
||||
// $this->configService->getAppValue(ConfigService::CHECK_FRONTAL_USING);
|
||||
}
|
||||
|
||||
|
||||
|
@ -198,12 +627,17 @@ class CirclesCheck extends Base {
|
|||
* @return bool
|
||||
* @throws RequestNetworkException
|
||||
*/
|
||||
private function testRequest(OutputInterface $o, string $type, string $route, array $args = []): bool {
|
||||
private function testRequest(
|
||||
OutputInterface $output,
|
||||
string $type,
|
||||
string $route,
|
||||
array $args = []
|
||||
): bool {
|
||||
$request = new NC22Request('', Request::type($type));
|
||||
$this->configService->configureRequest($request, $route, $args);
|
||||
$this->configService->configureLoopbackRequest($request, $route, $args);
|
||||
$request->setFollowLocation(false);
|
||||
|
||||
$o->write('- ' . $type . ' request on ' . $request->getCompleteUrl() . ': ');
|
||||
$output->write('- ' . $type . ' request on ' . $request->getCompleteUrl() . ': ');
|
||||
$this->doRequest($request);
|
||||
|
||||
$color = 'error';
|
||||
|
@ -212,7 +646,7 @@ class CirclesCheck extends Base {
|
|||
$color = 'info';
|
||||
}
|
||||
|
||||
$o->writeln('<' . $color . '>' . $result->getStatusCode() . '</' . $color . '>');
|
||||
$output->writeln('<' . $color . '>' . $result->getStatusCode() . '</' . $color . '>');
|
||||
|
||||
if ($result->getStatusCode() === 200) {
|
||||
return true;
|
||||
|
@ -256,5 +690,28 @@ class CirclesCheck extends Base {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $test
|
||||
*
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function parseAddress(string $test): array {
|
||||
$scheme = parse_url($test, PHP_URL_SCHEME);
|
||||
$cloudId = parse_url($test, PHP_URL_HOST);
|
||||
$cloudIdPort = parse_url($test, PHP_URL_PORT);
|
||||
|
||||
if (is_null($scheme) || is_null($cloudId)) {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
if (!is_null($cloudIdPort)) {
|
||||
$cloudId = $cloudId . ':' . $cloudIdPort;
|
||||
}
|
||||
|
||||
return [$scheme, $cloudId];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -199,7 +199,6 @@ class CirclesList extends Base {
|
|||
);
|
||||
$table->render();
|
||||
|
||||
$local = $this->configService->getFrontalInstance();
|
||||
$display = ($this->input->getOption('def') ? Circle::FLAGS_LONG : Circle::FLAGS_SHORT);
|
||||
foreach ($circles as $circle) {
|
||||
$owner = $circle->getOwner();
|
||||
|
@ -210,7 +209,7 @@ class CirclesList extends Base {
|
|||
json_encode(Circle::getCircleFlags($circle, $display)),
|
||||
Circle::$DEF_SOURCE[$circle->getSource()],
|
||||
$owner->getUserId(),
|
||||
($owner->getInstance() === $local) ? '' : $owner->getInstance(),
|
||||
$this->configService->displayInstance($owner->getInstance()),
|
||||
$this->getInt('members_limit', $circle->getSettings(), -1),
|
||||
substr(str_replace("\n", ' ', $circle->getDescription()), 0, 30)
|
||||
]
|
||||
|
|
|
@ -377,7 +377,6 @@ class CirclesMemberships extends Base {
|
|||
$table->render();
|
||||
|
||||
$count = 0;
|
||||
$local = $this->configService->getFrontalInstance();
|
||||
foreach ($circles as $circle) {
|
||||
$owner = $circle->getOwner();
|
||||
|
||||
|
@ -390,7 +389,7 @@ class CirclesMemberships extends Base {
|
|||
$circle->getDisplayName(),
|
||||
($circle->getSource() > 0) ? Circle::$DEF_SOURCE[$circle->getSource()] : '',
|
||||
$owner->getUserId(),
|
||||
($owner->getInstance() === $local) ? '' : $owner->getInstance(),
|
||||
$this->configService->displayInstance($owner->getInstance()),
|
||||
$updated,
|
||||
sizeof($federatedUser->getMemberships())
|
||||
]
|
||||
|
|
|
@ -42,7 +42,6 @@ use Exception;
|
|||
use OC\Core\Command\Base;
|
||||
use OCA\Circles\AppInfo\Application;
|
||||
use OCA\Circles\Db\RemoteRequest;
|
||||
use OCA\Circles\Exceptions\GSStatusException;
|
||||
use OCA\Circles\Exceptions\RemoteNotFoundException;
|
||||
use OCA\Circles\Exceptions\RemoteUidException;
|
||||
use OCA\Circles\Model\Federated\RemoteInstance;
|
||||
|
@ -125,6 +124,10 @@ class CirclesRemote extends Base {
|
|||
->addOption(
|
||||
'type', '', InputOption::VALUE_REQUIRED, 'set type of remote', RemoteInstance::TYPE_UNKNOWN
|
||||
)
|
||||
->addOption(
|
||||
'iface', '', InputOption::VALUE_REQUIRED, 'set interface to use to contact remote',
|
||||
RemoteInstance::$LIST_IFACE[RemoteInstance::IFACE_FRONTAL]
|
||||
)
|
||||
->addOption('yes', '', InputOption::VALUE_NONE, 'silently add the remote instance')
|
||||
->addOption('all', '', InputOption::VALUE_NONE, 'display all information');
|
||||
}
|
||||
|
@ -160,6 +163,7 @@ class CirclesRemote extends Base {
|
|||
*/
|
||||
private function requestInstance(string $host): void {
|
||||
$remoteType = $this->getRemoteType();
|
||||
$remoteIface = $this->getRemoteInterface();
|
||||
|
||||
$webfinger = $this->getWebfinger($host, Application::APP_SUBJECT);
|
||||
if ($this->input->getOption('all')) {
|
||||
|
@ -269,8 +273,9 @@ class CirclesRemote extends Base {
|
|||
}
|
||||
|
||||
if ($remoteSignatory->getUid() !== $localSignatory->getUid()) {
|
||||
$remoteSignatory->setInstance($host);
|
||||
$remoteSignatory->setType($remoteType);
|
||||
$remoteSignatory->setInstance($host)
|
||||
->setType($remoteType)
|
||||
->setInterface($remoteIface);
|
||||
|
||||
try {
|
||||
$stored = new RemoteInstance();
|
||||
|
@ -330,8 +335,9 @@ class CirclesRemote extends Base {
|
|||
'The remote instance <info>' . $remoteSignatory->getInstance() . '</info> looks good.'
|
||||
);
|
||||
$question = new ConfirmationQuestion(
|
||||
'Would you like to identify this remote instance as \'' . $remoteSignatory->getType()
|
||||
. '\' ? (y/N) ',
|
||||
'Would you like to identify this remote instance as \'<comment>' . $remoteSignatory->getType()
|
||||
. '</comment>\' using interface \'<comment>' . RemoteInstance::$LIST_IFACE[$remoteSignatory->getInterface()]
|
||||
. '</comment>\' ? (y/N) ',
|
||||
false,
|
||||
'/^(y|Y)/i'
|
||||
);
|
||||
|
@ -407,14 +413,13 @@ class CirclesRemote extends Base {
|
|||
|
||||
/**
|
||||
*
|
||||
* @throws GSStatusException
|
||||
*/
|
||||
private function verifyGSInstances(): void {
|
||||
$instances = $this->globalScaleService->getGlobalScaleInstances();
|
||||
$known = array_map(
|
||||
function(RemoteInstance $instance): string {
|
||||
return $instance->getInstance();
|
||||
}, $this->remoteRequest->getFromType(RemoteInstance::TYPE_GLOBAL_SCALE)
|
||||
}, $this->remoteRequest->getFromType(RemoteInstance::TYPE_GLOBALSCALE)
|
||||
);
|
||||
|
||||
$missing = array_diff($instances, $known);
|
||||
|
@ -433,7 +438,12 @@ class CirclesRemote extends Base {
|
|||
}
|
||||
$this->output->write('Adding <comment>' . $instance . '</comment>: ');
|
||||
try {
|
||||
$this->remoteStreamService->addRemoteInstance($instance, RemoteInstance::TYPE_GLOBAL_SCALE, true);
|
||||
$this->remoteStreamService->addRemoteInstance(
|
||||
$instance,
|
||||
RemoteInstance::TYPE_GLOBALSCALE,
|
||||
RemoteInstance::IFACE_INTERNAL,
|
||||
true
|
||||
);
|
||||
$this->output->writeln('<info>ok</info>');
|
||||
} catch (Exception $e) {
|
||||
$msg = ($e->getMessage() === '') ? '' : ' (' . $e->getMessage() . ')';
|
||||
|
@ -448,7 +458,7 @@ class CirclesRemote extends Base {
|
|||
$output = new ConsoleOutput();
|
||||
$output = $output->section();
|
||||
$table = new Table($output);
|
||||
$table->setHeaders(['instance', 'type', 'UID', 'Authed']);
|
||||
$table->setHeaders(['instance', 'type', 'iface', 'UID', 'Authed']);
|
||||
$table->render();
|
||||
|
||||
foreach ($instances as $instance) {
|
||||
|
@ -467,6 +477,7 @@ class CirclesRemote extends Base {
|
|||
[
|
||||
$instance->getInstance(),
|
||||
$instance->getType(),
|
||||
RemoteInstance::$LIST_IFACE[$instance->getInterface()],
|
||||
$instance->getUid(),
|
||||
$currentUid
|
||||
]
|
||||
|
@ -488,5 +499,18 @@ class CirclesRemote extends Base {
|
|||
throw new Exception('Unknown type: ' . implode(', ', RemoteInstance::$LIST_TYPE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getRemoteInterface(): int {
|
||||
foreach (RemoteInstance::$LIST_IFACE as $iface => $def) {
|
||||
if (strtolower($this->input->getOption('iface')) === strtolower($def)) {
|
||||
return $iface;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception('Unknown interface: ' . implode(', ', RemoteInstance::$LIST_IFACE));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -229,7 +229,6 @@ class MembersList extends Base {
|
|||
);
|
||||
$table->render();
|
||||
|
||||
$local = $this->configService->getFrontalInstance();
|
||||
foreach ($members as $member) {
|
||||
if ($member->getCircleId() === $circleId) {
|
||||
$level = $member->getLevel();
|
||||
|
@ -247,7 +246,7 @@ class MembersList extends Base {
|
|||
$member->hasBasedOn() ? Circle::$DEF_SOURCE[$member->getBasedOn()->getSource()] : '',
|
||||
($this->input->getOption('display-name')) ?
|
||||
$member->getBasedOn()->getDisplayName() : $member->getUserId(),
|
||||
($member->getInstance() === $local) ? '' : $member->getInstance(),
|
||||
$this->configService->displayInstance($member->getInstance()),
|
||||
($level > 0) ? Member::$DEF_LEVEL[$level] :
|
||||
'(' . strtolower($member->getStatus()) . ')'
|
||||
]
|
||||
|
|
|
@ -112,14 +112,13 @@ class MembersSearch extends Base {
|
|||
$table->setHeaders(['SingleId', 'UserId', 'UserType', 'Instance']);
|
||||
$table->render();
|
||||
|
||||
$local = $this->configService->getFrontalInstance();
|
||||
foreach ($result as $entry) {
|
||||
$table->appendRow(
|
||||
[
|
||||
$entry->getSingleId(),
|
||||
$entry->getUserId(),
|
||||
Member::$TYPE[$entry->getUserType()],
|
||||
($entry->getInstance() === $local) ? '' : $entry->getInstance(),
|
||||
$this->configService->displayInstance($entry->getInstance())
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ use OCA\Circles\Db\CircleRequest;
|
|||
use OCA\Circles\Exceptions\FederatedItemException;
|
||||
use OCA\Circles\Exceptions\FederatedUserException;
|
||||
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
|
||||
use OCA\Circles\Exceptions\RemoteInstanceException;
|
||||
use OCA\Circles\Model\Circle;
|
||||
use OCA\Circles\Model\Federated\FederatedEvent;
|
||||
use OCA\Circles\Model\Federated\RemoteInstance;
|
||||
|
@ -139,6 +140,7 @@ class RemoteController extends Controller {
|
|||
* @return DataResponse
|
||||
* @throws NotLoggedInException
|
||||
* @throws SignatoryException
|
||||
* @throws RemoteInstanceException
|
||||
*/
|
||||
public function appService(): DataResponse {
|
||||
try {
|
||||
|
@ -147,9 +149,13 @@ class RemoteController extends Controller {
|
|||
return new DataResponse();
|
||||
}
|
||||
|
||||
$confirm = $this->request->getParam('auth', '');
|
||||
$signatory = $this->remoteStreamService->getAppSignatory(
|
||||
$this->configService->isLocalInstance($this->request->getServerHost(), true),
|
||||
false,
|
||||
$this->request->getParam('auth', '')
|
||||
);
|
||||
|
||||
return new DataResponse($this->remoteStreamService->getAppSignatory(false, $confirm));
|
||||
return new DataResponse($signatory);
|
||||
}
|
||||
|
||||
|
||||
|
@ -209,8 +215,9 @@ class RemoteController extends Controller {
|
|||
*/
|
||||
public function test(): DataResponse {
|
||||
try {
|
||||
$test =
|
||||
$this->remoteStreamService->incomingSignedRequest($this->configService->getFrontalInstance());
|
||||
$test = $this->remoteStreamService->incomingSignedRequest(
|
||||
$this->configService->getValidLocalInstances()
|
||||
);
|
||||
|
||||
return new DataResponse($test->jsonSerialize());
|
||||
} catch (Exception $e) {
|
||||
|
@ -345,7 +352,7 @@ class RemoteController extends Controller {
|
|||
*/
|
||||
private function extractEventFromRequest(): FederatedEvent {
|
||||
$signed =
|
||||
$this->remoteStreamService->incomingSignedRequest($this->configService->getFrontalInstance());
|
||||
$this->remoteStreamService->incomingSignedRequest($this->configService->getValidLocalInstances());
|
||||
$this->confirmRemoteInstance($signed);
|
||||
|
||||
$event = new FederatedEvent();
|
||||
|
@ -367,7 +374,7 @@ class RemoteController extends Controller {
|
|||
*/
|
||||
private function extractDataFromFromRequest(): SimpleDataStore {
|
||||
$signed =
|
||||
$this->remoteStreamService->incomingSignedRequest($this->configService->getFrontalInstance());
|
||||
$this->remoteStreamService->incomingSignedRequest($this->configService->getValidLocalInstances());
|
||||
$remoteInstance = $this->confirmRemoteInstance($signed);
|
||||
|
||||
// There should be no need to confirm the need or the origin of the initiator as $remoteInstance
|
||||
|
|
|
@ -513,7 +513,7 @@ class CoreQueryBuilder extends NC22ExtendedQueryBuilder {
|
|||
$expr = $this->expr();
|
||||
$orX = $expr->orX();
|
||||
$orX->add(
|
||||
$expr->eq($aliasRemote . '.type', $this->createNamedParameter(RemoteInstance::TYPE_GLOBAL_SCALE))
|
||||
$expr->eq($aliasRemote . '.type', $this->createNamedParameter(RemoteInstance::TYPE_GLOBALSCALE))
|
||||
);
|
||||
|
||||
$orExtOrPassive = $expr->orX();
|
||||
|
|
|
@ -114,6 +114,7 @@ class CoreRequestBuilder {
|
|||
self::TABLE_REMOTE => [
|
||||
'id',
|
||||
'type',
|
||||
'interface',
|
||||
'uid',
|
||||
'instance',
|
||||
'href',
|
||||
|
|
|
@ -61,6 +61,7 @@ class RemoteRequest extends RemoteRequestBuilder {
|
|||
->setValue('instance', $qb->createNamedParameter($remote->getInstance()))
|
||||
->setValue('href', $qb->createNamedParameter($remote->getId()))
|
||||
->setValue('type', $qb->createNamedParameter($remote->getType()))
|
||||
->setValue('interface', $qb->createNamedParameter($remote->getInterface()))
|
||||
->setValue('item', $qb->createNamedParameter(json_encode($remote->getOrigData())));
|
||||
|
||||
$qb->execute();
|
||||
|
@ -171,7 +172,8 @@ class RemoteRequest extends RemoteRequestBuilder {
|
|||
$expr = $qb->expr();
|
||||
$orX = $expr->orX();
|
||||
|
||||
$orX->add($qb->exprLimitToDBField('type', RemoteInstance::TYPE_GLOBAL_SCALE, true, false));
|
||||
$orX->add($qb->exprLimitToDBField('type', RemoteInstance::TYPE_GLOBALSCALE, true, false));
|
||||
|
||||
if ($circle->isConfig(Circle::CFG_FEDERATED) || $broadcastAsFederated) {
|
||||
|
||||
// get all TRUSTED
|
||||
|
|
82
lib/FederatedItems/LoopbackTest.php
Normal file
82
lib/FederatedItems/LoopbackTest.php
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?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\FederatedItems;
|
||||
|
||||
|
||||
use daita\MySmallPhpTools\Model\SimpleDataStore;
|
||||
use OCA\Circles\IFederatedItem;
|
||||
use OCA\Circles\IFederatedItemLoopbackTest;
|
||||
use OCA\Circles\Model\Federated\FederatedEvent;
|
||||
|
||||
|
||||
/**
|
||||
* Class LoopbackTest
|
||||
*
|
||||
* @package OCA\Circles\FederatedItems
|
||||
*/
|
||||
class LoopbackTest implements
|
||||
IFederatedItem,
|
||||
IFederatedItemLoopbackTest {
|
||||
|
||||
|
||||
/**
|
||||
* LoopbackTest constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param FederatedEvent $event
|
||||
*/
|
||||
public function verify(FederatedEvent $event): void {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param FederatedEvent $event
|
||||
*/
|
||||
public function manage(FederatedEvent $event): void {
|
||||
$event->setResult(new SimpleDataStore(['status' => 1]));
|
||||
// $event->setOutcome($new->jsonSerialize());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param FederatedEvent $event
|
||||
* @param array $results
|
||||
*/
|
||||
public function result(FederatedEvent $event, array $results): void {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -348,7 +348,7 @@ class SingleMemberAdd implements
|
|||
|
||||
if (!$circle->isConfig(Circle::CFG_FEDERATED)) {
|
||||
$remoteInstance = $this->remoteStreamService->getCachedRemoteInstance($member->getInstance());
|
||||
if ($remoteInstance->getType() !== RemoteInstance::TYPE_GLOBAL_SCALE) {
|
||||
if ($remoteInstance->getType() !== RemoteInstance::TYPE_GLOBALSCALE) {
|
||||
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[127], 127);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ use daita\MySmallPhpTools\Exceptions\SignatureException;
|
|||
use daita\MySmallPhpTools\Traits\TArrayTools;
|
||||
use OC\URLGenerator;
|
||||
use OCA\Circles\AppInfo\Application;
|
||||
use OCA\Circles\Exceptions\RemoteInstanceException;
|
||||
use OCA\Circles\Service\ConfigService;
|
||||
use OCA\Circles\Service\RemoteStreamService;
|
||||
use OCP\Http\WellKnown\IHandler;
|
||||
|
@ -96,7 +97,8 @@ class WebfingerHandler implements IHandler {
|
|||
return $response;
|
||||
}
|
||||
|
||||
$subject = $this->get('resource', $context->getHttpRequest()->getParams());
|
||||
$request = $context->getHttpRequest();
|
||||
$subject = $this->get('resource', $request->getParams());
|
||||
if ($subject !== Application::APP_SUBJECT) {
|
||||
return $response;
|
||||
}
|
||||
|
@ -106,12 +108,14 @@ class WebfingerHandler implements IHandler {
|
|||
}
|
||||
|
||||
try {
|
||||
$this->remoteStreamService->getAppSignatory();
|
||||
} catch (SignatoryException $e) {
|
||||
$this->remoteStreamService->getAppSignatory(
|
||||
$this->configService->isLocalInstance($request->getServerHost(), true)
|
||||
);
|
||||
} catch (SignatoryException | RemoteInstanceException $e) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$href = $this->configService->getFrontalPath();
|
||||
$href = $this->configService->getInstancePathBasedOnHost($request->getServerHost());
|
||||
$info = [
|
||||
'app' => Application::APP_ID,
|
||||
'name' => Application::APP_NAME,
|
||||
|
|
43
lib/IFederatedItemLoopbackTest.php
Normal file
43
lib/IFederatedItemLoopbackTest.php
Normal 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@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;
|
||||
|
||||
|
||||
/**
|
||||
* Interface IFederatedItemLoopbackTest
|
||||
*
|
||||
* @package OCA\Circles
|
||||
*/
|
||||
interface IFederatedItemLoopbackTest {
|
||||
|
||||
}
|
||||
|
|
@ -91,7 +91,7 @@ class AddingMember implements IEventListener {
|
|||
$circle = $event->getCircle();
|
||||
$files = $this->shareWrapperService->getSharesToCircle($circle->getSingleId());
|
||||
|
||||
$event->getFederatedEvent()->addResult('files', new SimpleDataStore($files));
|
||||
$event->getFederatedEvent()->addResult('files', new SimpleDataStore($files));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -150,6 +150,13 @@ class Version0021Date20210105123456 extends SimpleMigrationStep {
|
|||
'default' => 'Unknown'
|
||||
]
|
||||
);
|
||||
$table->addColumn(
|
||||
'interface', 'integer', [
|
||||
'notnull' => true,
|
||||
'length' => 1,
|
||||
'default' => 0
|
||||
]
|
||||
);
|
||||
$table->addColumn(
|
||||
'uid', 'string', [
|
||||
'notnull' => false,
|
||||
|
|
|
@ -51,10 +51,11 @@ class FederatedEvent implements JsonSerializable {
|
|||
const SEVERITY_LOW = 1;
|
||||
const SEVERITY_HIGH = 3;
|
||||
|
||||
const BYPASS_LOCALCIRCLECHECK = 1;
|
||||
const BYPASS_LOCALMEMBERCHECK = 2;
|
||||
const BYPASS_INITIATORCHECK = 4;
|
||||
const BYPASS_INITIATORMEMBERSHIP = 8;
|
||||
const BYPASS_CIRCLE = 1;
|
||||
const BYPASS_LOCALCIRCLECHECK = 2;
|
||||
const BYPASS_LOCALMEMBERCHECK = 4;
|
||||
const BYPASS_INITIATORCHECK = 8;
|
||||
const BYPASS_INITIATORMEMBERSHIP = 16;
|
||||
|
||||
use TArrayTools;
|
||||
|
||||
|
|
|
@ -54,14 +54,22 @@ class RemoteInstance extends NC22Signatory implements INC22QueryRow, JsonSeriali
|
|||
const TYPE_PASSIVE = 'Passive'; // Minimum information about Federated Circles are broadcasted if a member belongs to the circle.
|
||||
const TYPE_EXTERNAL = 'External'; // info about Federated Circles and their members are broadcasted if a member belongs to the circle.
|
||||
const TYPE_TRUSTED = 'Trusted'; // everything about Federated Circles are broadcasted.
|
||||
const TYPE_GLOBAL_SCALE = 'GlobalScale'; // every Circle is broadcasted,
|
||||
const TYPE_GLOBALSCALE = 'GlobalScale'; // every Circle is broadcasted,
|
||||
|
||||
const IFACE_INTERNAL = 0;
|
||||
const IFACE_FRONTAL = 1;
|
||||
|
||||
public static $LIST_TYPE = [
|
||||
self::TYPE_UNKNOWN,
|
||||
self::TYPE_PASSIVE,
|
||||
self::TYPE_EXTERNAL,
|
||||
self::TYPE_TRUSTED,
|
||||
self::TYPE_GLOBAL_SCALE
|
||||
self::TYPE_GLOBALSCALE
|
||||
];
|
||||
|
||||
public static $LIST_IFACE = [
|
||||
self::IFACE_INTERNAL => 'internal',
|
||||
self::IFACE_FRONTAL => 'frontal'
|
||||
];
|
||||
|
||||
const TEST = 'test';
|
||||
|
@ -79,6 +87,9 @@ class RemoteInstance extends NC22Signatory implements INC22QueryRow, JsonSeriali
|
|||
/** @var string */
|
||||
private $type = self::TYPE_UNKNOWN;
|
||||
|
||||
/** @var int */
|
||||
private $interface = 0;
|
||||
|
||||
/** @var string */
|
||||
private $test = '';
|
||||
|
||||
|
@ -151,6 +162,25 @@ class RemoteInstance extends NC22Signatory implements INC22QueryRow, JsonSeriali
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $interface
|
||||
*
|
||||
* @return RemoteInstance
|
||||
*/
|
||||
public function setInterface(int $interface): self {
|
||||
$this->interface = $interface;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getInterface(): int {
|
||||
return $this->interface;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
@ -455,6 +485,7 @@ class RemoteInstance extends NC22Signatory implements INC22QueryRow, JsonSeriali
|
|||
$this->import($this->getArray($prefix . 'item', $data));
|
||||
$this->setOrigData($this->getArray($prefix . 'item', $data));
|
||||
$this->setType($this->get($prefix . 'type', $data));
|
||||
$this->setInterface($this->getInt($prefix . 'interface', $data));
|
||||
$this->setInstance($this->get($prefix . 'instance', $data));
|
||||
$this->setId($this->get($prefix . 'href', $data));
|
||||
|
||||
|
|
|
@ -393,7 +393,7 @@ class ModelManager {
|
|||
* @return string
|
||||
*/
|
||||
public function getLocalInstance(): string {
|
||||
return $this->configService->getFrontalInstance();
|
||||
return $this->configService->getLocalInstance();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
|
|||
use daita\MySmallPhpTools\Traits\TStringTools;
|
||||
use OCA\Circles\AppInfo\Application;
|
||||
use OCA\Circles\Exceptions\GSStatusException;
|
||||
use OCA\Circles\Exceptions\RemoteInstanceException;
|
||||
use OCA\Circles\Model\Circle;
|
||||
use OCA\Circles\Model\DeprecatedCircle;
|
||||
use OCA\Circles\Model\Member;
|
||||
|
@ -50,19 +51,15 @@ class ConfigService {
|
|||
const INTERNAL_CLOUD_SCHEME = 'internal_cloud_scheme';
|
||||
const LOOPBACK_CLOUD_ID = 'loopback_cloud_id';
|
||||
const LOOPBACK_CLOUD_SCHEME = 'loopback_cloud_scheme';
|
||||
const CHECK_FRONTAL_USING = 'check_frontal_using';
|
||||
const CHECK_INTERNAL_USING = 'check_internal_using';
|
||||
const SELF_SIGNED_CERT = 'self_signed_cert';
|
||||
const MEMBERS_LIMIT = 'members_limit';
|
||||
const ACTIVITY_ON_NEW_CIRCLE = 'creation_activity';
|
||||
const MIGRATION_22 = 'migration_22';
|
||||
|
||||
// deprecated
|
||||
const CIRCLES_CONTACT_BACKEND = 'contact_backend';
|
||||
const CIRCLES_ACCOUNTS_ONLY = 'accounts_only'; // only UserType=1
|
||||
const CIRCLES_SEARCH_FROM_COLLABORATOR = 'search_from_collaborator';
|
||||
|
||||
|
||||
const FORCE_NC_BASE = 'force_nc_base';
|
||||
const TEST_NC_BASE = 'test_nc_base';
|
||||
const LOOPBACK_TMP_ID = 'loopback_tmp_id';
|
||||
const LOOPBACK_TMP_SCHEME = 'loopback_tmp_scheme';
|
||||
|
||||
const GS_MODE = 'mode';
|
||||
const GS_KEY = 'key';
|
||||
|
@ -71,13 +68,28 @@ class ConfigService {
|
|||
const GS_LOOKUP_USERS = '/users';
|
||||
|
||||
|
||||
// deprecated -- removing in NC25
|
||||
const CIRCLES_CONTACT_BACKEND = 'contact_backend';
|
||||
const CIRCLES_ACCOUNTS_ONLY = 'accounts_only'; // only UserType=1
|
||||
const CIRCLES_SEARCH_FROM_COLLABORATOR = 'search_from_collaborator';
|
||||
|
||||
const FORCE_NC_BASE = 'force_nc_base';
|
||||
const TEST_NC_BASE = 'test_nc_base';
|
||||
|
||||
|
||||
|
||||
private $defaults = [
|
||||
self::FRONTAL_CLOUD_ID => '',
|
||||
self::FRONTAL_CLOUD_SCHEME => 'https',
|
||||
self::INTERNAL_CLOUD_ID => '',
|
||||
self::INTERNAL_CLOUD_SCHEME => 'https',
|
||||
self::LOOPBACK_CLOUD_ID => '',
|
||||
self::LOOPBACK_CLOUD_SCHEME => 'https',
|
||||
self::FRONTAL_CLOUD_ID => '',
|
||||
self::FRONTAL_CLOUD_SCHEME => 'https',
|
||||
self::INTERNAL_CLOUD_ID => '',
|
||||
self::INTERNAL_CLOUD_SCHEME => 'https',
|
||||
self::LOOPBACK_CLOUD_ID => '',
|
||||
self::LOOPBACK_CLOUD_SCHEME => 'https',
|
||||
self::CHECK_FRONTAL_USING => 'https://test.artificial-owl.com/',
|
||||
self::CHECK_INTERNAL_USING => '',
|
||||
self::LOOPBACK_TMP_ID => '',
|
||||
self::LOOPBACK_TMP_SCHEME => '',
|
||||
|
||||
self::SELF_SIGNED_CERT => '0',
|
||||
self::MEMBERS_LIMIT => '50',
|
||||
self::ACTIVITY_ON_NEW_CIRCLE => '1',
|
||||
|
@ -344,19 +356,97 @@ class ConfigService {
|
|||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLoopbackInstance(): string {
|
||||
$loopbackCloudId = $this->getAppValue(self::LOOPBACK_TMP_ID);
|
||||
if ($loopbackCloudId !== '') {
|
||||
return $loopbackCloudId;
|
||||
}
|
||||
|
||||
$loopbackCloudId = $this->getAppValue(self::LOOPBACK_CLOUD_ID);
|
||||
if ($loopbackCloudId !== '') {
|
||||
return $loopbackCloudId;
|
||||
}
|
||||
|
||||
$cliUrl = $this->getAppValue(self::FORCE_NC_BASE);
|
||||
if ($cliUrl === '') {
|
||||
$cliUrl = $this->config->getSystemValue('circles.force_nc_base', '');
|
||||
}
|
||||
|
||||
if ($cliUrl === '') {
|
||||
$cliUrl = $this->config->getSystemValue('overwrite.cli.url', '');
|
||||
}
|
||||
|
||||
$loopback = parse_url($cliUrl);
|
||||
if (!is_array($loopback) || !array_key_exists('host', $loopback)) {
|
||||
return $cliUrl;
|
||||
}
|
||||
|
||||
if (array_key_exists('port', $loopback)) {
|
||||
$loopbackCloudId = $loopback['host'] . ':' . $loopback['port'];
|
||||
} else {
|
||||
$loopbackCloudId = $loopback['host'];
|
||||
}
|
||||
|
||||
if (array_key_exists('scheme', $loopback)
|
||||
&& $this->getAppValue(self::LOOPBACK_TMP_SCHEME) !== $loopback['scheme']) {
|
||||
$this->setAppValue(self::LOOPBACK_TMP_SCHEME, $loopback['scheme']);
|
||||
}
|
||||
|
||||
return $loopbackCloudId;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns loopback address based on getLoopbackInstance and LOOPBACK_CLOUD_SCHEME
|
||||
* should be used to async process
|
||||
*
|
||||
* @param string $route
|
||||
* @param array $args
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLoopbackPath(string $route = '', array $args = []): string {
|
||||
$instance = $this->getLoopbackInstance();
|
||||
$scheme = $this->getAppValue(self::LOOPBACK_TMP_SCHEME);
|
||||
if ($scheme === '') {
|
||||
$scheme = $this->getAppValue(self::LOOPBACK_CLOUD_SCHEME);
|
||||
}
|
||||
|
||||
$base = $scheme . '://' . $instance;
|
||||
if ($route === '') {
|
||||
return $base;
|
||||
}
|
||||
|
||||
return $base . $this->urlGenerator->linkToRoute($route, $args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* - must be configured using INTERNAL_CLOUD_ID
|
||||
* - returns host+port, does not specify any protocol
|
||||
* - used mainly to assign instance and source to a request to local GlobalScale
|
||||
* - important only in GlobalScale environment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInternalInstance(): string {
|
||||
return $this->getAppValue(self::INTERNAL_CLOUD_ID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* - must be configured using FRONTAL_CLOUD_ID
|
||||
* - returns host+port, does not specify any protocol
|
||||
* - can be forced using FRONTAL_CLOUD_ID
|
||||
* - use 'overwrite.cli.url'
|
||||
* - can use the first entry from trusted_domains if FRONTAL_CLOUD_ID = 'use-trusted-domain'
|
||||
* - used mainly to assign instance and source to a request
|
||||
* - important only in remote environment; can be totally random in a jailed environment
|
||||
* - important only in remote environment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFrontalInstance(): string {
|
||||
$frontalCloudId = $this->getAppValue(self::FRONTAL_CLOUD_ID);
|
||||
|
||||
// using old settings - Deprecated in NC25
|
||||
// using old settings local_cloud_id from NC20, deprecated in NC25
|
||||
if ($frontalCloudId === '') {
|
||||
$frontalCloudId = $this->config->getAppValue(Application::APP_ID, 'local_cloud_id', '');
|
||||
if ($frontalCloudId !== '') {
|
||||
|
@ -364,30 +454,7 @@ class ConfigService {
|
|||
}
|
||||
}
|
||||
|
||||
if ($frontalCloudId === '') {
|
||||
$cliUrl = $this->config->getSystemValue('overwrite.cli.url', '');
|
||||
$frontal = parse_url($cliUrl);
|
||||
if (!is_array($frontal) || !array_key_exists('host', $frontal)) {
|
||||
if ($cliUrl !== '') {
|
||||
return $cliUrl;
|
||||
}
|
||||
|
||||
$randomCloudId = $this->uuid();
|
||||
$this->setAppValue(self::FRONTAL_CLOUD_ID, $randomCloudId);
|
||||
|
||||
return $randomCloudId;
|
||||
}
|
||||
|
||||
if (array_key_exists('port', $frontal)) {
|
||||
return $frontal['host'] . ':' . $frontal['port'];
|
||||
} else {
|
||||
return $frontal['host'];
|
||||
}
|
||||
} else if ($frontalCloudId === 'use-trusted-domain') {
|
||||
return $this->getTrustedDomains()[0];
|
||||
} else {
|
||||
return $frontalCloudId;
|
||||
}
|
||||
return $frontalCloudId;
|
||||
}
|
||||
|
||||
|
||||
|
@ -395,13 +462,25 @@ class ConfigService {
|
|||
* returns address based on FRONTAL_CLOUD_ID, FRONTAL_CLOUD_SCHEME and a routeName
|
||||
* perfect for urlId in ActivityPub env.
|
||||
*
|
||||
* @param bool $internal
|
||||
* @param string $route
|
||||
* @param array $args
|
||||
*
|
||||
* @return string
|
||||
* @throws RemoteInstanceException
|
||||
*/
|
||||
public function getFrontalPath(string $route = 'circles.Remote.appService', array $args = []): string {
|
||||
$base = $this->getAppValue(self::FRONTAL_CLOUD_SCHEME) . '://' . $this->getFrontalInstance();
|
||||
public function getInstancePath(
|
||||
bool $internal = false,
|
||||
string $route = 'circles.Remote.appService',
|
||||
array $args = []
|
||||
): string {
|
||||
if ($internal && $this->getInternalInstance() !== '') {
|
||||
$base = $this->getAppValue(self::INTERNAL_CLOUD_SCHEME) . '://' . $this->getInternalInstance();
|
||||
} else if ($this->getFrontalInstance() !== '') {
|
||||
$base = $this->getAppValue(self::FRONTAL_CLOUD_SCHEME) . '://' . $this->getFrontalInstance();
|
||||
} else {
|
||||
throw new RemoteInstanceException('not enabled');
|
||||
}
|
||||
|
||||
if ($route === '') {
|
||||
return $base;
|
||||
|
@ -410,91 +489,133 @@ class ConfigService {
|
|||
return $base . $this->urlGenerator->linkToRoute($route, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @param string $route
|
||||
* @param array $args
|
||||
*
|
||||
* @return string
|
||||
* @throws RemoteInstanceException
|
||||
*/
|
||||
public function getInstancePathBasedOnHost(
|
||||
string $host,
|
||||
string $route = 'circles.Remote.appService',
|
||||
array $args = []
|
||||
): string {
|
||||
return $this->getInstancePath(
|
||||
$this->isLocalInstance($host, true),
|
||||
$route,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $instance
|
||||
* @param bool $internal
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLocalInstance(string $instance): bool {
|
||||
public function isLocalInstance(string $instance, bool $internal = false): bool {
|
||||
if (strtolower($instance) === strtolower($this->getInternalInstance())
|
||||
&& $this->getInternalInstance() !== ''
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$internal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strtolower($instance) === strtolower($this->getFrontalInstance())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->getAppValue(self::FRONTAL_CLOUD_ID) === 'use-trusted-domain') {
|
||||
// if ($this->getAppValue(self::FRONTAL_CLOUD_ID) === 'use-trusted-domain') {
|
||||
return (in_array($instance, $this->getTrustedDomains()));
|
||||
// }
|
||||
|
||||
// return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $instance
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function displayInstance(string $instance): string {
|
||||
if ($this->isLocalInstance($instance)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return false;
|
||||
return $instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalInstance(): string {
|
||||
if ($this->getFrontalInstance() !== '') {
|
||||
return $this->getFrontalInstance();
|
||||
}
|
||||
|
||||
if ($this->getInternalInstance() !== '') {
|
||||
return $this->getInternalInstance();
|
||||
}
|
||||
|
||||
if ($this->getLoopbackInstance()) {
|
||||
return $this->getLoopbackInstance();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getValidLocalInstances(): array {
|
||||
return array_filter(
|
||||
array_unique(
|
||||
[
|
||||
$this->getFrontalInstance(),
|
||||
$this->getInternalInstance()
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* - Create route using getLoopbackAddress()
|
||||
* - perfect for loopback request.
|
||||
*
|
||||
* @param NC22Request $request
|
||||
* @param string $route
|
||||
* @param array $args
|
||||
*/
|
||||
public function configureLoopbackRequest(
|
||||
NC22Request $request,
|
||||
string $route = '',
|
||||
array $args = []
|
||||
): void {
|
||||
$this->configureRequest($request);
|
||||
$request->basedOnUrl($this->getLoopbackPath($route, $args));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param NC22Request $request
|
||||
* @param string $routeName
|
||||
* @param array $args
|
||||
*/
|
||||
public function configureRequest(NC22Request $request, string $routeName = '', array $args = []): void {
|
||||
$this->configureRequestAddress($request, $routeName, $args);
|
||||
|
||||
if ($this->getForcedNcBase() === '') {
|
||||
$request->setProtocols(['https', 'http']);
|
||||
}
|
||||
|
||||
public function configureRequest(NC22Request $request): void {
|
||||
$request->setVerifyPeer($this->getAppValue(ConfigService::SELF_SIGNED_CERT) !== '1');
|
||||
$request->setProtocols(['https', 'http']);
|
||||
$request->setHttpErrorsAllowed(true);
|
||||
$request->setLocalAddressAllowed(true);
|
||||
$request->setFollowLocation(true);
|
||||
$request->setTimeout(5);
|
||||
}
|
||||
|
||||
/**
|
||||
* - Create route using overwrite.cli.url.
|
||||
* - can be forced using FORCE_NC_BASE or TEST_BC_BASE (temporary)
|
||||
* - can also be overwritten in config/config.php: 'circles.force_nc_base'
|
||||
* - perfect for loopback request.
|
||||
*
|
||||
* @param NC22Request $request
|
||||
* @param string $routeName
|
||||
* @param array $args
|
||||
*/
|
||||
private function configureRequestAddress(
|
||||
NC22Request $request,
|
||||
string $routeName,
|
||||
array $args = []
|
||||
): void {
|
||||
if ($routeName === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$ncBase = $this->getForcedNcBase();
|
||||
if ($ncBase !== '') {
|
||||
$absolute = $this->cleanLinkToRoute($ncBase, $routeName, $args);
|
||||
} else {
|
||||
$absolute = $this->urlGenerator->linkToRouteAbsolute($routeName, $args);
|
||||
}
|
||||
|
||||
$request->basedOnUrl($absolute);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* - return force_nc_base from config/config.php, then from FORCE_NC_BASE.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getForcedNcBase(): string {
|
||||
if ($this->getAppValue(self::TEST_NC_BASE) !== '') {
|
||||
return $this->getAppValue(self::TEST_NC_BASE);
|
||||
}
|
||||
|
||||
$fromConfig = $this->config->getSystemValue('circles.force_nc_base', '');
|
||||
if ($fromConfig !== '') {
|
||||
return $fromConfig;
|
||||
}
|
||||
|
||||
return $this->getAppValue(self::FORCE_NC_BASE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sometimes, linkToRoute will include the base path to the nextcloud which will be duplicate with ncBase
|
||||
|
|
|
@ -62,6 +62,7 @@ use OCA\Circles\IFederatedItemDataRequestOnly;
|
|||
use OCA\Circles\IFederatedItemInitiatorCheckNotRequired;
|
||||
use OCA\Circles\IFederatedItemInitiatorMembershipNotRequired;
|
||||
use OCA\Circles\IFederatedItemLimitedToInstanceWithMembership;
|
||||
use OCA\Circles\IFederatedItemLoopbackTest;
|
||||
use OCA\Circles\IFederatedItemMemberCheckNotRequired;
|
||||
use OCA\Circles\IFederatedItemMemberEmpty;
|
||||
use OCA\Circles\IFederatedItemMemberOptional;
|
||||
|
@ -157,15 +158,18 @@ class FederatedEventService extends NC22Signature {
|
|||
* @throws RemoteResourceNotFoundException
|
||||
* @throws UnknownRemoteException
|
||||
* @throws RemoteInstanceException
|
||||
* @throws RequestBuilderException
|
||||
*/
|
||||
public function newEvent(FederatedEvent $event): array {
|
||||
$event->setSource($this->configService->getFrontalInstance());
|
||||
$event->setSource($this->configService->getLocalInstance());
|
||||
|
||||
$federatedItem = $this->getFederatedItem($event, false);
|
||||
|
||||
$this->confirmInitiator($event, true);
|
||||
if ($this->configService->isLocalInstance($event->getCircle()->getInstance())) {
|
||||
$event->setIncomingOrigin($event->getCircle()->getInstance());
|
||||
if ($event->canBypass(FederatedEvent::BYPASS_CIRCLE)
|
||||
|| $this->configService->isLocalInstance($event->getCircle()->getInstance())) {
|
||||
// $event->setIncomingOrigin($event->getCircle()->getInstance());
|
||||
$event->setIncomingOrigin($this->configService->getLocalInstance());
|
||||
|
||||
$federatedItem->verify($event);
|
||||
|
||||
|
@ -273,6 +277,10 @@ class FederatedEventService extends NC22Signature {
|
|||
* @param IFederatedItem $item
|
||||
*/
|
||||
private function setFederatedEventBypass(FederatedEvent $event, IFederatedItem $item) {
|
||||
if ($item instanceof IFederatedItemLoopbackTest) {
|
||||
$event->bypass(FederatedEvent::BYPASS_CIRCLE);
|
||||
$event->bypass(FederatedEvent::BYPASS_INITIATORCHECK);
|
||||
}
|
||||
if ($item instanceof IFederatedItemCircleCheckNotRequired) {
|
||||
$event->bypass(FederatedEvent::BYPASS_LOCALCIRCLECHECK);
|
||||
}
|
||||
|
@ -301,7 +309,7 @@ class FederatedEventService extends NC22Signature {
|
|||
IFederatedItem $item,
|
||||
bool $checkLocalOnly = true
|
||||
) {
|
||||
if (!$event->hasCircle()) {
|
||||
if (!$event->canBypass(FederatedEvent::BYPASS_CIRCLE) && !$event->hasCircle()) {
|
||||
throw new FederatedEventException('FederatedEvent has no Circle linked');
|
||||
}
|
||||
|
||||
|
@ -376,6 +384,8 @@ class FederatedEventService extends NC22Signature {
|
|||
*
|
||||
* @param FederatedEvent $event
|
||||
* @param array $filter
|
||||
*
|
||||
* @throws RequestBuilderException
|
||||
*/
|
||||
public function initBroadcast(FederatedEvent $event, array $filter = []): void {
|
||||
$instances = array_diff($this->getInstances($event), $filter);
|
||||
|
@ -389,9 +399,10 @@ class FederatedEventService extends NC22Signature {
|
|||
$wrapper->setCreation(time());
|
||||
$wrapper->setSeverity($event->getSeverity());
|
||||
|
||||
$circle = $event->getCircle();
|
||||
foreach ($instances as $instance) {
|
||||
if ($circle->isConfig(Circle::CFG_LOCAL) && !$this->configService->isLocalInstance($instance)) {
|
||||
if ($event->hasCircle()
|
||||
&& $event->getCircle()->isConfig(Circle::CFG_LOCAL)
|
||||
&& !$this->configService->isLocalInstance($instance)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -400,8 +411,10 @@ class FederatedEventService extends NC22Signature {
|
|||
}
|
||||
|
||||
$request = new NC22Request('', Request::TYPE_POST);
|
||||
$this->configService->configureRequest(
|
||||
$request, 'circles.EventWrapper.asyncBroadcast', ['token' => $wrapper->getToken()]
|
||||
$this->configService->configureLoopbackRequest(
|
||||
$request,
|
||||
'circles.EventWrapper.asyncBroadcast',
|
||||
['token' => $wrapper->getToken()]
|
||||
);
|
||||
|
||||
$event->setWrapperToken($wrapper->getToken());
|
||||
|
@ -423,6 +436,10 @@ class FederatedEventService extends NC22Signature {
|
|||
public function getInstances(FederatedEvent $event): array {
|
||||
$local = $this->configService->getFrontalInstance();
|
||||
|
||||
if (!$event->hasCircle()) {
|
||||
return [$this->configService->getLoopbackInstance()];
|
||||
}
|
||||
|
||||
$circle = $event->getCircle();
|
||||
$instances = array_map(
|
||||
function(RemoteInstance $instance): string {
|
||||
|
|
|
@ -121,14 +121,20 @@ class RemoteStreamService extends NC22Signature {
|
|||
* Returns the Signatory model for the Circles app.
|
||||
* Can be signed with a confirmKey.
|
||||
*
|
||||
* @param bool $internal
|
||||
* @param bool $generate
|
||||
* @param string $confirmKey
|
||||
*
|
||||
* @return RemoteInstance
|
||||
* @throws SignatoryException
|
||||
* @throws RemoteInstanceException
|
||||
*/
|
||||
public function getAppSignatory(bool $generate = true, string $confirmKey = ''): RemoteInstance {
|
||||
$app = new RemoteInstance($this->configService->getFrontalPath());
|
||||
public function getAppSignatory(
|
||||
bool $internal = false,
|
||||
bool $generate = true,
|
||||
string $confirmKey = ''
|
||||
): RemoteInstance {
|
||||
$app = new RemoteInstance($this->configService->getInstancePath($internal));
|
||||
$this->fillSimpleSignatory($app, $generate);
|
||||
$app->setUidFromKey();
|
||||
|
||||
|
@ -136,14 +142,15 @@ class RemoteStreamService extends NC22Signature {
|
|||
$app->setAuthSigned($this->signString($confirmKey, $app));
|
||||
}
|
||||
|
||||
$app->setRoot($this->configService->getFrontalPath(''));
|
||||
$app->setEvent($this->configService->getFrontalPath('circles.Remote.event'));
|
||||
$app->setIncoming($this->configService->getFrontalPath('circles.Remote.incoming'));
|
||||
$app->setTest($this->configService->getFrontalPath('circles.Remote.test'));
|
||||
$app->setCircles($this->configService->getFrontalPath('circles.Remote.circles'));
|
||||
$app->setRoot($this->configService->getInstancePath($internal, ''));
|
||||
$app->setEvent($this->configService->getInstancePath($internal, 'circles.Remote.event'));
|
||||
$app->setIncoming($this->configService->getInstancePath($internal, 'circles.Remote.incoming'));
|
||||
$app->setTest($this->configService->getInstancePath($internal, 'circles.Remote.test'));
|
||||
$app->setCircles($this->configService->getInstancePath($internal, 'circles.Remote.circles'));
|
||||
$app->setCircle(
|
||||
urldecode(
|
||||
$this->configService->getFrontalPath(
|
||||
$this->configService->getInstancePath(
|
||||
$internal,
|
||||
'circles.Remote.circle',
|
||||
['circleId' => '{circleId}']
|
||||
)
|
||||
|
@ -151,7 +158,8 @@ class RemoteStreamService extends NC22Signature {
|
|||
);
|
||||
$app->setMembers(
|
||||
urldecode(
|
||||
$this->configService->getFrontalPath(
|
||||
$this->configService->getInstancePath(
|
||||
$internal,
|
||||
'circles.Remote.members',
|
||||
['circleId' => '{circleId}']
|
||||
)
|
||||
|
@ -159,7 +167,8 @@ class RemoteStreamService extends NC22Signature {
|
|||
);
|
||||
$app->setMember(
|
||||
urldecode(
|
||||
$this->configService->getFrontalPath(
|
||||
$this->configService->getInstancePath(
|
||||
$internal,
|
||||
'circles.Remote.member',
|
||||
['type' => '{type}', 'userId' => '{userId}']
|
||||
)
|
||||
|
@ -253,7 +262,7 @@ class RemoteStreamService extends NC22Signature {
|
|||
|
||||
$request = new NC22Request('', $type);
|
||||
if ($this->configService->isLocalInstance($instance)) {
|
||||
$this->configService->configureRequest($request, 'circles.Remote.' . $item, $params);
|
||||
$this->configService->configureLoopbackRequest($request, 'circles.Remote.' . $item, $params);
|
||||
} else {
|
||||
$this->configService->configureRequest($request);
|
||||
$link = $this->getRemoteInstanceEntry($instance, $item, $params);
|
||||
|
@ -385,24 +394,29 @@ class RemoteStreamService extends NC22Signature {
|
|||
*
|
||||
* @param string $instance
|
||||
* @param string $type
|
||||
* @param int $iface
|
||||
* @param bool $overwrite
|
||||
*
|
||||
* @throws RemoteAlreadyExistsException
|
||||
* @throws RemoteUidException
|
||||
* @throws RequestNetworkException
|
||||
* @throws SignatoryException
|
||||
* @throws SignatureException
|
||||
* @throws WellKnownLinkNotFoundException
|
||||
* @throws RemoteAlreadyExistsException
|
||||
* @throws RemoteUidException
|
||||
*/
|
||||
public function addRemoteInstance(
|
||||
string $instance, string $type = RemoteInstance::TYPE_EXTERNAL, bool $overwrite = false
|
||||
string $instance,
|
||||
string $type = RemoteInstance::TYPE_EXTERNAL,
|
||||
int $iface = RemoteInstance::IFACE_FRONTAL,
|
||||
bool $overwrite = false
|
||||
): void {
|
||||
if ($this->configService->isLocalInstance($instance)) {
|
||||
throw new RemoteAlreadyExistsException('instance is local');
|
||||
}
|
||||
|
||||
$remoteInstance = $this->retrieveRemoteInstance($instance);
|
||||
$remoteInstance->setType($type);
|
||||
$remoteInstance->setType($type)
|
||||
->setInterface($iface);
|
||||
|
||||
try {
|
||||
$known = $this->remoteRequest->searchDuplicate($remoteInstance);
|
||||
|
|
|
@ -31,14 +31,12 @@ use daita\MySmallPhpTools\Model\Nextcloud\nc22\NC22Request;
|
|||
use daita\MySmallPhpTools\Model\Request;
|
||||
use daita\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Request;
|
||||
use Exception;
|
||||
use OCA\Circles\Api\v1\Circles;
|
||||
use OCA\Circles\Db\DeprecatedCirclesRequest;
|
||||
use OCA\Circles\Db\FederatedLinksRequest;
|
||||
use OCA\Circles\Db\SharingFrameRequest;
|
||||
use OCA\Circles\Exceptions\CircleDoesNotExistException;
|
||||
use OCA\Circles\Exceptions\ConfigNoCircleAvailableException;
|
||||
use OCA\Circles\Exceptions\MemberDoesNotExistException;
|
||||
use OCA\Circles\Exceptions\PayloadDeliveryException;
|
||||
use OCA\Circles\Exceptions\SharingFrameAlreadyDeliveredException;
|
||||
use OCA\Circles\Exceptions\SharingFrameAlreadyExistException;
|
||||
use OCA\Circles\Exceptions\SharingFrameDoesNotExistException;
|
||||
|
@ -318,7 +316,6 @@ class SharingFrameService {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param SharingFrame $frame
|
||||
*
|
||||
|
@ -349,7 +346,8 @@ class SharingFrameService {
|
|||
* @param SharingFrame $frame
|
||||
* @param FederatedLink[] $links
|
||||
*/
|
||||
private function forwardSharingFrameToFederatedLinks(DeprecatedCircle $circle, SharingFrame $frame, $links) {
|
||||
private function forwardSharingFrameToFederatedLinks(DeprecatedCircle $circle, SharingFrame $frame, $links
|
||||
) {
|
||||
//
|
||||
// $args = [
|
||||
// 'apiVersion' => Circles::version(),
|
||||
|
|
Loading…
Reference in a new issue