2626
2727use DB ;
2828use Crypt ;
29+ use Config ;
2930use Validator ;
3031use Pterodactyl \Models ;
3132use Pterodactyl \Exceptions \DisplayException ;
32- use Illuminate \Database \Capsule \Manager as Capsule ;
3333use Pterodactyl \Exceptions \DisplayValidationException ;
3434
3535class DatabaseRepository
3636{
3737 /**
38- * Adds a new database to a given database server.
38+ * Adds a new database to a specified database host server.
39+ *
3940 * @param int $server Id of the server to add a database for.
4041 * @param array $options Array of options for creating that database.
42+ *
43+ * @throws \Pterodactyl\Exceptions\DisplayException
44+ * @throws \Pterodactyl\Exceptions\DisplayValidationException
45+ * @throws \Exception
4146 * @return void
4247 */
43- public function create ($ server , $ options )
48+ public function create ($ server , $ data )
4449 {
4550 $ server = Models \Server::findOrFail ($ server );
46- $ validator = Validator::make ($ options , [
47- 'db_server ' => 'required|exists:database_servers,id ' ,
51+
52+ $ validator = Validator::make ($ data , [
53+ 'host ' => 'required|exists:database_servers,id ' ,
4854 'database ' => 'required|regex:/^\w{1,100}$/ ' ,
49- 'remote ' => 'required|regex:/^[0-9%.]{1,15}$/ ' ,
55+ 'connection ' => 'required|regex:/^[0-9%.]{1,15}$/ ' ,
5056 ]);
5157
5258 if ($ validator ->fails ()) {
5359 throw new DisplayValidationException ($ validator ->errors ());
5460 }
5561
62+ $ host = Models \DatabaseServer::findOrFail ($ data ['host ' ]);
5663 DB ::beginTransaction ();
64+
5765 try {
58- $ db = new Models \Database ;
59- $ db ->fill ([
66+ $ database = Models \Database::firstOrNew ([
6067 'server_id ' => $ server ->id ,
61- 'db_server ' => $ options ['db_server ' ],
62- 'database ' => "s {$ server ->id }_ {$ options ['database ' ]}" ,
63- 'username ' => $ server ->uuidShort . '_ ' . str_random (7 ),
64- 'remote ' => $ options ['remote ' ],
65- 'password ' => Crypt::encrypt (str_random (20 )),
68+ 'db_server ' => $ data ['host ' ],
69+ 'database ' => sprintf ('s%d_%s ' , $ server ->id , $ data ['database ' ]),
6670 ]);
67- $ db ->save ();
6871
69- // Contact Remote
70- $ dbr = Models \DatabaseServer::findOrFail ($ options ['db_server ' ]);
72+ if ($ database ->exists ) {
73+ throw new DisplayException ('A database with those details already exists in the system. ' );
74+ }
7175
72- $ capsule = new Capsule ;
73- $ capsule ->addConnection ([
74- 'driver ' => 'mysql ' ,
75- 'host ' => $ dbr ->host ,
76- 'port ' => $ dbr ->port ,
77- 'database ' => 'mysql ' ,
78- 'username ' => $ dbr ->username ,
79- 'password ' => Crypt::decrypt ($ dbr ->password ),
80- 'charset ' => 'utf8 ' ,
81- 'collation ' => 'utf8_unicode_ci ' ,
82- 'prefix ' => '' ,
83- 'options ' => [
84- \PDO ::ATTR_TIMEOUT => 3 ,
85- ],
86- ]);
76+ $ database ->username = sprintf ('s%d_%s ' , $ server ->id , str_random (10 ));
77+ $ database ->remote = $ data ['connection ' ];
78+ $ database ->password = Crypt::encrypt (str_random (20 ));
8779
88- $ capsule -> setAsGlobal ();
80+ $ database -> save ();
8981 } catch (\Exception $ ex ) {
9082 DB ::rollBack ();
91- throw new DisplayException ( ' There was an error while connecting to the Database Host Server. Please check the error logs. ' , $ ex) ;
83+ throw $ ex ;
9284 }
9385
86+ Config::set ('database.connections.dynamic ' , [
87+ 'driver ' => 'mysql ' ,
88+ 'host ' => $ host ->host ,
89+ 'port ' => $ host ->port ,
90+ 'database ' => 'mysql ' ,
91+ 'username ' => $ host ->username ,
92+ 'password ' => Crypt::decrypt ($ host ->password ),
93+ 'charset ' => 'utf8 ' ,
94+ 'collation ' => 'utf8_unicode_ci ' ,
95+ ]);
96+
9497 try {
95- Capsule::statement ('CREATE DATABASE ` ' . $ db ->database . '` ' );
96- Capsule::statement ('CREATE USER ` ' . $ db ->username . '`@` ' . $ db ->remote . '` IDENTIFIED BY \'' . Crypt::decrypt ($ db ->password ) . '\'' );
97- Capsule::statement ('GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON ` ' . $ db ->database . '`.* TO ` ' . $ db ->username . '`@` ' . $ db ->remote . '` ' );
98- Capsule::statement ('FLUSH PRIVILEGES ' );
98+ DB ::connection ('dynamic ' )->statement (sprintf ('CREATE DATABASE IF NOT EXISTS `%s` ' , $ database ->database ));
99+ DB ::connection ('dynamic ' )->statement (sprintf (
100+ 'CREATE USER `%s`@`%s` IDENTIFIED BY \'%s \'' ,
101+ $ database ->username , $ database ->remote , Crypt::decrypt ($ database ->password )
102+ ));
103+ DB ::connection ('dynamic ' )->statement (sprintf (
104+ 'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON `%s`.* TO `%s`@`%s` ' ,
105+ $ database ->database , $ database ->username , $ database ->remote
106+ ));
107+
108+ DB ::connection ('dynamic ' )->statement ('FLUSH PRIVILEGES ' );
109+
110+ // Save Everything
99111 DB ::commit ();
100112 } catch (\Exception $ ex ) {
101113 try {
102- Capsule::statement ('DROP DATABASE ` ' . $ db ->database . '` ' );
103- Capsule::statement ('DROP USER ` ' . $ db ->username . '`@` ' . $ db ->remote . '` ' );
104- } catch (\Exception $ exi ) {
105- // ignore it, if it fails its probably
106- // because we failed to ever make the DB
107- // or the user on the system.
108- } finally {
109- DB ::rollBack ();
110- throw $ ex ;
111- }
114+ DB ::connection ('dynamic ' )->statement (sprintf ('DROP DATABASE IF EXISTS `%s` ' , $ database ->database ));
115+ DB ::connection ('dynamic ' )->statement (sprintf ('DROP USER IF EXISTS `%s`@`%s` ' , $ database ->username , $ database ->remote ));
116+ DB ::connection ('dynamic ' )->statement ('FLUSH PRIVILEGES ' );
117+ } catch (\Exception $ ex ) {}
118+
119+ DB ::rollBack ();
120+ throw $ ex ;
112121 }
113122 }
114123
@@ -118,7 +127,7 @@ public function create($server, $options)
118127 * @param string $password The new password to use for the database.
119128 * @return bool
120129 */
121- public function modifyPassword ($ id , $ password )
130+ public function password ($ id , $ password )
122131 {
123132 $ database = Models \Database::with ('host ' )->findOrFail ($ id );
124133
@@ -127,33 +136,25 @@ public function modifyPassword($id, $password)
127136 $ database ->password = Crypt::encrypt ($ password );
128137 $ database ->save ();
129138
130- $ capsule = new Capsule ;
131- $ capsule ->addConnection ([
139+ Config::set ('database.connections.dynamic ' , [
132140 'driver ' => 'mysql ' ,
133141 'host ' => $ database ->host ->host ,
134142 'port ' => $ database ->host ->port ,
135143 'database ' => 'mysql ' ,
136144 'username ' => $ database ->host ->username ,
137145 'password ' => Crypt::decrypt ($ database ->host ->password ),
138- 'charset ' => 'utf8 ' ,
146+ 'charset ' => 'utf8 ' ,
139147 'collation ' => 'utf8_unicode_ci ' ,
140- 'prefix ' => '' ,
141- 'options ' => [
142- \PDO ::ATTR_TIMEOUT => 3 ,
143- ],
144148 ]);
145149
146- $ capsule ->setAsGlobal ();
147- Capsule::statement (sprintf (
150+ DB ::connection ('dynamic ' )->statement (sprintf (
148151 'SET PASSWORD FOR `%s`@`%s` = PASSWORD( \'%s \') ' ,
149- $ database ->username ,
150- $ database ->remote ,
151- $ password
152+ $ database ->username , $ database ->remote , $ password
152153 ));
153154
154155 DB ::commit ();
155156 } catch (\Exception $ ex ) {
156- DB ::rollback ();
157+ DB ::rollBack ();
157158 throw $ ex ;
158159 }
159160 }
@@ -168,34 +169,25 @@ public function drop($id)
168169 $ database = Models \Database::with ('host ' )->findOrFail ($ id );
169170
170171 DB ::beginTransaction ();
171-
172172 try {
173- $ capsule = new Capsule ;
174- $ capsule ->addConnection ([
173+ Config::set ('database.connections.dynamic ' , [
175174 'driver ' => 'mysql ' ,
176175 'host ' => $ database ->host ->host ,
177176 'port ' => $ database ->host ->port ,
178177 'database ' => 'mysql ' ,
179178 'username ' => $ database ->host ->username ,
180179 'password ' => Crypt::decrypt ($ database ->host ->password ),
181- 'charset ' => 'utf8 ' ,
180+ 'charset ' => 'utf8 ' ,
182181 'collation ' => 'utf8_unicode_ci ' ,
183- 'prefix ' => '' ,
184- 'options ' => [
185- \PDO ::ATTR_TIMEOUT => 3 ,
186- ],
187182 ]);
188183
189- $ capsule ->setAsGlobal ();
190-
191- Capsule::statement ('DROP USER ` ' . $ database ->username . '`@` ' . $ database ->remote . '` ' );
192- Capsule::statement ('DROP DATABASE ` ' . $ database ->database . '` ' );
184+ DB ::connection ('dynamic ' )->statement (sprintf ('DROP DATABASE IF EXISTS `%s` ' , $ database ->database ));
185+ DB ::connection ('dynamic ' )->statement (sprintf ('DROP USER IF EXISTS `%s`@`%s` ' , $ database ->username , $ database ->remote ));
186+ DB ::connection ('dynamic ' )->statement ('FLUSH PRIVILEGES ' );
193187
194188 $ database ->delete ();
195189
196190 DB ::commit ();
197-
198- return true ;
199191 } catch (\Exception $ ex ) {
200192 DB ::rollback ();
201193 throw $ ex ;
@@ -243,28 +235,20 @@ public function add(array $data)
243235 }
244236
245237 DB ::beginTransaction ();
246-
247238 try {
248- $ capsule = new Capsule ;
249- $ capsule ->addConnection ([
239+ Config::set ('database.connections.dynamic ' , [
250240 'driver ' => 'mysql ' ,
251241 'host ' => $ data ['host ' ],
252242 'port ' => $ data ['port ' ],
253243 'database ' => 'mysql ' ,
254244 'username ' => $ data ['username ' ],
255245 'password ' => $ data ['password ' ],
256- 'charset ' => 'utf8 ' ,
246+ 'charset ' => 'utf8 ' ,
257247 'collation ' => 'utf8_unicode_ci ' ,
258- 'prefix ' => '' ,
259- 'options ' => [
260- \PDO ::ATTR_TIMEOUT => 3 ,
261- ],
262248 ]);
263249
264- $ capsule ->setAsGlobal ();
265-
266250 // Allows us to check that we can connect to things.
267- Capsule:: select ('SELECT 1 FROM dual ' );
251+ DB :: connection ( ' dynamic ' )-> select ('SELECT 1 FROM dual ' );
268252
269253 Models \DatabaseServer::create ([
270254 'name ' => $ data ['name ' ],
0 commit comments