diff options
Diffstat (limited to 'Digitigrade/Model/Instance.php')
| -rw-r--r-- | Digitigrade/Model/Instance.php | 75 |
1 files changed, 71 insertions, 4 deletions
diff --git a/Digitigrade/Model/Instance.php b/Digitigrade/Model/Instance.php index 7176fcd..9e54a5f 100644 --- a/Digitigrade/Model/Instance.php +++ b/Digitigrade/Model/Instance.php @@ -25,8 +25,8 @@ class Instance extends FetchableModel { return null; } - public static function findByDomain(string $domain, bool $autoSave = true, bool $forceRefetch = false): ?self { - return self::findByUri("https://$domain/.well-known/pawpub-instance", $autoSave, $forceRefetch); + public static function findByHostname(string $host, bool $autoSave = true, bool $forceRefetch = false): ?self { + return self::findByUri("https://$host/.well-known/pawpub-instance", $autoSave, $forceRefetch); } protected function hydrate() { @@ -40,7 +40,7 @@ class Instance extends FetchableModel { } protected function finaliseAfterFetch(string $uri) { - $this->domain = explode('/', $uri)[2]; + $this->domain = hostname_from_uri($uri); } protected function finaliseAfterSave() { @@ -50,7 +50,7 @@ class Instance extends FetchableModel { public static function findByUri(string $uri, bool $autoSave = true, bool $forceRefetch = false): ?static { if (!$forceRefetch) { - $domain = explode('/', $uri)[2]; + $domain = hostname_from_uri($uri); $obj = self::findWhere('domain = ?', [$domain]); if ($obj != null) return $obj; @@ -65,6 +65,14 @@ class Instance extends FetchableModel { return self::find($authRecord->instanceId); } + public static function findByRequestHeaders(): ?self { + if (!isset($_SERVER['HTTP_AUTHORIZATION']) || !str_starts_with($_SERVER['HTTP_AUTHORIZATION'], 'Bearer ')) + return null; + $header = $_SERVER['HTTP_AUTHORIZATION']; + $token = substr($header, 7); + return self::findByInboundAuthToken($token); + } + public static function findByDialbackSecret(string $secret): ?self { $authRecord = InstanceAuth::findWhere('secret = ?', [$secret]); if ($authRecord == null) @@ -126,4 +134,63 @@ class Instance extends FetchableModel { $refreshAt = (new \DateTimeImmutable($data->expires))->sub(new \DateInterval('PT1H')); (new RefreshOutboundAuthToken($this->domain, $refreshAt))->submit(); } + + private function subscribeOrUnsubscribe(bool $isUnsubscribe): bool { + if (!isset($this->endpoints->subscribe, $this->endpoints->unsubscribe)) { + throw new \RuntimeException("can't (un)subscribe to $this->domain because it doesn't have the right endpoints"); + } + if (!isset($this->auth->outboundToken)) { + throw new \RuntimeException("can't (un)subscribe to $this->domain because i don't have an outbound token for it"); + } + $context = stream_context_create(['http' => [ + 'header' => 'Authorization: Bearer ' . $this->auth->outboundToken + ]]); + file_get_contents($isUnsubscribe ? $this->endpoints->unsubscribe : $this->endpoints->subscribe, context: $context); + return str_contains($http_response_header[0], '200'); + } + + /** + * Tries to subscribe to the instance for receiving objects by push + * @return bool whether subscribing was successful + */ + public function subscribe(): bool { + if ($this->subscribeOrUnsubscribe(isUnsubscribe: false)) { + $this->auth->inboundPushEnabled = true; + $this->auth->save(); + return true; + } + return false; + } + + /** + * Tries to unsubscribe from the instance + * @return bool whether unsubscribing was successful + */ + public function unsubscribe() { + if ($this->subscribeOrUnsubscribe(isUnsubscribe: true)) { + $this->auth->inboundPushEnabled = false; + $this->auth->save(); + return true; + } + return false; + } + + public function pushObject(\JsonSerializable $obj) { + if (!isset($this->endpoints->push)) { + throw new \RuntimeException("can't push to $this->domain because it doesn't have a push endpoint"); + } + if (!isset($this->auth->outboundToken)) { + throw new \RuntimeException("can't push to $this->domain because i don't have an outbound token for it"); + } + if (!$this->auth->outboundPushEnabled) { + throw new \RuntimeException("won't push to $this->domain because it hasn't subscribed to us"); + } + $context = stream_context_create(['http' => [ + 'method' => 'POST', + 'header' => "Content-Type: application/json\nAuthorization: Bearer " . $this->auth->outboundToken, + 'content' => json_encode($obj) + ]]); + file_get_contents($this->endpoints->push, context: $context); + return str_contains($http_response_header[0], '200'); + } }
\ No newline at end of file |
