diff options
Diffstat (limited to 'Digitigrade/Model/Instance.php')
| -rw-r--r-- | Digitigrade/Model/Instance.php | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/Digitigrade/Model/Instance.php b/Digitigrade/Model/Instance.php index de3ff9d..5f33e6d 100644 --- a/Digitigrade/Model/Instance.php +++ b/Digitigrade/Model/Instance.php @@ -1,7 +1,7 @@ <?php namespace Digitigrade\Model; -use Digitigrade\Model; +use Digitigrade\Job\RefreshOutboundAuthToken; class Instance extends FetchableModel { public ?int $id; @@ -15,6 +15,7 @@ class Instance extends FetchableModel { public ?string $softwareHomepage; public InstanceEndpoints $endpoints; + public InstanceAuth $auth; protected function getUpdateWhereClause(\PDO $db): ?string { if (self::findWhere('domain = ?', [$this->domain]) != null) @@ -28,14 +29,25 @@ class Instance extends FetchableModel { return self::findByUri("https://$domain/.well-known/pawpub-instance", $autoSave, $forceRefetch); } - public function hydrate() { + protected function hydrate() { $this->endpoints = InstanceEndpoints::findWhere('instance_id = ?', [$this->id]); + $auth = InstanceAuth::findWhere('instance_id = ?', [$this->id]); + if ($auth == null) { + $auth = new InstanceAuth(); + $auth->setOwnerId($this->id); + } + $this->auth = $auth; } - protected function beforeSave(string $uri) { + protected function finaliseAfterFetch(string $uri) { $this->domain = explode('/', $uri)[2]; } + protected function finaliseAfterSave() { + // this has to be done after saving because we didn't have an id before + $this->auth = InstanceAuth::findWhere('instance_id = ?', [$this->id]) ?? new InstanceAuth(); + } + public static function findByUri(string $uri, bool $autoSave = true, bool $forceRefetch = false): ?static { if (!$forceRefetch) { $domain = explode('/', $uri)[2]; @@ -45,4 +57,55 @@ class Instance extends FetchableModel { } return self::fetchFromRemote($uri, $autoSave); } + + public function beginOutboundAuth() { + $authEndpoint = $this->endpoints->auth; + if (!isset($authEndpoint)) { + throw new \RuntimeException("can't authenticate with $this->domain because it doesn't have an auth endpoint"); + } + file_get_contents($authEndpoint . '?phase=dialback&target=' . urlencode(path_to_uri('/auth/dialback'))); + } + + public function requestOutboundAuthToken(string $secret) { + $authEndpoint = $this->endpoints->auth; + if (!isset($authEndpoint)) { + throw new \RuntimeException("can't authenticate with $this->domain because it doesn't have an auth endpoint"); + } + $response = file_get_contents($authEndpoint . '?phase=token&secret=' . urlencode($secret)); + if ($response === false) { + throw new \RuntimeException("requesting a token from $this->domain failed"); + } + $data = json_decode($response); + if ($data === false || !isset($data->token, $data->expires)) { + throw new \RuntimeException("$this->domain sent bogus json in response to token request"); + } + + $this->auth->outboundToken = $data->token; + $this->save(); + + (new RefreshOutboundAuthToken($this->domain, new \DateTimeImmutable($data->expires)))->submit(); + } + + public function refreshOutboundAuthToken() { + $authEndpoint = $this->endpoints->auth; + if (!isset($authEndpoint)) { + throw new \RuntimeException("can't authenticate with $this->domain because it doesn't have an auth endpoint"); + } + if (!isset($this->auth->outboundToken)) { + throw new \RuntimeException("can't refresh outbound token for $this->domain because i don't already have one"); + } + $response = file_get_contents($authEndpoint . '?phase=refresh&token=' . urlencode($this->auth->outboundToken)); + if ($response === false) { + throw new \RuntimeException("requesting a new token from $this->domain failed"); + } + $data = json_decode($response); + if ($data === false || !isset($data->token, $data->expires)) { + throw new \RuntimeException("$this->domain sent bogus json in response to token refresh request"); + } + + $this->auth->outboundToken = $data->token; + $this->save(); + + (new RefreshOutboundAuthToken($this->domain, new \DateTimeImmutable($data->expires)))->submit(); + } }
\ No newline at end of file |
