1
0
mirror of https://github.com/beestat/app.git synced 2025-05-23 18:04:14 -04:00
beestat/api/patreon_token.php
2023-08-29 22:43:04 -04:00

147 lines
4.2 KiB
PHP

<?php
/**
* Tokens for authorizing access to Patreon accounts.
*
* @author Jon Ziebell
*/
class patreon_token extends cora\crud {
/**
* Obtain Patreon access & refresh tokens. If a token already exists for
* this user, overwrite it.
*
* @param string $code The code from patreon used to obtain the
* access/refresh tokens.
*
* @return array The patreon_token row.
*/
public function obtain($code) {
// Obtain the access and refresh tokens from the authorization code.
$response = $this->api(
'patreon',
'patreon_api',
[
'method' => 'POST',
'endpoint' => 'token',
'arguments' => [
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => $this->setting->get('patreon_redirect_uri')
]
]
);
// Make sure we got the expected result.
if (
isset($response['access_token']) === false ||
isset($response['refresh_token']) === false
) {
throw new cora\exception('Could not get first Patreon token.', 10100);
}
$new_patreon_token = [
'access_token' => $response['access_token'],
'refresh_token' => $response['refresh_token'],
'deleted' => false
];
/**
* Look for existing tokens (in case access was revoked and then
* re-granted). Include deleted tokens and revive that row since each user
* is limited to one token row.
*/
$existing_patreon_token = $this->read([
'deleted' => [0, 1]
]);
if (count($existing_patreon_token) > 0) {
$this->update(array_merge(
['patreon_token_id' => $existing_patreon_token[0]['patreon_token_id']],
$new_patreon_token
));
} else {
$this->create($new_patreon_token);
}
return $this->read()[0];
}
/**
* Get some new tokens. A database lock is obtained prior to getting a token
* so that no other API call can attempt to get a token at the same time.
* This way if two API calls fire off to patreon at the same time, then
* return at the same time, then call token->refresh() at the same time,
* only one can run and actually refresh at a time. If the transactionless
* one runs after that's fine as it will look up the token prior to
* refreshing.
*/
public function refresh() {
$database = cora\database::get_transactionless_instance();
$lock_name = 'patreon_token->refresh(' . $this->session->get_user_id() . ')';
$database->get_lock($lock_name, 3);
$patreon_tokens = $database->read(
'patreon_token',
[
'user_id' => $this->session->get_user_id(),
'deleted' => false
]
);
if(count($patreon_tokens) === 0) {
throw new cora\exception('Could not refresh Patreon token; no token found.', 10101);
}
$patreon_token = $patreon_tokens[0];
$response = $this->api(
'patreon',
'patreon_api',
[
'method' => 'POST',
'endpoint' => 'token',
'arguments' => [
'grant_type' => 'refresh_token',
'refresh_token' => $patreon_token['refresh_token']
]
]
);
if (
isset($response['access_token']) === false ||
isset($response['refresh_token']) === false
) {
$this->delete($patreon_token['patreon_token_id']);
$database->release_lock($lock_name);
throw new cora\exception('Could not refresh Patreon token; Patreon returned no token.', 10102, true, null, false);
}
$patreon_token = $database->update(
'patreon_token',
[
'patreon_token_id' => $patreon_token['patreon_token_id'],
'access_token' => $response['access_token'],
'refresh_token' => $response['refresh_token'],
'timestamp' => date('Y-m-d H:i:s')
]
);
$database->release_lock($lock_name);
return $patreon_token;
}
/**
* Delete a Patreon token and log the user out. Make sure to delete the
* token prior to logging out so the right permissions are present.
*
* @param int $id
*
* @return int
*/
public function delete($id) {
return parent::delete($id);
}
}