Skip to content

Commit

Permalink
Implement Basic Auth support
Browse files Browse the repository at this point in the history
Fixes #5
  • Loading branch information
JeroenDeDauw committed Sep 28, 2021
1 parent 8ac85c2 commit c7067a8
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 2 deletions.
25 changes: 25 additions & 0 deletions src/Adapters/BasicAuthCredentials.php
@@ -0,0 +1,25 @@
<?php

declare( strict_types = 1 );

namespace ProfessionalWiki\ExternalContent\Adapters;

class BasicAuthCredentials {

private string $userName;
private string $password;

public function __construct( string $userName, string $password ) {
$this->userName = $userName;
$this->password = $password;
}

public function getUserName(): string {
return $this->userName;
}

public function getPassword(): string {
return $this->password;
}

}
22 changes: 22 additions & 0 deletions src/Adapters/DomainCredentials.php
@@ -0,0 +1,22 @@
<?php

declare( strict_types = 1 );

namespace ProfessionalWiki\ExternalContent\Adapters;

class DomainCredentials {

/**
* @var array<string, BasicAuthCredentials>
*/
private array $credentials = [];

public function add( string $domainName, BasicAuthCredentials $credentials ): void {
$this->credentials[$domainName] = $credentials;
}

public function getForDomain( string $domainName ): ?BasicAuthCredentials {
return $this->credentials[$domainName] ?? null;
}

}
22 changes: 20 additions & 2 deletions src/Adapters/MediaWikiFileFetcher.php
Expand Up @@ -11,13 +11,18 @@
class MediaWikiFileFetcher implements FileFetcher {

private HttpRequestFactory $requestFactory;
private DomainCredentials $credentials;

public function __construct( HttpRequestFactory $requestFactory ) {
public function __construct( HttpRequestFactory $requestFactory, DomainCredentials $credentials = null ) {
$this->requestFactory = $requestFactory;
$this->credentials = $credentials ?? new DomainCredentials();
}

public function fetchFile( string $fileUrl ): string {
$result = $this->requestFactory->get( $fileUrl );
$result = $this->requestFactory->get(
$fileUrl,
$this->newRequestOptions( $fileUrl )
);

if ( is_string( $result ) ) {
return $result;
Expand All @@ -26,4 +31,17 @@ public function fetchFile( string $fileUrl ): string {
throw new FileFetchingException( $fileUrl );
}

private function newRequestOptions( string $fileUrl ): array {
$credentials = $this->credentials->getForDomain( parse_url( $fileUrl, PHP_URL_HOST ) ?? '' );

if ( $credentials === null ) {
return [];
}

return [
'username' => $credentials->getUserName(),
'password' => $credentials->getPassword(),
];
}

}
40 changes: 40 additions & 0 deletions tests/Integration/Adapters/MediaWikiFileFetcherIntegrationTest.php
Expand Up @@ -7,11 +7,15 @@
use FileFetcher\FileFetchingException;
use MediaWiki\MediaWikiServices;
use PHPUnit\Framework\TestCase;
use ProfessionalWiki\ExternalContent\Adapters\BasicAuthCredentials;
use ProfessionalWiki\ExternalContent\Adapters\DomainCredentials;
use ProfessionalWiki\ExternalContent\Adapters\MediaWikiFileFetcher;
use ProfessionalWiki\ExternalContent\Tests\TestEnvironment;

/**
* @covers \ProfessionalWiki\ExternalContent\Adapters\MediaWikiFileFetcher
* @covers \ProfessionalWiki\ExternalContent\Adapters\DomainCredentials
* @covers \ProfessionalWiki\ExternalContent\Adapters\BasicAuthCredentials
*/
class MediaWikiFileFetcherIntegrationTest extends TestCase {

Expand All @@ -20,6 +24,9 @@ public function testUnreachableFileResultsInException(): void {
( new MediaWikiFileFetcher( MediaWikiServices::getInstance()->getHttpRequestFactory() ) )->fetchFile( '404' );
}

/**
* To get this test to run, set the PHPUNIT_WIKI_URL ENV var. Example: http://localhost/index.php/
*/
public function testCanGetLocalFile(): void {
$specialVersionUrl = TestEnvironment::instance()->wikiUrl( 'Special:Version' );

Expand All @@ -33,4 +40,37 @@ public function testCanGetLocalFile(): void {
);
}

/**
* To get this test to run, set these ENV vars:
* * BITBUCKET_URL example: http://bitbucket.svc:7990/projects/MYP/repos/fluffykittens/raw/README.md
* * BITBUCKET_USER example: AdminUser
* * BITBUCKET_ACCESS_TOKEN example: mQk5OYTzMDIzOTM4OvMj9wLxDiKulWL3nxG8Xr7KbBZz
* The file needs to contain the string `professional-wiki` and can thus be the README of this repo.
*/
public function testAuthenticateWithBasicAuth(): void {
$url = getenv( 'BITBUCKET_URL' );
$user = getenv( 'BITBUCKET_USER' );
$password = getenv( 'BITBUCKET_ACCESS_TOKEN' );

if ( !is_string( $url ) || !is_string( $user ) || !is_string( $password ) ) {
$this->markTestSkipped( 'Bitbucket ENV vars not set' );
}

$credentials = new DomainCredentials();
$credentials->add(
parse_url( $url, PHP_URL_HOST ),
new BasicAuthCredentials( $user, $password )
);

$fileFetcher = new MediaWikiFileFetcher(
MediaWikiServices::getInstance()->getHttpRequestFactory(),
$credentials
);

$this->assertStringContainsString(
'professional-wiki',
$fileFetcher->fetchFile( $url )
);
}

}
39 changes: 39 additions & 0 deletions tests/Unit/Adapters/MediaWikiFileFetcherTest.php
Expand Up @@ -7,10 +7,14 @@
use FileFetcher\FileFetchingException;
use MediaWiki\Http\HttpRequestFactory;
use PHPUnit\Framework\TestCase;
use ProfessionalWiki\ExternalContent\Adapters\BasicAuthCredentials;
use ProfessionalWiki\ExternalContent\Adapters\DomainCredentials;
use ProfessionalWiki\ExternalContent\Adapters\MediaWikiFileFetcher;

/**
* @covers \ProfessionalWiki\ExternalContent\Adapters\MediaWikiFileFetcher
* @covers \ProfessionalWiki\ExternalContent\Adapters\DomainCredentials
* @covers \ProfessionalWiki\ExternalContent\Adapters\BasicAuthCredentials
*/
class MediaWikiFileFetcherTest extends TestCase {

Expand All @@ -36,4 +40,39 @@ public function testWhenRequestFactoryReturnsString_itIsReturned(): void {
);
}

public function testRightCredentialsArePassed(): void {
$requestFactory = $this->createMock( HttpRequestFactory::class );
$requestFactory->expects( $this->once() )
->method( 'get' )
->with(
$this->equalTo( 'https://example.com' ),
$this->equalTo( [
'username' => 'FooUser',
'password' => 'BarPassword'
] )
)->willReturn( '~=[,,_,,]:3' );

$domainCredentials = new DomainCredentials();
$domainCredentials->add( 'another-domain.com', new BasicAuthCredentials( 'Wrong', 'Wrong' ) );
$domainCredentials->add( 'example.com', new BasicAuthCredentials( 'FooUser', 'BarPassword' ) );
$domainCredentials->add( 'example.hax', new BasicAuthCredentials( 'Wrong', 'Wrong' ) );

( new MediaWikiFileFetcher( $requestFactory, $domainCredentials ) )->fetchFile( 'https://example.com' );
}

public function testNoCredentialsArePassedWhenDomainNotInCredentialList(): void {
$requestFactory = $this->createMock( HttpRequestFactory::class );
$requestFactory->expects( $this->once() )
->method( 'get' )
->with(
$this->equalTo( 'https://example.com' ),
$this->equalTo( [] )
)->willReturn( '~=[,,_,,]:3' );

$domainCredentials = new DomainCredentials();
$domainCredentials->add( 'example.hax', new BasicAuthCredentials( 'Wrong', 'Wrong' ) );

( new MediaWikiFileFetcher( $requestFactory, $domainCredentials ) )->fetchFile( 'https://example.com' );
}

}

0 comments on commit c7067a8

Please sign in to comment.