diff --git a/app/Http/Controllers/API/AuthController.php b/app/Http/Controllers/API/AuthController.php index 638a0afd..613f872f 100644 --- a/app/Http/Controllers/API/AuthController.php +++ b/app/Http/Controllers/API/AuthController.php @@ -115,7 +115,7 @@ class AuthController extends BaseController * @Post("/validate") * @Versions({"v1"}) * @Request(headers={"Authorization": "Bearer "}) - * @Response(204); + * @Response(204) */ public function postValidate(Request $request) { return $this->response->noContent(); diff --git a/app/Http/Controllers/API/UserController.php b/app/Http/Controllers/API/UserController.php index f4f3cf25..e3cc7d9d 100644 --- a/app/Http/Controllers/API/UserController.php +++ b/app/Http/Controllers/API/UserController.php @@ -4,8 +4,11 @@ namespace Pterodactyl\Http\Controllers\API; use Illuminate\Http\Request; +use Dingo\Api\Exception\StoreResourceFailedException; + use Pterodactyl\Transformers\UserTransformer; use Pterodactyl\Models; +use Pterodactyl\Repositories\UserRepository; /** * @Resource("Users", uri="/users") @@ -21,7 +24,7 @@ class UserController extends BaseController * @Get("/{?page}") * @Versions({"v1"}) * @Parameters({ - * @Parameter("page", type="integer", description="The page of results to view.", default=1) + * @Parameter("page", type="integer", description="The page of results to view.", default=1) * }) * @Response(200) */ @@ -39,8 +42,8 @@ class UserController extends BaseController * @Get("/{id}/{fields}") * @Versions({"v1"}) * @Parameters({ - * @Parameter("id", type="integer", required=true, description="The ID of the user to get information on."), - * @Parameter("fields", type="string", required=false, description="A comma delimidated list of fields to include.") + * @Parameter("id", type="integer", required=true, description="The ID of the user to get information on."), + * @Parameter("fields", type="string", required=false, description="A comma delimidated list of fields to include.") * }) * @Response(200) */ @@ -59,4 +62,82 @@ class UserController extends BaseController return $query->first(); } + /** + * Create a New User + * + * @Post("/") + * @Versions({"v1"}) + * @Transaction({ + * @Request({ + * "email": "foo@example.com", + * "password": "foopassword", + * "admin": false + * }, headers={"Authorization": "Bearer "}), + * @Response(200, body={"id": 1}), + * @Response(422, body{ + * "message": "A validation error occured.", + * "errors": { + * "email": ["The email field is required."], + * "password": ["The password field is required."], + * "admin": ["The admin field is required."] + * }, + * "status_code": 422 + * }) + * }) + */ + public function postUsers(Request $request) + { + try { + $user = new UserRepository; + $create = $user->create($request->input('email'), $request->input('password'), $request->input('admin')); + return [ 'id' => $create ]; + } catch (\Pterodactyl\Exceptions\DisplayValidationException $ex) { + throw new StoreResourceFailedException('A validation error occured.', json_decode($ex->getMessage(), true)); + } catch (\Exception $ex) { + throw new StoreResourceFailedException('Unable to create a user on the system due to an error.'); + } + } + + /** + * Update an Existing User + * + * The data sent in the request will be used to update the existing user on the system. + * + * @Patch("/{id}") + * @Versions({"v1"}) + * @Transaction({ + * @Request({ + * "email": "new@email.com" + * }, headers={"Authorization": "Bearer "}), + * @Response(200, body={"email": "new@email.com"}), + * @Response(422) + * }) + * @Parameters({ + * @Parameter("id", type="integer", required=true, description="The ID of the user to modify.") + * }) + */ + public function patchUser(Request $request, $id) + { + // + } + + /** + * Delete a User + * + * @Delete("/{id}") + * @Versions({"v1"}) + * @Transaction({ + * @Request(headers={"Authorization": "Bearer "}), + * @Response(204), + * @Response(422) + * }) + * @Parameters({ + * @Parameter("id", type="integer", required=true, description="The ID of the user to delete.") + * }) + */ + public function deleteUser(Request $request, $id) + { + // + } + } diff --git a/app/Http/Controllers/Admin/AccountsController.php b/app/Http/Controllers/Admin/AccountsController.php index 813162a7..77a82d9f 100644 --- a/app/Http/Controllers/Admin/AccountsController.php +++ b/app/Http/Controllers/Admin/AccountsController.php @@ -62,27 +62,18 @@ class AccountsController extends Controller public function postNew(Request $request) { - $this->validate($request, [ - 'email' => 'required|email|unique:users,email', - 'password' => 'required|confirmed|regex:((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})' - ]); - try { $user = new UserRepository; $userid = $user->create($request->input('username'), $request->input('email'), $request->input('password')); - - if (!$userid) { - throw new \Exception('Unable to create user, response was not an integer.'); - } - Alert::success('Account has been successfully created.')->flash(); return redirect()->route('admin.accounts.view', ['id' => $userid]); - } catch (\Exception $e) { - Log::error($e); + } catch (\Pterodactyl\Exceptions\DisplayValidationException $ex) { + return redirect()->route('admin.nodes.view', $id)->withErrors(json_decode($e->getMessage()))->withInput(); + } catch (\Exception $ex) { + Log::error($ex); Alert::danger('An error occured while attempting to add a new user. ' . $e->getMessage())->flash(); return redirect()->route('admin.accounts.new'); } - } public function postUpdate(Request $request) diff --git a/app/Http/Routes/APIRoutes.php b/app/Http/Routes/APIRoutes.php index 3525e6cd..58157d8a 100644 --- a/app/Http/Routes/APIRoutes.php +++ b/app/Http/Routes/APIRoutes.php @@ -36,12 +36,16 @@ class APIRoutes 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@getUsers' ]); + $api->post('users', [ + 'as' => 'api.users.post', + 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@postUsers' + ]); + $api->get('users/{id}/{fields?}', [ 'as' => 'api.users.view', 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@getUserByID' ]); - }); } diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index adffbf30..aa633d39 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -2,11 +2,14 @@ namespace Pterodactyl\Repositories; +use Validator; use Hash; use Pterodactyl\Models\User; use Pterodactyl\Services\UuidService; +use Pterodactyl\Exceptions\DisplayValidationException; + class UserRepository { @@ -22,16 +25,39 @@ class UserRepository * @param string $password An unhashed version of the user's password. * @return bool|integer */ - public function create($email, $password) + public function create($email, $password, $admin = false) { + + $validator = Validator::make([ + 'email' => $email, + 'password' => $password, + 'admin' => $admin + ], [ + 'email' => 'required|email|unique:users,email', + 'password' => 'required|regex:((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})', + 'admin' => 'required|boolean' + ]); + + // Run validator, throw catchable and displayable exception if it fails. + // Exception includes a JSON result of failed validation rules. + if ($validator->fails()) { + throw new DisplayValidationException($validator->errors()); + } + $user = new User; $uuid = new UuidService; $user->uuid = $uuid->generate('users', 'uuid'); $user->email = $email; $user->password = Hash::make($password); + $user->root_admin = ($admin) ? 1 : 0; - return ($user->save()) ? $user->id : false; + try { + $user->save(); + return $user->id; + } catch (\Exception $ex) { + throw $e; + } } /**