Skip to content

Commit

Permalink
✨ Extract Domain formatter + add more formats to accept (#3000)
Browse files Browse the repository at this point in the history
  • Loading branch information
HerrLevin authored Nov 29, 2024
1 parent 65c124f commit 2440ee4
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 43 deletions.
19 changes: 2 additions & 17 deletions app/Http/Controllers/Backend/Social/MastodonController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use App\Models\Status;
use App\Models\User;
use App\Notifications\MastodonNotSent;
use App\Services\MastodonDomainExtractionService;
use Error;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
Expand Down Expand Up @@ -54,7 +55,7 @@ public static function getUserFromSocialite(SocialiteUser $socialiteUser, Mastod
* @throws InvalidMastodonException
*/
public static function getMastodonServer(string $domain): ?MastodonServer {
$domain = self::formatDomain($domain);
$domain = (new MastodonDomainExtractionService())->formatDomain($domain);

$mastodonServer = MastodonServer::where('domain', $domain)->first();

Expand All @@ -67,22 +68,6 @@ public static function getMastodonServer(string $domain): ?MastodonServer {
return $mastodonServer ?? self::createMastodonServer($domain);
}

public static function formatDomain(string $domain): string {
$domain = strtolower($domain);

// remove leading usernames
if (str_contains($domain, '@')) {
$domain = last(explode('@', $domain));
}

// Force HTTPS
$domain = str_replace('http://', 'https://', $domain);
if (!str_starts_with($domain, 'https://')) {
$domain = 'https://' . $domain;
}
return $domain;
}

/**
* @param string $domain
*
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Controllers/Frontend/Social/MastodonController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Exceptions\SocialAuth\InvalidMastodonException;
use App\Http\Controllers\Backend\Social\MastodonController as MastodonBackend;
use App\Http\Controllers\Controller;
use App\Services\MastodonDomainExtractionService;
use Carbon\Carbon;
use Exception;
use Illuminate\Http\RedirectResponse;
Expand All @@ -25,7 +26,7 @@ class MastodonController extends Controller
* @throws ValidationException
*/
public function redirect(Request $request): SympfonyRedirectResponse|RedirectResponse {
$domain = MastodonBackend::formatDomain($request->input('domain') ?? '');
$domain = (new MastodonDomainExtractionService)->formatDomain($request->input('domain') ?? '');
$validator = Validator::make(['domain' => $domain], ['domain' => ['required', 'active_url']]);
$validated = $validator->validate();

Expand Down
48 changes: 48 additions & 0 deletions app/Services/MastodonDomainExtractionService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace App\Services;

class MastodonDomainExtractionService
{
private const string HTTP_PREFIX = 'https://';
private const string REPLACE_PREFIX = 'http://';

public function formatDomain(string $domain): string {
$domain = strtolower(trim($domain));

if (empty($domain)) {
return '';
}

$domain = $this->removeProtocolFromUrl($domain);
$domain = $this->removePathFromUrl($domain);
$domain = $this->extractUrlFromUserHandleFormat($domain);

return $this->forceHttps($domain);
}

private function extractUrlFromUserHandleFormat(string $domain): string {
if (str_contains($domain, '@')) {
$domain = last(explode('@', $domain));
}

return $domain;
}

private function removePathFromUrl(string $domain): string {
return explode('/', $domain)[0];
}

private function removeProtocolFromUrl(string $domain): string {
return preg_replace('/^https?:\/\//', '', $domain);
}

private function forceHttps(string $domain): string {
$domain = str_replace(self::REPLACE_PREFIX, self::HTTP_PREFIX, $domain);
if (!str_starts_with($domain, self::HTTP_PREFIX)) {
$domain = self::HTTP_PREFIX . $domain;
}

return $domain;
}
}
25 changes: 0 additions & 25 deletions tests/Feature/Social/MastodonControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use GuzzleHttp\Psr7\Response;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Revolution\Mastodon\Facades\Mastodon;
use Tests\FeatureTestCase;

Expand All @@ -27,30 +26,6 @@ class MastodonControllerTest extends FeatureTestCase
const TOOTID_ANSWER_3 = "1340";
const OP_CONTEXT_URL = '/statuses/' . self::TOOTID_OP . '/context';

/**
* @dataProvider providerTestFormatDomain
*/
public function testFormatDomain($case, $expected): void {
$formatted = MastodonController::formatDomain($case);
$this->assertEquals($expected, $formatted);

$validated = Validator::make(['domain' => $formatted], ['domain' => ['active_url']]);

$this->assertFalse($validated->fails());
}

public static function providerTestFormatDomain(): array {
return [
['https://uelfte.club', 'https://uelfte.club'],
['http://uelfte.club', 'https://uelfte.club'],
['uelfte.club', 'https://uelfte.club'],
['great_username@uelfte.club', 'https://uelfte.club'],
['@great_username@uelfte.club', 'https://uelfte.club'],
['https://mastodon.sergal.org', 'https://mastodon.sergal.org'] # see issue 1182
];
}


public function testFindEndOfChainIfThereAreNoAnswers(): void {
$user = $this->setupUserWithMastodonAccount();

Expand Down
40 changes: 40 additions & 0 deletions tests/Unit/Services/MastodonDomainExtractionServiceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Tests\Unit\Services;

use App\Services\MastodonDomainExtractionService;
use Illuminate\Support\Facades\Validator;
use Tests\Unit\UnitTestCase;

class MastodonDomainExtractionServiceTest extends UnitTestCase
{
/**
* @dataProvider providerTestFormatDomain
*/
public function testFormatDomain($case, $expected): void {
$formatted = (new MastodonDomainExtractionService())->formatDomain($case);
$this->assertEquals($expected, $formatted);

$validated = Validator::make(['domain' => $formatted], ['domain' => ['active_url']]);

$this->assertFalse($validated->fails());
}

public static function providerTestFormatDomain(): array {
return [
[' https://github.com ', 'https://github.com'],
[' ', ''],
['', ''],
['https://github.com', 'https://github.com'],
['http://github.com', 'https://github.com'],
['github.com', 'https://github.com'],
['great_username@github.com', 'https://github.com'],
['@great_username@github.com', 'https://github.com'],
['https://traewelling.github.io', 'https://traewelling.github.io'],
['https://traewelling.github.io/', 'https://traewelling.github.io'],
['https://traewelling.github.io/@foobar', 'https://traewelling.github.io'],
['github.com/mastodon/mastodon', 'https://github.com'],
['@user@github.com/@mastodon/mastodon', 'https://github.com'] // who would do this?
];
}
}

0 comments on commit 2440ee4

Please sign in to comment.