44
55use Illuminate \Support \Arr ;
66use Pterodactyl \Models \Server ;
7- use GuzzleHttp \ Exception \ RequestException ;
7+ use Pterodactyl \ Models \ Allocation ;
88use Illuminate \Database \ConnectionInterface ;
99use Pterodactyl \Exceptions \DisplayException ;
10+ use Illuminate \Database \Eloquent \ModelNotFoundException ;
1011use Pterodactyl \Repositories \Wings \DaemonServerRepository ;
11- use Pterodactyl \Exceptions \Repository \RecordNotFoundException ;
12- use Pterodactyl \Contracts \Repository \ServerRepositoryInterface ;
13- use Pterodactyl \Contracts \Repository \AllocationRepositoryInterface ;
14- use Pterodactyl \Exceptions \Http \Connection \DaemonConnectionException ;
1512
1613class BuildModificationService
1714{
18- /**
19- * @var \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface
20- */
21- private $ allocationRepository ;
22-
2315 /**
2416 * @var \Illuminate\Database\ConnectionInterface
2517 */
@@ -30,11 +22,6 @@ class BuildModificationService
3022 */
3123 private $ daemonServerRepository ;
3224
33- /**
34- * @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface
35- */
36- private $ repository ;
37-
3825 /**
3926 * @var \Pterodactyl\Services\Servers\ServerConfigurationStructureService
4027 */
@@ -43,23 +30,17 @@ class BuildModificationService
4330 /**
4431 * BuildModificationService constructor.
4532 *
46- * @param \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface $allocationRepository
4733 * @param \Pterodactyl\Services\Servers\ServerConfigurationStructureService $structureService
4834 * @param \Illuminate\Database\ConnectionInterface $connection
4935 * @param \Pterodactyl\Repositories\Wings\DaemonServerRepository $daemonServerRepository
50- * @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
5136 */
5237 public function __construct (
53- AllocationRepositoryInterface $ allocationRepository ,
5438 ServerConfigurationStructureService $ structureService ,
5539 ConnectionInterface $ connection ,
56- DaemonServerRepository $ daemonServerRepository ,
57- ServerRepositoryInterface $ repository
40+ DaemonServerRepository $ daemonServerRepository
5841 ) {
59- $ this ->allocationRepository = $ allocationRepository ;
6042 $ this ->daemonServerRepository = $ daemonServerRepository ;
6143 $ this ->connection = $ connection ;
62- $ this ->repository = $ repository ;
6344 $ this ->structureService = $ structureService ;
6445 }
6546
@@ -70,9 +51,8 @@ public function __construct(
7051 * @param array $data
7152 * @return \Pterodactyl\Models\Server
7253 *
54+ * @throws \Throwable
7355 * @throws \Pterodactyl\Exceptions\DisplayException
74- * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
75- * @throws \Pterodactyl\Exceptions\Model\DataValidationException
7656 */
7757 public function handle (Server $ server , array $ data )
7858 {
@@ -82,48 +62,35 @@ public function handle(Server $server, array $data)
8262
8363 if (isset ($ data ['allocation_id ' ]) && $ data ['allocation_id ' ] != $ server ->allocation_id ) {
8464 try {
85- $ this ->allocationRepository ->findFirstWhere ([
86- ['id ' , '= ' , $ data ['allocation_id ' ]],
87- ['server_id ' , '= ' , $ server ->id ],
88- ]);
89- } catch (RecordNotFoundException $ ex ) {
90- throw new DisplayException (trans ('admin/server.exceptions.default_allocation_not_found ' ));
65+ Allocation::query ()->where ('id ' , $ data ['allocation_id ' ])->where ('server_id ' , $ server ->id )->firstOrFail ();
66+ } catch (ModelNotFoundException $ ex ) {
67+ throw new DisplayException ('The requested default allocation is not currently assigned to this server. ' );
9168 }
9269 }
9370
94- /* @var \Pterodactyl\Models\Server $server */
95- $ server = $ this ->repository ->withFreshModel ()->update ($ server ->id , [
96- 'oom_disabled ' => array_get ($ data , 'oom_disabled ' ),
97- 'memory ' => array_get ($ data , 'memory ' ),
98- 'swap ' => array_get ($ data , 'swap ' ),
99- 'io ' => array_get ($ data , 'io ' ),
100- 'cpu ' => array_get ($ data , 'cpu ' ),
101- 'threads ' => array_get ($ data , 'threads ' ),
102- 'disk ' => array_get ($ data , 'disk ' ),
103- 'allocation_id ' => array_get ($ data , 'allocation_id ' ),
104- 'database_limit ' => array_get ($ data , 'database_limit ' , 0 ) ?? null ,
105- 'allocation_limit ' => array_get ($ data , 'allocation_limit ' , 0 ) ?? null ,
106- 'backup_limit ' => array_get ($ data , 'backup_limit ' , 0 ) ?? null ,
107- ]);
71+ // If any of these values are passed through in the data array go ahead and set
72+ // them correctly on the server model.
73+ $ merge = Arr::only ($ data , ['oom_disabled ' , 'memory ' , 'swap ' , 'io ' , 'cpu ' , 'threads ' , 'disk ' , 'allocation_id ' ]);
74+
75+ $ server ->forceFill (array_merge ($ merge , [
76+ 'database_limit ' => Arr::get ($ data , 'database_limit ' , 0 ) ?? null ,
77+ 'allocation_limit ' => Arr::get ($ data , 'allocation_limit ' , 0 ) ?? null ,
78+ 'backup_limit ' => Arr::get ($ data , 'backup_limit ' , 0 ) ?? 0 ,
79+ ]))->saveOrFail ();
80+
81+ $ server = $ server ->fresh ();
10882
10983 $ updateData = $ this ->structureService ->handle ($ server );
11084
111- try {
112- $ this ->daemonServerRepository
113- ->setServer ($ server )
114- ->update (Arr::only ($ updateData , ['build ' ]));
85+ $ this ->daemonServerRepository ->setServer ($ server )->update ($ updateData ['build ' ] ?? []);
11586
116- $ this ->connection ->commit ();
117- } catch (RequestException $ exception ) {
118- throw new DaemonConnectionException ($ exception );
119- }
87+ $ this ->connection ->commit ();
12088
12189 return $ server ;
12290 }
12391
12492 /**
125- * Process the allocations being assigned in the data and ensure they
126- * are available for a server.
93+ * Process the allocations being assigned in the data and ensure they are available for a server.
12794 *
12895 * @param \Pterodactyl\Models\Server $server
12996 * @param array $data
@@ -132,55 +99,53 @@ public function handle(Server $server, array $data)
13299 */
133100 private function processAllocations (Server $ server , array &$ data )
134101 {
135- $ firstAllocationId = null ;
136-
137- if (! array_key_exists ('add_allocations ' , $ data ) && ! array_key_exists ('remove_allocations ' , $ data )) {
102+ if (empty ($ data ['add_allocations ' ]) && empty ($ data ['remove_allocations ' ])) {
138103 return ;
139104 }
140105
141- // Handle the addition of allocations to this server.
142- if (array_key_exists ('add_allocations ' , $ data ) && ! empty ($ data ['add_allocations ' ])) {
143- $ unassigned = $ this ->allocationRepository ->getUnassignedAllocationIds ($ server ->node_id );
106+ // Handle the addition of allocations to this server. Only assign allocations that are not currently
107+ // assigned to a different server, and only allocations on the same node as the server.
108+ if (! empty ($ data ['add_allocations ' ])) {
109+ $ query = Allocation::query ()
110+ ->where ('node_id ' , $ server ->node_id )
111+ ->whereIn ('id ' , $ data ['add_allocations ' ])
112+ ->whereNull ('server_id ' );
144113
145- $ updateIds = [];
146- foreach ($ data ['add_allocations ' ] as $ allocation ) {
147- if (! in_array ($ allocation , $ unassigned )) {
148- continue ;
149- }
150-
151- $ firstAllocationId = $ firstAllocationId ?? $ allocation ;
152- $ updateIds [] = $ allocation ;
153- }
114+ // Keep track of all the allocations we're just now adding so that we can use the first
115+ // one to reset the default allocation to.
116+ $ freshlyAllocated = $ query ->pluck ('id ' )->first ();
154117
155- if (! empty ($ updateIds )) {
156- $ this ->allocationRepository ->updateWhereIn ('id ' , $ updateIds , ['server_id ' => $ server ->id ]);
157- }
118+ $ query ->update (['server_id ' => $ server ->id ]);
158119 }
159120
160- // Handle removal of allocations from this server.
161- if (array_key_exists ('remove_allocations ' , $ data ) && ! empty ($ data ['remove_allocations ' ])) {
162- $ assigned = $ server ->allocations ->pluck ('id ' )->toArray ();
163-
164- $ updateIds = [];
121+ if (! empty ($ data ['remove_allocations ' ])) {
165122 foreach ($ data ['remove_allocations ' ] as $ allocation ) {
166- if (! in_array ($ allocation , $ assigned )) {
167- continue ;
168- }
169-
170- if ($ allocation == $ data ['allocation_id ' ]) {
171- if (is_null ($ firstAllocationId )) {
172- throw new DisplayException (trans ('admin/server.exceptions.no_new_default_allocation ' ));
123+ // If we are attempting to remove the default allocation for the server, see if we can reassign
124+ // to the first provided value in add_allocations. If there is no new first allocation then we
125+ // will throw an exception back.
126+ if ($ allocation === ($ data ['allocation_id ' ] ?? $ server ->allocation_id )) {
127+ if (empty ($ freshlyAllocated )) {
128+ throw new DisplayException (
129+ 'You are attempting to delete the default allocation for this server but there is no fallback allocation to use. '
130+ );
173131 }
174132
175- $ data ['allocation_id ' ] = $ firstAllocationId ;
133+ // Update the default allocation to be the first allocation that we are creating.
134+ $ data ['allocation_id ' ] = $ freshlyAllocated ;
176135 }
177-
178- $ updateIds [] = $ allocation ;
179136 }
180137
181- if (! empty ($ updateIds )) {
182- $ this ->allocationRepository ->updateWhereIn ('id ' , $ updateIds , ['server_id ' => null ]);
183- }
138+ // Remove any of the allocations we got that are currently assigned to this server on
139+ // this node. Also set the notes to null, otherwise when re-allocated to a new server those
140+ // notes will be carried over.
141+ Allocation::query ()->where ('node_id ' , $ server ->node_id )
142+ ->where ('server_id ' , $ server ->id )
143+ // Only remove the allocations that we didn't also attempt to add to the server...
144+ ->whereIn ('id ' , array_diff ($ data ['remove_allocations ' ], $ data ['add_allocations ' ] ?? []))
145+ ->update ([
146+ 'notes ' => null ,
147+ 'server_id ' => null ,
148+ ]);
184149 }
185150 }
186151}
0 commit comments