33namespace Pterodactyl \Models ;
44
55use Auth ;
6- use Validator ;
6+ use DB ;
77use Debugbar ;
8+ use Validator ;
89
910use Pterodactyl \Exceptions \DisplayException ;
1011use Pterodactyl \Exceptions \AccountNotFoundException ;
11- use Pterodactyl \Models \User ;
12- use Pterodactyl \Models \Permission ;
13- use Pterodactyl \Models \Subuser ;
12+ use Pterodactyl \Exceptions \DisplayValidationException ;
13+
14+ use Pterodactyl \Models ;
15+
1416use Illuminate \Database \Eloquent \Model ;
1517
1618class Server extends Model
@@ -48,6 +50,18 @@ public function __construct()
4850 self ::$ user = Auth::user ();
4951 }
5052
53+ protected static function generateSFTPUsername ($ name )
54+ {
55+
56+ $ name = preg_replace ('/\s+/ ' , '' , $ name );
57+ if (strlen ($ name ) > 6 ) {
58+ return strtolower ('ptdl- ' . substr ($ name , 0 , 6 ) . '_ ' . str_random (5 ));
59+ }
60+
61+ return strtolower ('ptdl- ' . $ name . '_ ' . str_random ((11 - strlen ($ name ))));
62+
63+ }
64+
5165 /**
5266 * Determine if we need to change the server's daemonSecret value to
5367 * match that of the user if they are a subuser.
@@ -62,7 +76,7 @@ protected static function getUserDaemonSecret(Server $server)
6276 return $ server ->daemonSecret ;
6377 }
6478
65- $ subuser = Subuser::where ('server_id ' , $ server ->id )->where ('user_id ' , self ::$ user ->id )->first ();
79+ $ subuser = Models \ Subuser::where ('server_id ' , $ server ->id )->where ('user_id ' , self ::$ user ->id )->first ();
6680
6781 if (is_null ($ subuser )) {
6882 return null ;
@@ -87,7 +101,7 @@ public static function getUserServers()
87101 ->where ('active ' , 1 );
88102
89103 if (self ::$ user ->root_admin !== 1 ) {
90- $ query ->whereIn ('servers.id ' , Subuser::accessServers ());
104+ $ query ->whereIn ('servers.id ' , Models \ Subuser::accessServers ());
91105 }
92106
93107 return $ query ->get ();
@@ -110,7 +124,7 @@ public static function getByUUID($uuid)
110124 $ query = self ::where ('uuidShort ' , $ uuid )->where ('active ' , 1 );
111125
112126 if (self ::$ user ->root_admin !== 1 ) {
113- $ query ->whereIn ('servers.id ' , Subuser::accessServers ());
127+ $ query ->whereIn ('servers.id ' , Models \ Subuser::accessServers ());
114128 }
115129
116130 $ result = $ query ->first ();
@@ -154,7 +168,7 @@ public static function addServer(array $data)
154168 // Validate Fields
155169 $ validator = Validator::make ($ data , [
156170 'owner ' => 'required|email|exists:users,email ' ,
157- 'node ' => 'required|numeric|min:1 ' ,
171+ 'node ' => 'required|numeric|min:1|exists:nodes,id ' ,
158172 'name ' => 'required|regex:([\w -]{4,35}) ' ,
159173 'memory ' => 'required|numeric|min:1 ' ,
160174 'disk ' => 'required|numeric|min:1 ' ,
@@ -167,14 +181,60 @@ public static function addServer(array $data)
167181 'custom_image_name ' => 'required_if:use_custom_image,on ' ,
168182 ]);
169183
170- // @TODO: Have this return a JSON response.
184+ // Run validator, throw catchable and displayable exception if it fails.
185+ // Exception includes a JSON result of failed validation rules.
171186 if ($ validator ->fails ()) {
172- foreach ($ validator ->errors ()->all () as $ error ) {
173- Debugbar::info ($ error );
187+ throw new DisplayValidationException (json_encode ($ validator ->errors ()->all ()));
188+ }
189+
190+ // Get the User ID; user exists since we passed the 'exists:users,email' part of the validation
191+ $ user = Models \User::select ('id ' )->where ('email ' , $ data ['owner ' ])->first ();
192+
193+ // Verify IP & Port are a.) free and b.) assigned to the node.
194+ // We know the node exists because of 'exists:nodes,id' in the validation
195+ $ node = Models \Node::find ($ data ['node ' ]);
196+ $ allocation = Models \Allocation::where ('ip ' , $ data ['ip ' ])->where ('port ' , $ data ['port ' ])->where ('node ' , $ data ['node ' ])->whereNull ('assigned_to ' )->first ();
197+
198+ // Something failed in the query, either that combo doesn't exist, or it is in use.
199+ if (!$ allocation ) {
200+ throw new DisplayException ('The selected IP/Port combination ( ' . $ data ['ip ' ] . ': ' . $ data ['port ' ] . ') is either already in use, or unavaliable for this node. ' );
201+ }
202+
203+ // Validate those Service Option Variables
204+ // We know the service and option exists because of the validation.
205+ // We need to verify that the option exists for the service, and then check for
206+ // any required variable fields. (fields are labeled env_<env_variable>)
207+ $ option = Models \ServiceOptions::where ('id ' , $ data ['option ' ])->where ('parent_service ' , $ data ['service ' ])->first ();
208+ if (!$ option ) {
209+ throw new DisplayException ('The requested service option does not exist for the specified service. ' );
210+ }
211+
212+ // Check those Variables
213+ $ variables = Models \ServiceVariables::where ('option_id ' , $ data ['option ' ])->get ();
214+ if ($ variables ) {
215+ foreach ($ variables as $ variable ) {
216+
217+ // Is the variable required?
218+ if (!$ data ['env_ ' . $ variable ->env_variable ]) {
219+ if ($ variable ->required === 1 ) {
220+ throw new DisplayException ('A required service option variable field (env_ ' . $ variable ->env_variable . ') was missing from the request. ' );
221+ }
222+
223+ $ data ['env_ ' . $ variable ->env_variable ] = $ variable ->default_value ;
224+ continue ;
225+ }
226+
227+ // Check aganist Regex Pattern
228+ if (!is_null ($ variable ->regex ) && !preg_match ($ variable ->regex , $ data ['env_ ' . $ variable ->env_variable ])) {
229+ throw new DisplayException ('Failed to validate service option variable field (env_ ' . $ variable ->env_variable . ') aganist regex ( ' . $ variable ->regex . '). ' );
230+ }
231+
232+ continue ;
233+
174234 }
175235 }
176236
177- return ;
237+ return self :: generateSFTPUsername ( $ data [ ' name ' ]) ;
178238
179239 }
180240
0 commit comments