From 8c9e79721031fa915d8076844a21e487b039e0c7 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 14 Jan 2016 23:13:26 -0500 Subject: [PATCH] Finish user portion of API --- app/Http/Controllers/API/AuthController.php | 6 +-- app/Http/Controllers/API/UserController.php | 60 ++++++++++++++------- app/Http/Routes/APIRoutes.php | 14 +++-- app/Models/User.php | 2 +- app/Repositories/UserRepository.php | 51 +++++++++++++----- 5 files changed, 94 insertions(+), 39 deletions(-) diff --git a/app/Http/Controllers/API/AuthController.php b/app/Http/Controllers/API/AuthController.php index 613f872f5..2a4284a10 100644 --- a/app/Http/Controllers/API/AuthController.php +++ b/app/Http/Controllers/API/AuthController.php @@ -21,7 +21,7 @@ use Pterodactyl\Transformers\UserTransformer; use Pterodactyl\Models; /** - * @Resource("Auth", uri="/auth") + * @Resource("Auth") */ class AuthController extends BaseController { @@ -57,7 +57,7 @@ class AuthController extends BaseController * * Authenticate with the API to recieved a JSON Web Token * - * @Post("/login") + * @Post("/auth/login") * @Versions({"v1"}) * @Request({"email": "e@mail.com", "password": "soopersecret"}) * @Response(200, body={"token": ""}) @@ -112,7 +112,7 @@ class AuthController extends BaseController /** * Check if Authenticated * - * @Post("/validate") + * @Post("/auth/validate") * @Versions({"v1"}) * @Request(headers={"Authorization": "Bearer "}) * @Response(204) diff --git a/app/Http/Controllers/API/UserController.php b/app/Http/Controllers/API/UserController.php index 006d73ed0..0ab62f2c8 100644 --- a/app/Http/Controllers/API/UserController.php +++ b/app/Http/Controllers/API/UserController.php @@ -6,12 +6,14 @@ use Illuminate\Http\Request; use Dingo\Api\Exception\StoreResourceFailedException; -use Pterodactyl\Transformers\UserTransformer; use Pterodactyl\Models; +use Pterodactyl\Transformers\UserTransformer; use Pterodactyl\Repositories\UserRepository; +use Pterodactyl\Exceptions\DisplayValidationException; +use Pterodactyl\Exceptions\DisplayException; /** - * @Resource("Users", uri="/users") + * @Resource("Users") */ class UserController extends BaseController { @@ -21,7 +23,7 @@ class UserController extends BaseController * * Lists all users currently on the system. * - * @Get("/{?page}") + * @Get("/users/{?page}") * @Versions({"v1"}) * @Parameters({ * @Parameter("page", type="integer", description="The page of results to view.", default=1) @@ -39,7 +41,7 @@ class UserController extends BaseController * * Lists specific fields about a user or all fields pertaining to that user. * - * @Get("/{id}/{fields}") + * @Get("/users/{id}/{fields}") * @Versions({"v1"}) * @Parameters({ * @Parameter("id", type="integer", required=true, description="The ID of the user to get information on."), @@ -47,7 +49,7 @@ class UserController extends BaseController * }) * @Response(200) */ - public function getUserByID(Request $request, $id, $fields = null) + public function getUser(Request $request, $id, $fields = null) { $query = Models\User::where('id', $id); @@ -65,7 +67,7 @@ class UserController extends BaseController /** * Create a New User * - * @Post("/") + * @Post("/users") * @Versions({"v1"}) * @Transaction({ * @Request({ @@ -73,26 +75,30 @@ class UserController extends BaseController * "password": "foopassword", * "admin": false * }, headers={"Authorization": "Bearer "}), - * @Response(200, body={"id": 1}), - * @Response(422, body{ + * @Response(201), + * @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."] + * "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) + public function postUser(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) { + return $this->response->created(route('api.users.view', [ + 'id' => $create + ])); + } catch (DisplayValidationException $ex) { throw new StoreResourceFailedException('A validation error occured.', json_decode($ex->getMessage(), true)); + } catch (DisplayException $ex) { + throw new StoreResourceFailedException($ex->getMessage()); } catch (\Exception $ex) { throw new StoreResourceFailedException('Unable to create a user on the system due to an error.'); } @@ -103,7 +109,7 @@ class UserController extends BaseController * * The data sent in the request will be used to update the existing user on the system. * - * @Patch("/{id}") + * @Patch("/users/{id}") * @Versions({"v1"}) * @Transaction({ * @Request({ @@ -118,13 +124,23 @@ class UserController extends BaseController */ public function patchUser(Request $request, $id) { - // + try { + $user = new UserRepository; + $user->update($id, $request->all()); + return Models\User::findOrFail($id); + } catch (DisplayValidationException $ex) { + throw new StoreResourceFailedException('A validation error occured.', json_decode($ex->getMessage(), true)); + } catch (DisplayException $ex) { + throw new StoreResourceFailedException($ex->getMessage()); + } catch (\Exception $ex) { + throw new StoreResourceFailedException('Unable to create a user on the system due to an error.'); + } } /** * Delete a User * - * @Delete("/{id}") + * @Delete("/users/{id}") * @Versions({"v1"}) * @Transaction({ * @Request(headers={"Authorization": "Bearer "}), @@ -137,7 +153,15 @@ class UserController extends BaseController */ public function deleteUser(Request $request, $id) { - // + try { + $user = new UserRepository; + $user->delete($id); + return $this->response->noContent(); + } catch (DisplayException $ex) { + throw new StoreResourceFailedException($ex->getMessage()); + } catch (\Exception $ex) { + throw new StoreResourceFailedException('Unable to delete this user due to an error.'); + } } } diff --git a/app/Http/Routes/APIRoutes.php b/app/Http/Routes/APIRoutes.php index 58157d8a9..79b7db006 100644 --- a/app/Http/Routes/APIRoutes.php +++ b/app/Http/Routes/APIRoutes.php @@ -30,7 +30,6 @@ class APIRoutes }); $api->version('v1', ['middleware' => 'api.auth'], function ($api) { - $api->get('users', [ 'as' => 'api.users', 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@getUsers' @@ -38,14 +37,23 @@ class APIRoutes $api->post('users', [ 'as' => 'api.users.post', - 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@postUsers' + 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@postUser' ]); $api->get('users/{id}/{fields?}', [ 'as' => 'api.users.view', - 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@getUserByID' + 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@getUser' ]); + $api->patch('users/{id}/', [ + 'as' => 'api.users.patch', + 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@patchUser' + ]); + + $api->delete('users/{id}/', [ + 'as' => 'api.users.delete', + 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@deleteUser' + ]); }); } diff --git a/app/Models/User.php b/app/Models/User.php index 742f194bc..2ce0c6746 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -34,7 +34,7 @@ class User extends Model implements AuthenticatableContract, * * @var array */ - protected $fillable = ['name', 'email', 'password']; + protected $fillable = ['name', 'email', 'password', 'use_totp', 'totp_secret', 'language']; /** * The attributes excluded from the model's JSON form. diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index 62f690871..92f431d97 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -2,13 +2,15 @@ namespace Pterodactyl\Repositories; -use Validator; +use DB; use Hash; +use Validator; -use Pterodactyl\Models\User; +use Pterodactyl\Models; use Pterodactyl\Services\UuidService; use Pterodactyl\Exceptions\DisplayValidationException; +use Pterodactyl\Exceptions\DisplayException; class UserRepository { @@ -27,15 +29,14 @@ class UserRepository */ public function create($email, $password, $admin = false) { - $validator = Validator::make([ 'email' => $email, 'password' => $password, - 'admin' => $admin + 'root_admin' => $admin ], [ 'email' => 'required|email|unique:users,email', 'password' => 'required|regex:((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})', - 'admin' => 'required|boolean' + 'root_admin' => 'required|boolean' ]); // Run validator, throw catchable and displayable exception if it fails. @@ -44,7 +45,7 @@ class UserRepository throw new DisplayValidationException($validator->errors()); } - $user = new User; + $user = new Models\User; $uuid = new UuidService; $user->uuid = $uuid->generate('users', 'uuid'); @@ -64,16 +65,25 @@ class UserRepository * Updates a user on the panel. * * @param integer $id - * @param array $user An array of columns and their associated values to update for the user. + * @param array $data An array of columns and their associated values to update for the user. * @return boolean */ - public function update($id, array $user) + public function update($id, array $data) { - if(array_key_exists('password', $user)) { - $user['password'] = Hash::make($user['password']); + $validator = Validator::make($data, [ + 'email' => 'email|unique:users,email,' . $id, + 'password' => 'regex:((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})', + 'root_admin' => 'boolean', + 'language' => 'string|min:1|max:5', + 'use_totp' => 'boolean', + 'totp_secret' => 'size:16' + ]); + + if(array_key_exists('password', $data)) { + $user['password'] = Hash::make($data['password']); } - return User::find($id)->update($user); + return Models\User::find($id)->update($data); } /** @@ -84,9 +94,22 @@ class UserRepository */ public function delete($id) { - // @TODO cannot delete user with associated servers! - // clean up subusers! - return User::destroy($id); + if(Models\Server::where('owner', $id)->count() > 0) { + throw new DisplayException('Cannot delete a user with active servers attached to thier account.'); + } + + DB::beginTransaction(); + + Models\Permission::where('user_id', $id)->delete(); + Models\Subuser::where('user_id', $id)->delete(); + Models\User::destroy($id); + + try { + DB::commit(); + return true; + } catch (\Exception $ex) { + throw $ex; + } } }