Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions app/Helper/WikiDbVersionHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

/* The purpose of this class to have one only place where
* this map of mediawikiVersion -> dbVersion lives.
*/

namespace App\Helper;

/**
* Exception thrown when a database version is not mapped in WikiDbVersionHelper.
*/
class UnknownDbVersionException extends \Exception {}

/**
* Exception thrown when a mediawiki version is not mapped in WikiDbVersionHelper.
*/
class UnknownMwVersionException extends \Exception {}

class WikiDbVersionHelper {
/** @var array<string, string> Map of DB version strings to MediaWiki version strings */
private const DB_VERSION_TO_MW_VERSION = [
'mw1.39-wbs1' => '139',
'mw1.43-wbs1' => '143',
];

public static function isValidDbVersion(string $dbVersionString): bool {
return array_key_exists(
$dbVersionString,
self::DB_VERSION_TO_MW_VERSION
);
}

public static function isValidMwVersion(string $mwVersionString): bool {
return array_key_exists(
$mwVersionString,
array_flip(self::DB_VERSION_TO_MW_VERSION)
);
}

/**
* @throws UnknownMwVersionException
*/
public static function getDbVersion(string $mwVersionString): string {
if (self::isValidMwVersion($mwVersionString)) {
return array_flip(self::DB_VERSION_TO_MW_VERSION)[$mwVersionString];
}

throw new UnknownMwVersionException("Unknown MediaWiki version string: '{$mwVersionString}'");
}

/**
* @throws UnknownDbVersionException
*/
public static function getMwVersion(string $dbVersionString): string {
if (self::isValidDbVersion($dbVersionString)) {
return self::DB_VERSION_TO_MW_VERSION[$dbVersionString];
}

throw new UnknownDbVersionException("Unknown database version string: '{$dbVersionString}'");
}
}
48 changes: 38 additions & 10 deletions app/Http/Controllers/Backend/WikiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Http\Controllers\Backend;

use App\Helper\WikiDbVersionHelper;
use App\Http\Controllers\Controller;
use App\Wiki;
use Illuminate\Http\Request;
Expand All @@ -10,19 +11,17 @@ class WikiController extends Controller {
private static $with = ['wikiDb', 'wikiQueryserviceNamespace', 'settings'];

public function getWikiForDomain(Request $request): \Illuminate\Http\JsonResponse {
$domain = $request->input('domain');
$validated = $request->validate([
'domain' => 'required|string',
]);

$domain = $validated['domain'];

// XXX: this same logic is in quickstatements.php and platform api WikiController backend
try {
if ($domain === 'localhost' || $domain === 'mediawiki') {
// If just using localhost then just get the first undeleted wiki
$result = Wiki::with(self::$with)->first();
} else {
// TODO don't select the timestamps and redundant info for the settings?
$result = Wiki::where('domain', $domain)->with(self::$with)->first();
}
} catch (\Exception $ex) {
return response()->json($ex->getMessage(), 500);
$result = Wiki::with(['wikiDb', 'wikiQueryserviceNamespace', 'settings'])->firstWhere('domain', $domain);
} catch (\Exception $e) {
return response()->json($e->getMessage(), 500);
}

if (!$result) {
Expand All @@ -31,4 +30,33 @@ public function getWikiForDomain(Request $request): \Illuminate\Http\JsonRespons

return response()->json(['data' => $result], 200);
}

public function setWikiDbVersionForDomain(Request $request): \Illuminate\Http\JsonResponse {
$validated = $request->validate([
'domain' => 'required|string',
'dbVersion' => 'required|string',
]);

$domain = $validated['domain'];
$targetDbVersion = $validated['dbVersion'];

try {
$wiki = Wiki::with('wikiDb')->firstWhere('domain', $domain);

if (!$wiki) {
return response()->json(['error' => "No wiki found with domain: '{$domain}'"], 404);
}

if (!WikiDbVersionHelper::isValidDbVersion($targetDbVersion)) {
return response()->json(['error' => "Invalid database version string: '{$targetDbVersion}'"], 400);
}

$wiki->wikiDb->version = $targetDbVersion;
$wiki->wikiDb->save();
} catch (\Exception $e) {
return response()->json($e->getMessage(), 500);
}

return response()->json(['result' => 'success'], 200);
}
}
20 changes: 7 additions & 13 deletions app/Services/MediaWikiHostResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Services;

use App\Helper\WikiDbVersionHelper;
use App\Wiki;
use Exception;

Expand All @@ -16,17 +17,6 @@ class UnknownDBVersionException extends Exception {}
class UnknownWikiDomainException extends Exception {}

class MediaWikiHostResolver {
// TODO: Move this mapping to a config file so that MW updates do not require code changes here.
/** @var array<string, string> Map of DB version strings to MediaWiki version strings */
private const DB_VERSION_TO_MW_VERSION = [
'mw1.39-wbs1' => '139',
'mw1.43-wbs1' => '143',
];

/**
* @throws UnknownDBVersionException
* @throws UnknownWikiDomainException
*/
public function getHostsForDomain(string $domain): array {
$mwVersionForDomain = $this->getMwVersionForDomain($domain);

Expand All @@ -44,6 +34,10 @@ public function getBackendHostForDomain(string $domain): string {
return sprintf('mediawiki-%s-app-backend.default.svc.cluster.local', $this->getMwVersionForDomain($domain));
}

/**
* @throws UnknownDBVersionException
* @throws UnknownWikiDomainException
*/
private function getMwVersionForDomain(string $domain): string {
$wiki = Wiki::where('domain', $domain)->first();

Expand All @@ -53,8 +47,8 @@ private function getMwVersionForDomain(string $domain): string {

$dbVersion = $wiki->wikiDb->version;

if (array_key_exists($dbVersion, self::DB_VERSION_TO_MW_VERSION)) {
return self::DB_VERSION_TO_MW_VERSION[$dbVersion];
if (WikiDbVersionHelper::isValidDbVersion($dbVersion)) {
return WikiDbVersionHelper::getMwVersion($dbVersion);
}
throw new UnknownDBVersionException("Unknown DB version '{$dbVersion}' for domain '{$domain}'.");
}
Expand Down
2 changes: 2 additions & 0 deletions routes/backend.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
$router->group(['prefix' => 'wiki'], function () use ($router) {
// GET
$router->get('getWikiForDomain', ['uses' => 'WikiController@getWikiForDomain']);
// POST
$router->post('setDbVersion', ['uses' => 'WikiController@setWikiDbVersionForDomain']);
// PATCH
$router->patch('updateEntityImport', ['uses' => '\App\Http\Controllers\WikiEntityImportController@update']);
});
Expand Down
36 changes: 36 additions & 0 deletions tests/Helper/WikiDbVersionHelperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Tests\Jobs;

use App\Helper\UnknownDbVersionException;
use App\Helper\UnknownMwVersionException;
use App\Helper\WikiDbVersionHelper;
use Tests\TestCase;

class WikiDbVersionHelperTest extends TestCase {
public function testUnknownDbVersion() {
$this->expectException(UnknownDbVersionException::class);

WikiDbVersionHelper::getMwVersion('invalidDbVersion');
}

public function testUnknownMwVersion() {
$this->expectException(UnknownMwVersionException::class);

WikiDbVersionHelper::getDbVersion('invalidMwVersion');
}

public function testKnownDbVersion() {
$this->assertSame(
WikiDbVersionHelper::getDbVersion('143'),
'mw1.43-wbs1'
);
}

public function testKnownMwVersion() {
$this->assertSame(
WikiDbVersionHelper::getMwVersion('mw1.39-wbs1'),
'139'
);
}
}
92 changes: 92 additions & 0 deletions tests/Routes/Backend/WikiControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace Tests\Routes\Backend;

use App\Wiki;
use App\WikiDb;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class WikiControllerTest extends TestCase {
use RefreshDatabase;

const VALID_WIKI_DB_VERSION_STRING_139 = 'mw1.39-wbs1';

const VALID_WIKI_DB_VERSION_STRING_143 = 'mw1.43-wbs1';

protected $routeSetDbVersion = '/backend/wiki/setDbVersion';

protected $routeGetWikiForDomain = '/backend/wiki/getWikiForDomain';

private function createWiki(string $domain, string $version) {
$wiki = Wiki::factory()->create(['domain' => $domain]);
WikiDb::create([
'name' => $domain,
'user' => 'someUser',
'password' => 'somePassword',
'version' => $version,
'prefix' => 'somePrefix',
'wiki_id' => $wiki->id,
]);
}

public function testSetWikiDbVersionForDomainSuccess() {
$targetDbVersion = self::VALID_WIKI_DB_VERSION_STRING_143;
$wikiDomain = 'coffeebase.wikibase.cloud';

$this->createWiki($wikiDomain, self::VALID_WIKI_DB_VERSION_STRING_139);

$this->postJson("{$this->routeSetDbVersion}?domain={$wikiDomain}&dbVersion={$targetDbVersion}")
->assertStatus(200)
->assertJson([
'result' => 'success',
]);
}

public function testSetWikiDbVersionForDomainWikiNotfound() {
$targetDbVersion = self::VALID_WIKI_DB_VERSION_STRING_143;
$wikiDomain = 'notFound.wikibase.cloud';

$this->postJson("{$this->routeSetDbVersion}?domain={$wikiDomain}&dbVersion={$targetDbVersion}")
->assertStatus(404);
}

public function testSetWikiDbVersionForDomainUnknownDbVersion() {
$targetDbVersion = 'unknownVersion';
$wikiDomain = 'coffeebase.wikibase.cloud';

$this->createWiki($wikiDomain, self::VALID_WIKI_DB_VERSION_STRING_139);

$this->postJson("{$this->routeSetDbVersion}?domain={$wikiDomain}&dbVersion={$targetDbVersion}")
->assertStatus(400);
}

public function testSetWikiDbVersionForDomainMissingDbVersion() {
$wikiDomain = 'coffeebase.wikibase.cloud';

$this->createWiki($wikiDomain, self::VALID_WIKI_DB_VERSION_STRING_139);

$this->postJson("{$this->routeSetDbVersion}?domain={$wikiDomain}")
->assertStatus(422);
}

public function testSetWikiDbVersionForDomainMissingWikiDomain() {
$targetDbVersion = self::VALID_WIKI_DB_VERSION_STRING_143;
$wikiDomain = 'coffeebase.wikibase.cloud';

$this->createWiki($wikiDomain, self::VALID_WIKI_DB_VERSION_STRING_139);

$this->postJson("{$this->routeSetDbVersion}?dbVersion={$targetDbVersion}")
->assertStatus(422);
}

public function testGetWikiForDomainMissingWikiDomain() {
$this->getJson("{$this->routeGetWikiForDomain}")
->assertStatus(422);
}

public function testGetWikiForDomainWikiNotFound() {
$this->getJson("{$this->routeGetWikiForDomain}?domain=somewiki")
->assertStatus(404);
}
}
Loading