aboutsummaryrefslogtreecommitdiffhomepage
path: root/Digitigrade/Model/Instance.php
diff options
context:
space:
mode:
Diffstat (limited to 'Digitigrade/Model/Instance.php')
-rw-r--r--Digitigrade/Model/Instance.php75
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