diff --git a/app/Helper/WikiDbVersionHelper.php b/app/Helper/WikiDbVersionHelper.php new file mode 100644 index 000000000..c1026f594 --- /dev/null +++ b/app/Helper/WikiDbVersionHelper.php @@ -0,0 +1,45 @@ + dbVersion lives. + */ + +namespace App\Helper; + +/** + * Exception thrown when a database version is not mapped in WikiDbVersionHelper. + */ +class UnknownDbVersionException extends \Exception {} + +class WikiDbVersionHelper { + /** @var array 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 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}'"); + } +} diff --git a/app/Http/Controllers/Backend/WikiController.php b/app/Http/Controllers/Backend/WikiController.php index 8fccf7781..440d441e6 100644 --- a/app/Http/Controllers/Backend/WikiController.php +++ b/app/Http/Controllers/Backend/WikiController.php @@ -2,27 +2,24 @@ namespace App\Http\Controllers\Backend; +use App\Helper\WikiDbVersionHelper; use App\Http\Controllers\Controller; use App\Wiki; use Illuminate\Http\Request; 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) { @@ -31,4 +28,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); + } } diff --git a/app/Services/MediaWikiHostResolver.php b/app/Services/MediaWikiHostResolver.php index a07e6f9a4..21fc8884b 100644 --- a/app/Services/MediaWikiHostResolver.php +++ b/app/Services/MediaWikiHostResolver.php @@ -2,6 +2,7 @@ namespace App\Services; +use App\Helper\WikiDbVersionHelper; use App\Wiki; use Exception; @@ -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 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); @@ -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(); @@ -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}'."); } diff --git a/routes/backend.php b/routes/backend.php index 478a40367..795e475a0 100644 --- a/routes/backend.php +++ b/routes/backend.php @@ -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']); }); diff --git a/tests/Helper/WikiDbVersionHelperTest.php b/tests/Helper/WikiDbVersionHelperTest.php new file mode 100644 index 000000000..c3e9402c9 --- /dev/null +++ b/tests/Helper/WikiDbVersionHelperTest.php @@ -0,0 +1,22 @@ +expectException(UnknownDbVersionException::class); + + WikiDbVersionHelper::getMwVersion('invalidDbVersion'); + } + + public function testKnownMwVersion() { + $this->assertSame( + WikiDbVersionHelper::getMwVersion('mw1.39-wbs1'), + '139' + ); + } +} diff --git a/tests/Routes/Backend/WikiControllerTest.php b/tests/Routes/Backend/WikiControllerTest.php new file mode 100644 index 000000000..a1529e0c3 --- /dev/null +++ b/tests/Routes/Backend/WikiControllerTest.php @@ -0,0 +1,92 @@ +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); + } +}