Skip to content

Commit 7013d10

Browse files
committed
Add basic support for per-server databases
Still missing ability to define database servers
1 parent 76049c5 commit 7013d10

File tree

8 files changed

+503
-1
lines changed

8 files changed

+503
-1
lines changed

app/Http/Controllers/Admin/ServersController.php

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
use Pterodactyl\Models;
3131
use Pterodactyl\Repositories\ServerRepository;
32+
use Pterodactyl\Repositories\DatabaseRepository;
3233

3334
use Pterodactly\Exceptions\DisplayException;
3435
use Pterodactly\Exceptions\DisplayValidationException;
@@ -95,7 +96,12 @@ public function getView(Request $request, $id)
9596
->join('server_variables', 'server_variables.variable_id', '=', 'service_variables.id')
9697
->where('service_variables.option_id', $server->option)
9798
->where('server_variables.server_id', $server->id)
98-
->get()
99+
->get(),
100+
'databases' => Models\Database::select('databases.*', 'database_servers.host as a_host', 'database_servers.port as a_port')
101+
->where('server', $server->id)
102+
->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
103+
->get(),
104+
'db_servers' => Models\DatabaseServer::all()
99105
]);
100106
}
101107

@@ -375,4 +381,42 @@ public function postUpdateServerStartup(Request $request, $id)
375381
}
376382
}
377383

384+
public function postDatabase(Request $request, $id)
385+
{
386+
try {
387+
$repo = new DatabaseRepository;
388+
$repo->create($id, $request->except([
389+
'_token'
390+
]));
391+
Alert::success('Added new database to this server.')->flash();
392+
} catch (\Pterodactyl\Exceptions\DisplayValidationException $ex) {
393+
return redirect()->route('admin.servers.view', [
394+
'id' => $id,
395+
'tab' => 'tab_database'
396+
])->withInput()->withErrors(json_decode($ex->getMessage()))->withInput();
397+
} catch (\Exception $ex) {
398+
Log::error($ex);
399+
Alert::danger('An exception occured while attempting to add a new database for this server.')->flash();
400+
}
401+
402+
return redirect()->route('admin.servers.view', [
403+
'id' => $id,
404+
'tab' => 'tab_database'
405+
])->withInput();
406+
}
407+
408+
public function deleteDatabase(Request $request, $id, $database)
409+
{
410+
try {
411+
$repo = new DatabaseRepository;
412+
$repo->drop($database);
413+
return response('', 204);
414+
} catch (\Exception $ex) {
415+
Log::error($ex);
416+
return response()->json([
417+
'error' => 'An exception occured while attempting to delete this database.'
418+
], 500);
419+
}
420+
}
421+
378422
}

app/Http/Routes/AdminRoutes.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,16 @@ public function map(Router $router) {
152152
'uses' => 'Admin\ServersController@getView'
153153
]);
154154

155+
// Database Stuffs
156+
$router->post('/view/{id}/database', [
157+
'as' => 'admin.servers.database',
158+
'uses' => 'Admin\ServersController@postDatabase'
159+
]);
160+
161+
$router->delete('/view/{id}/database/{database}', [
162+
'uses' => 'Admin\ServersController@deleteDatabase'
163+
]);
164+
155165
// Change Server Details
156166
$router->post('/view/{id}/details', [
157167
'uses' => 'Admin\ServersController@postUpdateServerDetails'

app/Models/Database.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
namespace Pterodactyl\Models;
25+
26+
use Illuminate\Database\Eloquent\Model;
27+
28+
class Database extends Model
29+
{
30+
31+
/**
32+
* The table associated with the model.
33+
*
34+
* @var string
35+
*/
36+
protected $table = 'databases';
37+
38+
/**
39+
* The attributes excluded from the model's JSON form.
40+
*
41+
* @var array
42+
*/
43+
protected $hidden = ['password'];
44+
45+
/**
46+
* Fields that are not mass assignable.
47+
*
48+
* @var array
49+
*/
50+
protected $guarded = ['id', 'created_at', 'updated_at'];
51+
52+
/**
53+
* Cast values to correct type.
54+
*
55+
* @var array
56+
*/
57+
protected $casts = [
58+
'server' => 'integer',
59+
'db_server' => 'integer',
60+
];
61+
62+
}

app/Models/DatabaseServer.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
namespace Pterodactyl\Models;
25+
26+
use Illuminate\Database\Eloquent\Model;
27+
28+
class DatabaseServer extends Model
29+
{
30+
31+
/**
32+
* The table associated with the model.
33+
*
34+
* @var string
35+
*/
36+
protected $table = 'database_servers';
37+
38+
/**
39+
* The attributes excluded from the model's JSON form.
40+
*
41+
* @var array
42+
*/
43+
protected $hidden = ['password'];
44+
45+
/**
46+
* Fields that are not mass assignable.
47+
*
48+
* @var array
49+
*/
50+
protected $guarded = ['id', 'created_at', 'updated_at'];
51+
52+
/**
53+
* Cast values to correct type.
54+
*
55+
* @var array
56+
*/
57+
protected $casts = [
58+
'id' => 'integer',
59+
];
60+
61+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
namespace Pterodactyl\Repositories;
25+
26+
use Crypt;
27+
use DB;
28+
use Validator;
29+
30+
use Pterodactyl\Models;
31+
use Pterodactyl\Exceptions\DisplayException;
32+
use Pterodactyl\Exceptions\DisplayValidationException;
33+
34+
use Illuminate\Database\Capsule\Manager as Capsule;
35+
36+
class DatabaseRepository {
37+
38+
/**
39+
* Adds a new database to a given database server.
40+
* @param int $server Id of the server to add a database for.
41+
* @param array $options Array of options for creating that database.
42+
* @return void
43+
*/
44+
public function create($server, $options)
45+
{
46+
$server = Models\Server::findOrFail($server);
47+
$validator = Validator::make($options, [
48+
'db_server' => 'required|exists:database_servers,id',
49+
'database' => 'required|regex:/^\w{1,100}$/',
50+
'remote' => 'required|regex:/^[0-9%.]{1,15}$/',
51+
]);
52+
53+
if ($validator->fails()) {
54+
throw new DisplayValidationException($validator->errors());
55+
}
56+
57+
DB::beginTransaction();
58+
59+
$db = new Models\Database;
60+
$db->fill([
61+
'server' => $server->id,
62+
'db_server' => $options['db_server'],
63+
'database' => $server->uuidShort . '_' . $options['database'],
64+
'username' => $server->uuidShort . '_' . str_random(7),
65+
'remote' => $options['remote'],
66+
'password' => Crypt::encrypt(str_random(20))
67+
]);
68+
$db->save();
69+
70+
// Contact Remote
71+
$dbr = Models\DatabaseServer::findOrFail($options['db_server']);
72+
73+
try {
74+
75+
$capsule = new Capsule;
76+
$capsule->addConnection([
77+
'driver' => 'mysql',
78+
'host' => $dbr->host,
79+
'port' => $dbr->port,
80+
'database' => 'mysql',
81+
'username' => $dbr->username,
82+
'password' => Crypt::decrypt($dbr->password),
83+
'charset' => 'utf8',
84+
'collation' => 'utf8_unicode_ci',
85+
'prefix' => ''
86+
]);
87+
88+
$capsule->setAsGlobal();
89+
90+
Capsule::statement('CREATE DATABASE ' . $db->database);
91+
Capsule::statement('CREATE USER \'' . $db->username . '\'@\'' . $db->remote . '\' IDENTIFIED BY \'' . Crypt::decrypt($db->password) . '\'');
92+
Capsule::statement('GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON ' . $db->database . '.* TO \'' . $db->username . '\'@\'' . $db->remote . '\'');
93+
Capsule::statement('FLUSH PRIVILEGES');
94+
95+
DB::commit();
96+
return true;
97+
} catch (\Exception $ex) {
98+
DB::rollback();
99+
throw $ex;
100+
}
101+
}
102+
103+
/**
104+
* Drops a database from the associated MySQL Server
105+
* @param int $database The ID of the database to drop.
106+
* @return boolean
107+
*/
108+
public function drop($database)
109+
{
110+
$db = Models\Database::findOrFail($database);
111+
$dbr = Models\DatabaseServer::findOrFail($db->db_server);
112+
113+
try {
114+
115+
DB::beginTransaction();
116+
117+
$capsule = new Capsule;
118+
$capsule->addConnection([
119+
'driver' => 'mysql',
120+
'host' => $dbr->host,
121+
'port' => $dbr->port,
122+
'database' => 'mysql',
123+
'username' => $dbr->username,
124+
'password' => Crypt::decrypt($dbr->password),
125+
'charset' => 'utf8',
126+
'collation' => 'utf8_unicode_ci',
127+
'prefix' => ''
128+
]);
129+
130+
$capsule->setAsGlobal();
131+
132+
Capsule::statement('DROP USER \'' . $db->username . '\'@\'' . $db->remote . '\'');
133+
Capsule::statement('DROP DATABASE ' . $db->database);
134+
135+
$db->delete();
136+
137+
DB::commit();
138+
return true;
139+
} catch (\Exception $ex) {
140+
DB::rollback();
141+
throw $ex;
142+
}
143+
144+
}
145+
146+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
use Illuminate\Database\Schema\Blueprint;
4+
use Illuminate\Database\Migrations\Migration;
5+
6+
class AddDatabasesTables extends Migration
7+
{
8+
/**
9+
* Run the migrations.
10+
*
11+
* @return void
12+
*/
13+
public function up()
14+
{
15+
Schema::create('databases', function (Blueprint $table) {
16+
$table->increments('id');
17+
$table->integer('server')->unsigned();
18+
$table->integer('db_server')->unsigned();
19+
$table->string('database')->unique();
20+
$table->string('username')->unique();
21+
$table->string('remote')->default('%');
22+
$table->text('password');
23+
$table->timestamps();
24+
});
25+
}
26+
27+
/**
28+
* Reverse the migrations.
29+
*
30+
* @return void
31+
*/
32+
public function down()
33+
{
34+
Schema::drop('databases');
35+
}
36+
}

0 commit comments

Comments
 (0)