mirror of
https://github.com/koel/koel
synced 2025-02-17 13:58:28 +00:00
chore: use Authenticator instead of inheritance for Last.fm auth
This commit is contained in:
parent
8b5fd336df
commit
f405924bee
11 changed files with 92 additions and 65 deletions
64
app/Http/Integrations/Lastfm/Auth/LastfmAuthenticator.php
Normal file
64
app/Http/Integrations/Lastfm/Auth/LastfmAuthenticator.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Integrations\Lastfm\Auth;
|
||||
|
||||
use App\Http\Integrations\Lastfm\Contracts\RequiresSignature;
|
||||
use Saloon\Contracts\Authenticator;
|
||||
use Saloon\Http\PendingRequest;
|
||||
use Saloon\Repositories\Body\FormBodyRepository;
|
||||
|
||||
final class LastfmAuthenticator implements Authenticator
|
||||
{
|
||||
public function __construct(private string $key, private string $secret)
|
||||
{
|
||||
}
|
||||
|
||||
public function set(PendingRequest $pendingRequest): void
|
||||
{
|
||||
$this->addApiKey($pendingRequest);
|
||||
|
||||
if ($pendingRequest->getRequest() instanceof RequiresSignature) {
|
||||
$this->sign($pendingRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private function addApiKey(PendingRequest $request): void
|
||||
{
|
||||
if ($request->body() instanceof FormBodyRepository) {
|
||||
$request->body()->add('api_key', $this->key);
|
||||
} else {
|
||||
$request->query()->add('api_key', $this->key);
|
||||
}
|
||||
}
|
||||
|
||||
protected function sign(PendingRequest $request): void
|
||||
{
|
||||
if ($request->body() instanceof FormBodyRepository) {
|
||||
$request->body()->add('api_sig', $this->createSignature($request->body()->all()));
|
||||
} else {
|
||||
$request->query()->add('api_sig', $this->createSignature($request->query()->all()));
|
||||
}
|
||||
}
|
||||
|
||||
private function createSignature(array $parameters): string
|
||||
{
|
||||
ksort($parameters);
|
||||
|
||||
// Generate the API signature.
|
||||
// @link http://www.last.fm/api/webauth#6
|
||||
$str = '';
|
||||
|
||||
foreach ($parameters as $name => $value) {
|
||||
if ($name === 'format') {
|
||||
// The format parameter is not part of the signature.
|
||||
continue;
|
||||
}
|
||||
|
||||
$str .= $name . $value;
|
||||
}
|
||||
|
||||
$str .= $this->secret;
|
||||
|
||||
return md5($str);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Integrations\Concerns;
|
||||
namespace App\Http\Integrations\Lastfm\Concerns;
|
||||
|
||||
trait FormatsLastFmText
|
||||
{
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Integrations\Lastfm\Contracts;
|
||||
|
||||
interface RequiresSignature
|
||||
{
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Integrations\Lastfm;
|
||||
|
||||
use App\Http\Integrations\Lastfm\Auth\LastfmAuthenticator;
|
||||
use Saloon\Http\Connector;
|
||||
use Saloon\Traits\Plugins\AcceptsJson;
|
||||
|
||||
|
@ -13,4 +14,9 @@ class LastfmConnector extends Connector
|
|||
{
|
||||
return config('koel.lastfm.endpoint');
|
||||
}
|
||||
|
||||
protected function defaultAuth(): LastfmAuthenticator
|
||||
{
|
||||
return new LastfmAuthenticator(config('koel.lastfm.key'), config('koel.lastfm.secret'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Http\Integrations\Lastfm\Requests;
|
||||
|
||||
use App\Http\Integrations\Concerns\FormatsLastFmText;
|
||||
use App\Http\Integrations\Lastfm\Concerns\FormatsLastFmText;
|
||||
use App\Models\Album;
|
||||
use App\Values\AlbumInformation;
|
||||
use Illuminate\Support\Arr;
|
||||
|
@ -29,7 +29,6 @@ final class GetAlbumInfoRequest extends Request
|
|||
protected function defaultQuery(): array
|
||||
{
|
||||
return [
|
||||
'api_key' => config('koel.lastfm.key'),
|
||||
'method' => 'album.getInfo',
|
||||
'artist' => $this->album->artist->name,
|
||||
'album' => $this->album->name,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Http\Integrations\Lastfm\Requests;
|
||||
|
||||
use App\Http\Integrations\Concerns\FormatsLastFmText;
|
||||
use App\Http\Integrations\Lastfm\Concerns\FormatsLastFmText;
|
||||
use App\Models\Artist;
|
||||
use App\Values\ArtistInformation;
|
||||
use Saloon\Enums\Method;
|
||||
|
@ -28,7 +28,6 @@ final class GetArtistInfoRequest extends Request
|
|||
protected function defaultQuery(): array
|
||||
{
|
||||
return [
|
||||
'api_key' => config('koel.lastfm.key'),
|
||||
'method' => 'artist.getInfo',
|
||||
'artist' => $this->artist->name,
|
||||
'autocorrect' => 1,
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
|
||||
namespace App\Http\Integrations\Lastfm\Requests;
|
||||
|
||||
use App\Http\Integrations\Lastfm\Contracts\RequiresSignature;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
|
||||
final class GetSessionKeyRequest extends SignedRequest
|
||||
final class GetSessionKeyRequest extends Request implements RequiresSignature
|
||||
{
|
||||
protected Method $method = Method::GET;
|
||||
|
||||
public function __construct(private string $token)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function resolveEndpoint(): string
|
||||
|
@ -22,7 +23,6 @@ final class GetSessionKeyRequest extends SignedRequest
|
|||
protected function defaultQuery(): array
|
||||
{
|
||||
return [
|
||||
'api_key' => config('koel.lastfm.key'),
|
||||
'method' => 'auth.getSession',
|
||||
'token' => $this->token,
|
||||
'format' => 'json',
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
|
||||
namespace App\Http\Integrations\Lastfm\Requests;
|
||||
|
||||
use App\Http\Integrations\Lastfm\Contracts\RequiresSignature;
|
||||
use App\Models\Album;
|
||||
use App\Models\Song;
|
||||
use App\Models\User;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasFormBody;
|
||||
|
||||
final class ScrobbleRequest extends SignedRequest implements HasBody
|
||||
final class ScrobbleRequest extends Request implements HasBody, RequiresSignature
|
||||
{
|
||||
use HasFormBody;
|
||||
|
||||
|
@ -17,7 +19,6 @@ final class ScrobbleRequest extends SignedRequest implements HasBody
|
|||
|
||||
public function __construct(private Song $song, private User $user, private int $timestamp)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function resolveEndpoint(): string
|
||||
|
@ -29,7 +30,6 @@ final class ScrobbleRequest extends SignedRequest implements HasBody
|
|||
protected function defaultBody(): array
|
||||
{
|
||||
$body = [
|
||||
'api_key' => config('koel.lastfm.key'),
|
||||
'method' => 'track.scrobble',
|
||||
'artist' => $this->song->artist->name,
|
||||
'track' => $this->song->title,
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Integrations\Lastfm\Requests;
|
||||
|
||||
use Saloon\Http\PendingRequest;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Repositories\Body\FormBodyRepository;
|
||||
|
||||
abstract class SignedRequest extends Request
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware()->onRequest(fn (PendingRequest $request) => $this->sign($request));
|
||||
}
|
||||
|
||||
protected function sign(PendingRequest $request): void
|
||||
{
|
||||
if ($request->body() instanceof FormBodyRepository) {
|
||||
$request->body()->add('api_sig', self::createSignature($request->body()->all()));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$request->query()->add('api_sig', self::createSignature($request->query()->all()));
|
||||
}
|
||||
|
||||
private static function createSignature(array $parameters): string
|
||||
{
|
||||
ksort($parameters);
|
||||
|
||||
// Generate the API signature.
|
||||
// @link http://www.last.fm/api/webauth#6
|
||||
$str = '';
|
||||
|
||||
foreach ($parameters as $name => $value) {
|
||||
if ($name === 'format') {
|
||||
// The format parameter is not part of the signature.
|
||||
continue;
|
||||
}
|
||||
|
||||
$str .= $name . $value;
|
||||
}
|
||||
|
||||
$str .= config('koel.lastfm.secret');
|
||||
|
||||
return md5($str);
|
||||
}
|
||||
}
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
namespace App\Http\Integrations\Lastfm\Requests;
|
||||
|
||||
use App\Http\Integrations\Lastfm\Contracts\RequiresSignature;
|
||||
use App\Models\Song;
|
||||
use App\Models\User;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasFormBody;
|
||||
|
||||
final class ToggleLoveTrackRequest extends SignedRequest implements HasBody
|
||||
final class ToggleLoveTrackRequest extends Request implements HasBody, RequiresSignature
|
||||
{
|
||||
use HasFormBody;
|
||||
|
||||
|
@ -16,7 +18,6 @@ final class ToggleLoveTrackRequest extends SignedRequest implements HasBody
|
|||
|
||||
public function __construct(private Song $song, private User $user, private bool $love)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function resolveEndpoint(): string
|
||||
|
@ -28,7 +29,6 @@ final class ToggleLoveTrackRequest extends SignedRequest implements HasBody
|
|||
protected function defaultBody(): array
|
||||
{
|
||||
return [
|
||||
'api_key' => config('koel.lastfm.key'),
|
||||
'method' => $this->love ? 'track.love' : 'track.unlove',
|
||||
'sk' => $this->user->preferences->lastFmSessionKey,
|
||||
'artist' => $this->song->artist->name,
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
|
||||
namespace App\Http\Integrations\Lastfm\Requests;
|
||||
|
||||
use App\Http\Integrations\Lastfm\Contracts\RequiresSignature;
|
||||
use App\Models\Album;
|
||||
use App\Models\Song;
|
||||
use App\Models\User;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasFormBody;
|
||||
|
||||
final class UpdateNowPlayingRequest extends SignedRequest implements HasBody
|
||||
final class UpdateNowPlayingRequest extends Request implements HasBody, RequiresSignature
|
||||
{
|
||||
use HasFormBody;
|
||||
|
||||
|
@ -17,7 +19,6 @@ final class UpdateNowPlayingRequest extends SignedRequest implements HasBody
|
|||
|
||||
public function __construct(private Song $song, private User $user)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function resolveEndpoint(): string
|
||||
|
@ -29,7 +30,6 @@ final class UpdateNowPlayingRequest extends SignedRequest implements HasBody
|
|||
protected function defaultBody(): array
|
||||
{
|
||||
$parameters = [
|
||||
'api_key' => config('koel.lastfm.key'),
|
||||
'method' => 'track.updateNowPlaying',
|
||||
'artist' => $this->song->artist->name,
|
||||
'track' => $this->song->title,
|
||||
|
|
Loading…
Add table
Reference in a new issue