aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2024-02-28 10:06:19 +0100
committerJoas Schilling <coding@schilljs.com>2024-02-28 10:20:55 +0100
commitecb111cec74d96ed66e0880bef093d1156afa256 (patch)
tree5d48abc3489fe983aa9d7454117fa12870e16b47
parent6f95febe17bc982da4468579e3a33c08583b4a8f (diff)
downloadnextcloud-server-ecb111cec74d96ed66e0880bef093d1156afa256.tar.gz
nextcloud-server-ecb111cec74d96ed66e0880bef093d1156afa256.zip
fix(federation): Allow cloud federation providers to handle unsuccessful return codes
Otherwise they are put to retry and will immediately trigger bruteforce protection infinitely Signed-off-by: Joas Schilling <coding@schilljs.com>
-rw-r--r--lib/private/Federation/CloudFederationProviderManager.php61
-rw-r--r--lib/private/Http/Client/Client.php16
-rw-r--r--lib/public/Federation/ICloudFederationProviderManager.php22
-rw-r--r--lib/public/Http/Client/IClient.php10
4 files changed, 109 insertions, 0 deletions
diff --git a/lib/private/Federation/CloudFederationProviderManager.php b/lib/private/Federation/CloudFederationProviderManager.php
index ea2f0dd7575..07df3e7a209 100644
--- a/lib/private/Federation/CloudFederationProviderManager.php
+++ b/lib/private/Federation/CloudFederationProviderManager.php
@@ -36,6 +36,7 @@ use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudFederationShare;
use OCP\Federation\ICloudIdManager;
use OCP\Http\Client\IClientService;
+use OCP\Http\Client\IResponse;
use OCP\IConfig;
use OCP\OCM\Exceptions\OCMProviderException;
use OCP\OCM\IOCMDiscoveryService;
@@ -111,6 +112,9 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
}
}
+ /**
+ * @deprecated 29.0.0 - Use {@see sendCloudShare()} instead and handle errors manually
+ */
public function sendShare(ICloudFederationShare $share) {
$cloudID = $this->cloudIdManager->resolveCloudId($share->getShareWith());
try {
@@ -148,9 +152,38 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
}
/**
+ * @param ICloudFederationShare $share
+ * @return IResponse
+ * @throws OCMProviderException
+ */
+ public function sendCloudShare(ICloudFederationShare $share): IResponse {
+ $cloudID = $this->cloudIdManager->resolveCloudId($share->getShareWith());
+ $ocmProvider = $this->discoveryService->discover($cloudID->getRemote());
+
+ $client = $this->httpClientService->newClient();
+ try {
+ return $client->post($ocmProvider->getEndPoint() . '/shares', [
+ 'body' => json_encode($share->getShare()),
+ 'headers' => ['content-type' => 'application/json'],
+ 'verify' => !$this->config->getSystemValueBool('sharing.federation.allowSelfSignedCertificates', false),
+ 'timeout' => 10,
+ 'connect_timeout' => 10,
+ ]);
+ } catch (\Throwable $e) {
+ $this->logger->error('Error while sending share to federation server: ' . $e->getMessage(), ['exception' => $e]);
+ try {
+ return $client->getResponseFromThrowable($e);
+ } catch (\Throwable $e) {
+ throw new OCMProviderException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+ }
+
+ /**
* @param string $url
* @param ICloudFederationNotification $notification
* @return array|false
+ * @deprecated 29.0.0 - Use {@see sendCloudNotification()} instead and handle errors manually
*/
public function sendNotification($url, ICloudFederationNotification $notification) {
try {
@@ -181,6 +214,34 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
}
/**
+ * @param string $url
+ * @param ICloudFederationNotification $notification
+ * @return IResponse
+ * @throws OCMProviderException
+ */
+ public function sendCloudNotification(string $url, ICloudFederationNotification $notification): IResponse {
+ $ocmProvider = $this->discoveryService->discover($url);
+
+ $client = $this->httpClientService->newClient();
+ try {
+ return $client->post($ocmProvider->getEndPoint() . '/notifications', [
+ 'body' => json_encode($notification->getMessage()),
+ 'headers' => ['content-type' => 'application/json'],
+ 'verify' => !$this->config->getSystemValueBool('sharing.federation.allowSelfSignedCertificates', false),
+ 'timeout' => 10,
+ 'connect_timeout' => 10,
+ ]);
+ } catch (\Throwable $e) {
+ $this->logger->error('Error while sending notification to federation server: ' . $e->getMessage(), ['exception' => $e]);
+ try {
+ return $client->getResponseFromThrowable($e);
+ } catch (\Throwable $e) {
+ throw new OCMProviderException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+ }
+
+ /**
* check if the new cloud federation API is ready to be used
*
* @return bool
diff --git a/lib/private/Http/Client/Client.php b/lib/private/Http/Client/Client.php
index 26a0a63378b..b43583ba09a 100644
--- a/lib/private/Http/Client/Client.php
+++ b/lib/private/Http/Client/Client.php
@@ -408,6 +408,22 @@ class Client implements IClient {
return new Response($response);
}
+ /**
+ * Get the response of a Throwable thrown by the request methods when possible
+ *
+ * @param \Throwable $e
+ * @return IResponse
+ * @throws \Throwable When $e did not have a response
+ * @since 29.0.0
+ */
+ public function getResponseFromThrowable(\Throwable $e): IResponse {
+ if (method_exists($e, 'hasResponse') && method_exists($e, 'getResponse') && $e->hasResponse()) {
+ return new Response($e->getResponse());
+ }
+
+ throw $e;
+ }
+
protected function wrapGuzzlePromise(PromiseInterface $promise): IPromise {
return new GuzzlePromiseAdapter(
$promise,
diff --git a/lib/public/Federation/ICloudFederationProviderManager.php b/lib/public/Federation/ICloudFederationProviderManager.php
index 7272653b14d..14ac59f3b0b 100644
--- a/lib/public/Federation/ICloudFederationProviderManager.php
+++ b/lib/public/Federation/ICloudFederationProviderManager.php
@@ -23,6 +23,9 @@
*/
namespace OCP\Federation;
+use OCP\Http\Client\IResponse;
+use OCP\OCM\Exceptions\OCMProviderException;
+
/**
* Class ICloudFederationProviderManager
*
@@ -80,10 +83,19 @@ interface ICloudFederationProviderManager {
* @return mixed
*
* @since 14.0.0
+ * @deprecated 29.0.0 - Use {@see sendCloudShare()} instead and handle errors manually
*/
public function sendShare(ICloudFederationShare $share);
/**
+ * @param ICloudFederationShare $share
+ * @return IResponse
+ * @throws OCMProviderException
+ * @since 29.0.0
+ */
+ public function sendCloudShare(ICloudFederationShare $share): IResponse;
+
+ /**
* send notification about existing share
*
* @param string $url
@@ -91,10 +103,20 @@ interface ICloudFederationProviderManager {
* @return array|false
*
* @since 14.0.0
+ * @deprecated 29.0.0 - Use {@see sendCloudNotification()} instead and handle errors manually
*/
public function sendNotification($url, ICloudFederationNotification $notification);
/**
+ * @param string $url
+ * @param ICloudFederationNotification $notification
+ * @return IResponse
+ * @throws OCMProviderException
+ * @since 29.0.0
+ */
+ public function sendCloudNotification(string $url, ICloudFederationNotification $notification): IResponse;
+
+ /**
* check if the new cloud federation API is ready to be used
*
* @return bool
diff --git a/lib/public/Http/Client/IClient.php b/lib/public/Http/Client/IClient.php
index fb1760c25f2..9268eb62920 100644
--- a/lib/public/Http/Client/IClient.php
+++ b/lib/public/Http/Client/IClient.php
@@ -208,6 +208,16 @@ interface IClient {
public function options(string $uri, array $options = []): IResponse;
/**
+ * Get the response of a Throwable thrown by the request methods when possible
+ *
+ * @param \Throwable $e
+ * @return IResponse
+ * @throws \Throwable When $e did not have a response
+ * @since 29.0.0
+ */
+ public function getResponseFromThrowable(\Throwable $e): IResponse;
+
+ /**
* Sends an asynchronous GET request
* @param string $uri
* @param array $options Array such as