From e35fa9b85a8116c791c052853e568a0e18c318e4 Mon Sep 17 00:00:00 2001 From: printempw Date: Sun, 23 Oct 2016 11:41:52 +0800 Subject: [PATCH] refactor models --- app/Http/Controllers/AdminController.php | 41 +-- app/Http/Controllers/AuthController.php | 148 ++++---- app/Http/Controllers/ClosetController.php | 5 +- app/Http/Controllers/HomeController.php | 18 +- app/Http/Controllers/PlayerController.php | 7 +- app/Http/Controllers/SkinlibController.php | 20 +- app/Http/Controllers/TextureController.php | 11 +- app/Http/Controllers/UserController.php | 8 +- app/Http/Kernel.php | 1 + app/Http/Middleware/CheckAdminMiddleware.php | 2 +- app/Http/Middleware/CheckAuthenticated.php | 17 +- .../Middleware/CheckPlayerExistMiddleware.php | 2 +- app/Http/Middleware/CheckSessionUserValid.php | 35 ++ app/Http/Middleware/EncryptCookies.php | 12 +- .../Middleware/RedirectIfAuthenticated.php | 5 +- app/Models/Closet.php | 41 ++- app/Models/Player.php | 52 ++- app/Models/Texture.php | 4 +- app/Models/User.php | 348 +++++++++++------- app/Providers/AppServiceProvider.php | 6 +- app/Services/Repositories/UserRepository.php | 58 +++ app/helpers.php | 20 + resources/views/admin/index.tpl | 4 +- resources/views/admin/master.tpl | 2 +- resources/views/admin/users.tpl | 2 +- resources/views/skinlib/item.tpl | 2 +- resources/views/skinlib/show.tpl | 8 +- resources/views/user/closet.tpl | 2 +- resources/views/user/index.tpl | 6 +- resources/views/user/master.tpl | 2 +- resources/views/user/player.tpl | 2 +- resources/views/user/profile.tpl | 2 +- resources/views/vendor/breadcrumb.tpl | 2 +- 33 files changed, 568 insertions(+), 327 deletions(-) create mode 100644 app/Http/Middleware/CheckSessionUserValid.php create mode 100644 app/Services/Repositories/UserRepository.php diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 41f6b961..772a0dfd 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -7,14 +7,13 @@ use Utils; use App\Models\User; use App\Models\Player; use App\Models\Texture; -use App\Models\UserModel; use Illuminate\Http\Request; use App\Services\PluginManager; use App\Exceptions\PrettyPageException; +use App\Services\Repositories\UserRepository; class AdminController extends Controller { - public function index() { return view('admin.index'); @@ -128,11 +127,11 @@ class AdminController extends Controller $q = $request->input('q', ''); if ($filter == "") { - $users = UserModel::orderBy('uid'); + $users = User::orderBy('uid'); } elseif ($filter == "email") { - $users = UserModel::like('email', $q)->orderBy('uid'); + $users = User::like('email', $q)->orderBy('uid'); } elseif ($filter == "nickname") { - $users = UserModel::like('nickname', $q)->orderBy('uid'); + $users = User::like('nickname', $q)->orderBy('uid'); } $total_pages = ceil($users->count() / 30); @@ -181,7 +180,7 @@ class AdminController extends Controller * @param Request $request * @return void */ - public function userAjaxHandler(Request $request) + public function userAjaxHandler(Request $request, UserRepository $users) { $action = $request->input('action'); @@ -196,11 +195,11 @@ class AdminController extends Controller return json('修改配色成功', 0); } - $user = new User($request->input('uid')); + $user = $users->get($request->input('uid')); // current user - $cur_user = new User(session('uid')); + $cur_user = $users->get(session('uid')); - if (!$user->is_registered) + if (!$user) return json('用户不存在', 1); if ($action == "email") { @@ -236,36 +235,36 @@ class AdminController extends Controller return json('积分修改成功', 0); } elseif ($action == "ban") { - if ($user->getPermission() == "1") { - if ($cur_user->getPermission() != "2") + if ($user->getPermission() == User::ADMIN) { + if ($cur_user->getPermission() != User::SUPER_ADMIN) return json('非超级管理员无法封禁普通管理员'); - } elseif ($user->getPermission() == "2") { + } elseif ($user->getPermission() == User::SUPER_ADMIN) { return json('超级管理员无法被封禁'); } - $permission = $user->getPermission() == "-1" ? "0" : "-1"; + $permission = $user->getPermission() == User::BANNED ? User::NORMAL : User::BANNED; if ($user->setPermission($permission)) { return json([ 'errno' => 0, - 'msg' => '账号已被' . ($permission == '-1' ? '封禁' : '解封'), + 'msg' => '账号已被' . ($permission == User::BANNED ? '封禁' : '解封'), 'permission' => $user->getPermission() ]); } } elseif ($action == "admin") { - if ($cur_user->getPermission() != "2") + if ($cur_user->getPermission() != User::SUPER_ADMIN) return json('非超级管理员无法进行此操作'); - if ($user->getPermission() == "2") + if ($user->getPermission() == User::SUPER_ADMIN) return json('超级管理员无法被解除'); - $permission = $user->getPermission() == "1" ? "0" : "1"; + $permission = $user->getPermission() == User::ADMIN ? User::NORMAL : User::ADMIN; if ($user->setPermission($permission)) { return json([ 'errno' => 0, - 'msg' => '账号已被' . ($permission == '1' ? '设为' : '解除') . '管理员', + 'msg' => '账号已被' . ($permission == User::ADMIN ? '设为' : '解除') . '管理员', 'permission' => $user->getPermission() ]); } @@ -282,7 +281,7 @@ class AdminController extends Controller /** * Handle ajax request from /admin/players */ - public function playerAjaxHandler(Request $request) + public function playerAjaxHandler(Request $request, UserRepository $users) { $action = isset($_GET['action']) ? $_GET['action'] : ""; @@ -317,9 +316,9 @@ class AdminController extends Controller 'uid' => 'required|integer' ]); - $user = new User($request->input('uid')); + $user = $users->get($request->input('uid')); - if (!$user->is_registered) + if (!$user) return json('不存在的用户', 1); if ($player->setOwner($request->input('uid'))) diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 4da80062..37e506d4 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -5,12 +5,14 @@ namespace App\Http\Controllers; use Mail; use View; use Utils; +use Cookie; use Option; use Session; use App\Models\User; use App\Models\UserModel; use Illuminate\Http\Request; use App\Exceptions\PrettyPageException; +use App\Services\Repositories\UserRepository; class AuthController extends Controller { @@ -19,7 +21,7 @@ class AuthController extends Controller return view('auth.login'); } - public function handleLogin(Request $request) + public function handleLogin(Request $request, UserRepository $users) { $this->validate($request, [ 'identification' => 'required', @@ -28,19 +30,22 @@ class AuthController extends Controller $identification = $request->input('identification'); - $auth_type = (validate($request->input('identification'), 'email')) ? "email" : "username"; + // guess type of identification + $auth_type = (validate($identification, 'email')) ? "email" : "username"; event(new \App\Events\UserTryToLogin($identification, $auth_type)); - // instantiate user - $user = new User(null, [$auth_type => $identification]); + // Get user instance from repository. + // If the given identification is not registered yet, + // it will return a null value. + $user = $users->get($identification, $auth_type); if (session('login_fails', 0) > 3) { if (strtolower($request->input('captcha')) != strtolower(session('phrase'))) return json(trans('auth.validation.captcha'), 1); } - if (!$user->is_registered) { + if (!$user) { return json(trans('auth.validation.user'), 2); } else { if ($user->checkPasswd($request->input('password'))) { @@ -49,16 +54,16 @@ class AuthController extends Controller Session::put('uid' , $user->uid); Session::put('token', $user->getToken()); - $time = $request->input('keep') == true ? 86400 : 3600; - - setcookie('uid', $user->uid, time()+$time, '/'); - setcookie('token', $user->getToken(), time()+$time, '/'); + // time in minutes + $time = $request->input('keep') == true ? 10080 : 60; event(new \App\Events\UserLoggedIn($user)); return json(trans('auth.login.success'), 0, [ 'token' => $user->getToken() - ]); + ]) // set cookies + ->withCookie('uid', $user->uid, $time) + ->withCookie('token', $user->getToken(), $time); } else { Session::put('login_fails', session('login_fails', 0) + 1); @@ -69,16 +74,16 @@ class AuthController extends Controller } } - public function logout() + public function logout(Request $request) { - if (Session::has('token')) { - setcookie('uid', '', time() - 3600, '/'); - setcookie('token', '', time() - 3600, '/'); - + if ($request->hasSession()) { + // flush sessions Session::flush(); - Session::regenerate(); - return json(trans('auth.logout.success'), 0); + // delete cookies + return json(trans('auth.logout.success'), 0) + ->withCookie(Cookie::forget('uid')) + ->withCookie(Cookie::forget('token')); } else { return json(trans('auth.logout.fail'), 1); } @@ -86,16 +91,16 @@ class AuthController extends Controller public function register() { - if (Option::get('user_can_register') == 1) { + if (option('user_can_register')) { return view('auth.register'); } else { throw new PrettyPageException(trans('auth.register.close'), 7); } } - public function handleRegister(Request $request) + public function handleRegister(Request $request, UserRepository $users) { - if (strtolower($request->input('captcha')) != strtolower(session('phrase'))) + if (!$this->checkCaptcha($request)) return json(trans('auth.validation.captcha'), 1); $this->validate($request, [ @@ -104,38 +109,46 @@ class AuthController extends Controller 'nickname' => 'required|nickname|max:255' ]); - $user = new User(null, ['email' => $request->input('email')]); + if (!option('user_can_register')) { + return json(trans('auth.register.close'), 7); + } - if (!$user->is_registered) { - if (Option::get('user_can_register') == 1) { - $ip = get_real_ip(); + $ip = get_real_ip(); - // If amount of registered accounts of IP is more than allowed amounts, - // then reject the register. - if (UserModel::where('ip', $ip)->count() < Option::get('regs_per_ip')) - { - // register new user - $user = $user->register($request->input('password'), $ip); - $user->setNickName($request->input('nickname')); + // If amount of registered accounts of IP is more than allowed amounts, + // then reject the register. + if (User::where('ip', $ip)->count() < option('regs_per_ip')) + { + // Register a new user. + // If the email is already registered, + // it will return a false value. + $user = User::register( + $request->input('email'), + $request->input('password'), + function($user) use ($ip, $request) + { + $user->ip = $ip; + $user->score = option('user_initial_score'); + $user->register_at = Utils::getTimeFormatted(); + $user->last_sign_at = Utils::getTimeFormatted(time() - 86400); + $user->permission = User::NORMAL; + $user->nickname = $request->input('nickname'); + }); - // set cookies - setcookie('uid', $user->uid, time() + 3600, '/'); - setcookie('token', $user->getToken(), time() + 3600, '/'); - - return json([ - 'errno' => 0, - 'msg' => trans('auth.register.success'), - 'token' => $user->getToken() - ]); - - } else { - return json(trans('auth.register.max', ['regs' => Option::get('regs_per_ip')]), 7); - } - } else { - return json(trans('auth.register.close'), 7); + if (!$user) { + return json(trans('auth.register.registered'), 5); } + + return json([ + 'errno' => 0, + 'msg' => trans('auth.register.success'), + 'token' => $user->getToken() + ]) // set cookies + ->withCookie('uid', $user->uid, 60) + ->withCookie('token', $user->getToken(), 60); + } else { - return json(trans('auth.register.registered'), 5); + return json(trans('auth.register.max', ['regs' => option('regs_per_ip')]), 7); } } @@ -148,9 +161,9 @@ class AuthController extends Controller } } - public function handleForgot(Request $request) + public function handleForgot(Request $request, UserRepository $users) { - if (strtolower($request->input('captcha')) != strtolower(session('phrase'))) + if (!$this->checkCaptcha($request)) return json(trans('auth.validation.captcha'), 1); if (config('mail.host') == "") @@ -159,12 +172,14 @@ class AuthController extends Controller if (Session::has('last_mail_time') && (time() - session('last_mail_time')) < 60) return json(trans('auth.forgot.frequent-mail'), 1); - $user = new User(null, ['email' => $request->input('email')]); + // get user instance + $user = $users->get($request->input('email'), 'email'); - if (!$user->is_registered) + if (!$user) return json(trans('auth.forgot.unregistered'), 1); - $uid = $user->uid; + $uid = $user->uid; + // generate token for password resetting $token = base64_encode($user->getToken().substr(time(), 4, 6).Utils::generateRndString(16)); $url = Option::get('site_url')."/auth/reset?uid=$uid&token=$token"; @@ -185,21 +200,24 @@ class AuthController extends Controller return json(trans('auth.mail.success'), 0); } - public function reset() + public function reset(UserRepository $users, Request $request) { - if (isset($_GET['uid']) && isset($_GET['token'])) { - $user = new User($_GET['uid']); - if (!$user->is_registered) + if ($request->has('uid') && $request->has('token')) { + // get user instance from repository + $user = $users->get($request->input('uid')); + + if (!$user) return redirect('auth/forgot')->with('msg', trans('auth.reset.invalid')); - $token = substr(base64_decode($_GET['token']), 0, -22); + // unpack to get user token & timestamp + $encrypted = base64_decode($request->input('token')); + $token = substr($encrypted, 0, -22); + $timestamp = substr($encrypted, strlen($token), 6); if ($user->getToken() != $token) { return redirect('auth/forgot')->with('msg', trans('auth.reset.invalid')); } - $timestamp = substr(base64_decode($_GET['token']), strlen($token), 6); - // more than 1 hour if ((substr(time(), 4, 6) - $timestamp) > 3600) { return redirect('auth/forgot')->with('msg', trans('auth.reset.expired')); @@ -211,19 +229,16 @@ class AuthController extends Controller } } - public function handleReset(Request $request) + public function handleReset(Request $request, UserRepository $users) { $this->validate($request, [ 'uid' => 'required|integer', 'password' => 'required|min:8|max:16', ]); - $user = new User($request->input('uid')); - - $user->changePasswd($request->input('password')); + $users->get($request->input('uid'))->changePasswd($request->input('password')); return json(trans('auth.reset.success'), 0); - } public function captcha() @@ -236,4 +251,9 @@ class AuthController extends Controller return \Response::png(); } + private function checkCaptcha($request) + { + return (strtolower($request->input('captcha')) == strtolower(session('phrase'))); + } + } diff --git a/app/Http/Controllers/ClosetController.php b/app/Http/Controllers/ClosetController.php index 6a85e2c5..54894fc0 100644 --- a/app/Http/Controllers/ClosetController.php +++ b/app/Http/Controllers/ClosetController.php @@ -10,6 +10,7 @@ use App\Models\Texture; use App\Models\ClosetModel; use Illuminate\Http\Request; use App\Exceptions\PrettyPageException; +use App\Services\Repositories\UserRepository; class ClosetController extends Controller { @@ -25,7 +26,7 @@ class ClosetController extends Controller $this->closet = new Closet(session('uid')); } - public function index(Request $request) + public function index(Request $request, UserRepository $users) { $category = $request->input('category', 'skin'); $page = $request->input('page', 1); @@ -56,7 +57,7 @@ class ClosetController extends Controller ->with('q', $q) ->with('category', $category) ->with('total_pages', $total_pages) - ->with('user', (new User(session('uid')))) + ->with('user', $users->get(session('uid'))) ->render(); } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 4b6d6137..ed1d6d29 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -6,25 +6,13 @@ use Session; use App\Models\User; use Illuminate\Support\Arr; use Illuminate\Http\Request; +use App\Services\Repositories\UserRepository; class HomeController extends Controller { - - public function index() + public function index(UserRepository $users, Request $request) { - if (isset($_COOKIE['uid']) && isset($_COOKIE['token'])) { - $user = new User($_COOKIE['uid']); - - if ($_COOKIE['token'] != $user->getToken() || $user->getPermission() == "-1") { - // delete cookies - setcookie("uid", "", time() - 3600, '/'); - setcookie("token", "", time() - 3600, '/'); - } - } - - $user = Session::has('uid') ? new User(session('uid')) : null; - - return view('index')->with('user', $user); + return view('index')->with('user', $users->get(session('uid'))); } public function locale($lang, Request $request) diff --git a/app/Http/Controllers/PlayerController.php b/app/Http/Controllers/PlayerController.php index 08f55610..f3855c92 100644 --- a/app/Http/Controllers/PlayerController.php +++ b/app/Http/Controllers/PlayerController.php @@ -13,6 +13,7 @@ use Illuminate\Http\Request; use App\Events\PlayerWasAdded; use App\Events\PlayerWasDeleted; use App\Exceptions\PrettyPageException; +use App\Services\Repositories\UserRepository; class PlayerController extends Controller { @@ -30,9 +31,9 @@ class PlayerController extends Controller */ private $player; - public function __construct(Request $request) + public function __construct(Request $request, UserRepository $users) { - $this->user = new User(session('uid')); + $this->user = $users->get(session('uid')); if ($request->has('pid')) $this->player = Player::find($request->pid); @@ -40,7 +41,7 @@ class PlayerController extends Controller public function index() { - return view('user.player')->with('players', $this->user->getPlayers()->toArray())->with('user', $this->user); + return view('user.player')->with('players', $this->user->players->toArray())->with('user', $this->user); } public function add(Request $request) diff --git a/app/Http/Controllers/SkinlibController.php b/app/Http/Controllers/SkinlibController.php index b4c152b8..46d89b5c 100644 --- a/app/Http/Controllers/SkinlibController.php +++ b/app/Http/Controllers/SkinlibController.php @@ -11,14 +11,18 @@ use App\Models\User; use App\Models\Texture; use Illuminate\Http\Request; use App\Exceptions\PrettyPageException; +use App\Services\Repositories\UserRepository; class SkinlibController extends Controller { private $user = null; - public function __construct() + public function __construct(UserRepository $users) { - $this->user = Session::has('uid') ? new User(session('uid')) : null; + // Try to load user by uid stored in session. + // If there is no uid stored in session or the uid is invalid + // it will return a null value. + $this->user = $users->get(session('uid')); } public function index(Request $request) @@ -46,7 +50,7 @@ class SkinlibController extends Controller if (!is_null($this->user)) { // show private textures when show uploaded textures of current user - if ($uid != $this->user->uid && !$this->user->is_admin) + if ($uid != $this->user->uid && !$this->user->isAdmin()) $textures = $textures->where('public', '1'); } else { $textures = $textures->where('public', '1'); @@ -111,7 +115,7 @@ class SkinlibController extends Controller } if ($texture->public == "0") { - if (is_null($this->user) || ($this->user->uid != $texture->uploader && !$this->user->is_admin)) + if (is_null($this->user) || ($this->user->uid != $texture->uploader && !$this->user->isAdmin())) abort(404, trans('skinlib.show.private')); } @@ -165,7 +169,7 @@ class SkinlibController extends Controller $this->user->setScore($cost, 'minus'); - if ($this->user->closet->add($t->tid, $t->name)) { + if ($this->user->getCloset()->add($t->tid, $t->name)) { return json(trans('skinlib.upload.success', ['name' => $request->input('name')]), 0, [ 'tid' => $t->tid ]); @@ -179,7 +183,7 @@ class SkinlibController extends Controller if (!$result) return json(trans('skinlib.non-existent'), 1); - if ($result->uploader != $this->user->uid && !$this->user->is_admin) + if ($result->uploader != $this->user->uid && !$this->user->isAdmin()) return json(trans('skinlib.no-permission'), 1); // check if file occupied @@ -199,7 +203,7 @@ class SkinlibController extends Controller if (!$t) return json(trans('skinlib.non-existent'), 1); - if ($t->uploader != $this->user->uid && !$this->user->is_admin) + if ($t->uploader != $this->user->uid && !$this->user->isAdmin()) return json(trans('skinlib.no-permission'), 1); if ($t->setPrivacy(!$t->public)) { @@ -222,7 +226,7 @@ class SkinlibController extends Controller if (!$t) return json(trans('skinlib.non-existent'), 1); - if ($t->uploader != $this->user->uid && !$this->user->is_admin) + if ($t->uploader != $this->user->uid && !$this->user->isAdmin()) return json(trans('skinlib.no-permission'), 1); $t->name = $request->input('new_name'); diff --git a/app/Http/Controllers/TextureController.php b/app/Http/Controllers/TextureController.php index 8dc12ac7..0bc37b6f 100644 --- a/app/Http/Controllers/TextureController.php +++ b/app/Http/Controllers/TextureController.php @@ -14,6 +14,7 @@ use Illuminate\Http\Request; use App\Events\GetSkinPreview; use App\Events\GetAvatarPreview; use App\Exceptions\PrettyPageException; +use App\Services\Repositories\UserRepository; class TextureController extends Controller { @@ -80,11 +81,11 @@ class TextureController extends Controller return $player->getBinaryTexture('cape'); } - public function avatar($base64_email, $size = 128) + public function avatar($base64_email, $size = 128, UserRepository $users) { - $user = new User(null, ['email' => base64_decode($base64_email)]); + $user = $users->get(base64_decode($base64_email), 'email'); - if ($user->is_registered) { + if ($user) { $tid = $user->getAvatarId(); if ($t = Texture::find($tid)) { @@ -113,9 +114,9 @@ class TextureController extends Controller return Response::png(); } - public function avatarWithSize($size, $base64_email) + public function avatarWithSize($size, $base64_email, UserRepository $users) { - return $this->avatar($base64_email, $size); + return $this->avatar($base64_email, $size, $users); } public function preview($tid, $size = 250) diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index bc773073..f30c742d 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -2,22 +2,24 @@ namespace App\Http\Controllers; +use App; use View; use Utils; use App\Models\User; use App\Models\Texture; use Illuminate\Http\Request; use App\Exceptions\PrettyPageException; +use App\Services\Repositories\UserRepository; class UserController extends Controller { private $action = ""; private $user = null; - public function __construct() + public function __construct(Request $request, UserRepository $users) { - $this->action = isset($_GET['action']) ? $_GET['action'] : ""; - $this->user = new User(session('uid')); + $this->action = $request->input('action', ''); + $this->user = $users->get(session('uid')); } public function index() diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 9c63904b..2caa49be 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -29,6 +29,7 @@ class Kernel extends HttpKernel \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, + \App\Http\Middleware\CheckSessionUserValid::class, \App\Http\Middleware\Internationalization::class, //\App\Http\Middleware\VerifyCsrfToken::class, ], diff --git a/app/Http/Middleware/CheckAdminMiddleware.php b/app/Http/Middleware/CheckAdminMiddleware.php index 49e73d9a..59fbc6f7 100644 --- a/app/Http/Middleware/CheckAdminMiddleware.php +++ b/app/Http/Middleware/CheckAdminMiddleware.php @@ -12,7 +12,7 @@ class CheckAdminMiddleware return $user; } - if (!$user->is_admin) { + if (!$user->isAdmin()) { return redirect('user')->with('msg', '看起来你并不是管理员哦'); } diff --git a/app/Http/Middleware/CheckAuthenticated.php b/app/Http/Middleware/CheckAuthenticated.php index 3e6fb3d1..05175325 100644 --- a/app/Http/Middleware/CheckAuthenticated.php +++ b/app/Http/Middleware/CheckAuthenticated.php @@ -2,11 +2,11 @@ namespace App\Http\Middleware; +use App; use View; use Http; use Session; use App\Models\User; -use App\Models\UserModel; use App\Exceptions\PrettyPageException; class CheckAuthenticated @@ -14,17 +14,14 @@ class CheckAuthenticated public function handle($request, \Closure $next, $return_user = false) { if (Session::has('uid')) { - $user = new User(session('uid')); + $user = App::make('users')->get(session('uid')); if (session('token') != $user->getToken()) return redirect('auth/login')->with('msg', trans('auth.check.token')); if ($user->getPermission() == "-1") { - // delete cookies - setcookie('uid', '', time() - 3600, '/'); - setcookie('token', '', time() - 3600, '/'); - - Session::flush(); + delete_sessions(); + delete_cookies(); throw new PrettyPageException(trans('auth.check.banned'), 5); } @@ -33,11 +30,11 @@ class CheckAuthenticated if ($user->email == "") { if (isset($request->email)) { if (filter_var($request->email, FILTER_VALIDATE_EMAIL)) { - if (UserModel::where('email', $request->email)->get()->isEmpty()) { + if (User::where('email', $request->email)->get()->isEmpty()) { $user->setEmail($request->email); // refresh token - Session::put('token', $user->getToken(true)); - setcookie('token', session('token'), time() + 3600, '/'); + Session::put('token', $user->getToken(true)); + Cookie::queue('token', $user->getToken(), 60); return $next($request); } else { diff --git a/app/Http/Middleware/CheckPlayerExistMiddleware.php b/app/Http/Middleware/CheckPlayerExistMiddleware.php index 2e0b638d..25228594 100644 --- a/app/Http/Middleware/CheckPlayerExistMiddleware.php +++ b/app/Http/Middleware/CheckPlayerExistMiddleware.php @@ -2,9 +2,9 @@ namespace App\Http\Middleware; +use Event; use App\Models\Player; use App\Events\CheckPlayerExists; -use Event; class CheckPlayerExistMiddleware { diff --git a/app/Http/Middleware/CheckSessionUserValid.php b/app/Http/Middleware/CheckSessionUserValid.php new file mode 100644 index 00000000..014850c6 --- /dev/null +++ b/app/Http/Middleware/CheckSessionUserValid.php @@ -0,0 +1,35 @@ +cookie('uid') && $request->cookie('token')) { + Session::put('uid' , $request->cookie('uid')); + Session::put('token', $request->cookie('token')); + } + + if (Session::has('uid')) { + $user = User::find(session('uid')); + + if ($user && $user->getToken() == session('token')) { + // push user instance to repository + App::make('users')->set($user->uid, $user); + } else { + // remove sessions & cookies + delete_sessions(); + delete_cookies(); + } + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php index bc218a06..afbfd6ee 100644 --- a/app/Http/Middleware/EncryptCookies.php +++ b/app/Http/Middleware/EncryptCookies.php @@ -14,16 +14,8 @@ class EncryptCookies extends BaseEncrypter * @var array */ protected $except = [ - 'locale' + 'locale', + 'token' ]; - public function handle($request, Closure $next) - { - if (isset($_COOKIE['uid']) && isset($_COOKIE['token'])) { - Session::put('uid' , $_COOKIE['uid']); - Session::put('token', $_COOKIE['token']); - } - - return parent::handle($request, $next); - } } diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index da9ec675..52cb65d3 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -2,15 +2,16 @@ namespace App\Http\Middleware; -use App\Models\User; +use App; use Session; +use App\Models\User; class RedirectIfAuthenticated { public function handle($request, \Closure $next) { if (session()->has('uid')) { - if (session('token') != (new User(session('uid')))->getToken()) { + if (session('token') != App::make('users')->get(session('uid'))->getToken()) { Session::put('msg', trans('auth.check.token')); } else { return redirect('user'); diff --git a/app/Models/Closet.php b/app/Models/Closet.php index ebfb0d13..5086c921 100644 --- a/app/Models/Closet.php +++ b/app/Models/Closet.php @@ -2,34 +2,45 @@ namespace App\Models; +use DB; + class Closet { public $uid; /** - * Instance of Query Builder + * Instance of Query Builder. + * * @var \Illuminate\Database\Query\Builder */ private $db; /** - * Textures array generated from json + * Textures array generated from json. + * * @var Array */ private $textures = []; /** - * Array of App\Models\Texture instances + * Array of App\Models\Texture instances. + * * @var array */ private $textures_skin = []; /** - * Array of App\Models\Texture instances + * Array of App\Models\Texture instances. + * * @var array */ private $textures_cape = []; + /** + * Items that are modified. + * + * @var array + */ private $items_modified = []; /** @@ -40,7 +51,7 @@ class Closet public function __construct($uid) { $this->uid = $uid; - $this->db = \DB::table('closets'); + $this->db = DB::table('closets'); // create a new closet if not exists if (!$this->db->where('uid', $uid)->get()) { @@ -106,8 +117,8 @@ class Closet /** * Add an item to the closet. * - * @param int $tid - * @param string $name + * @param int $tid + * @param string $name * @return bool */ public function add($tid, $name) @@ -165,7 +176,7 @@ class Closet } /** - * Remove a texture from closet + * Remove a texture from closet. * @param int $tid * @return boolean */ @@ -185,6 +196,12 @@ class Closet return false; } + /** + * Check if given tid is valid. + * + * @param int $tid + * @return bool + */ private function checkTextureExist($tid) { return ! Texture::where('tid', $tid)->isEmpty(); @@ -200,6 +217,11 @@ class Closet return $this->db->where('uid', $this->uid)->update(['textures' => $textures]);; } + /** + * Do really database operations. + * + * @return bool + */ public function save() { if (empty($this->items_modified)) return; @@ -207,6 +229,9 @@ class Closet return $this->setTextures(json_encode($this->textures)); } + /** + * Save when the object will be destructed. + */ public function __destruct() { $this->save(); diff --git a/app/Models/Player.php b/app/Models/Player.php index 93ebf13f..f7a545a9 100644 --- a/app/Models/Player.php +++ b/app/Models/Player.php @@ -2,7 +2,6 @@ namespace App\Models; -use View; use Event; use Utils; use Storage; @@ -12,21 +11,29 @@ use Illuminate\Support\Arr; use App\Events\GetPlayerJson; use App\Events\PlayerProfileUpdated; use App\Exceptions\PrettyPageException; +use Illuminate\Database\Eloquent\Model; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -class Player extends \Illuminate\Database\Eloquent\Model +class Player extends Model { + /** + * Json APIs. + */ + const CSL_API = 0; + const USM_API = 1; + + /** + * Set of models. + */ + const MODELS = ['steve', 'alex', 'cape']; + + /** + * Properties for Eloquent Model. + */ public $primaryKey = 'pid'; public $timestamps = false; - protected $fillable = ['uid', 'player_name', 'preference', 'last_modified']; - public $is_banned = false; - - const CSL_API = 0; - const USM_API = 1; - const MODELS = ['steve', 'alex', 'cape']; - /** * Check if the player is banned. * @@ -34,14 +41,24 @@ class Player extends \Illuminate\Database\Eloquent\Model */ public function isBanned() { - return (new User($this->uid))->getPermission() == "-1"; + return $this->user->getPermission() == User::BANNED; + } + + /** + * Return the owner of the player. + * + * @return App\Models\User + */ + public function user() + { + return $this->belongsTo('App\Models\User', 'uid'); } /** * Get specific texture of player. * * @param string $type steve|alex|cape - * @return string sha256-hash of texture file + * @return string Sha256-hash of texture file. */ public function getTexture($type) { @@ -94,6 +111,12 @@ class Player extends \Illuminate\Database\Eloquent\Model ]); } + /** + * Get binary texture by type. + * + * @param string $type steve|alex|cape + * @return \Illuminate\Http\Response + */ public function getBinaryTexture($type) { if ($this->getTexture($type)) { @@ -130,6 +153,11 @@ class Player extends \Illuminate\Database\Eloquent\Model return Event::fire(new PlayerProfileUpdated($this)); } + /** + * Get model preference of the player. + * + * @return string + */ public function getPreference() { return $this['preference']; @@ -182,7 +210,7 @@ class Player extends \Illuminate\Database\Eloquent\Model return $this->generateJsonProfile($api_type); } } else { - throw new InvalidArgumentException('The given api type should be 0 or 1.'); + throw new InvalidArgumentException('The given api type should be Player::CSL_API or Player::USM_API.'); } } diff --git a/app/Models/Texture.php b/app/Models/Texture.php index 5da1e5ae..4ccdb2b0 100644 --- a/app/Models/Texture.php +++ b/app/Models/Texture.php @@ -2,7 +2,9 @@ namespace App\Models; -class Texture extends \Illuminate\Database\Eloquent\Model +use Illuminate\Database\Eloquent\Model; + +class Texture extends Model { public $primaryKey = 'tid'; public $timestamps = false; diff --git a/app/Models/User.php b/app/Models/User.php index a4b2306b..9456f9e6 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,87 +2,71 @@ namespace App\Models; +use DB; +use App; use Utils; -use Option; use Carbon\Carbon; +use Illuminate\Database\Eloquent\Model; -class User +class User extends Model { - public $uid = ""; - public $email = ""; - - private $password = ""; - private $token = ""; - - private $storage_used = null; - /** - * Instance of App\Services\Cipher\{cipher} - * @var null + * Permissions. */ - private $cipher = null; + const BANNED = -1; + const NORMAL = 0; + const ADMIN = 1; + const SUPER_ADMIN = 2; /** - * Instance of App\Models\UserModel - * @var null + * User Token. + * @var string */ - private $model = null; + private $token; /** - * Instance of App\Models\Closet - * @var null + * Instance of Closet. + * @var App\Models\Closet */ - public $closet = null; - - public $is_registered = false; - public $is_admin = false; + private $closet; /** - * Pass uid or an array to instantiate a user + * Properties for Eloquent Model. + */ + public $primaryKey = 'uid'; + public $timestamps = false; + protected $fillable = ['email', 'nickname', 'permission']; + + /** + * Check if user is admin. * - * $info = [ - * 'username' => 'foo', - * 'email' => 'foo@bar.com' - * ]; - * - * @param int $uid - * @param array $info + * @return bool */ - public function __construct($uid, Array $info = []) + public function isAdmin() { - event(new \App\Events\UserInstantiated($uid)); - - // Construct user with uid|email|player_name - if ($uid !== null) { - $this->uid = $uid; - $this->model = UserModel::find($uid); - } else { - if (isset($info['email'])) { - $this->email = e($info['email']); - $this->model = UserModel::where('email', $this->email)->first(); - } elseif (isset($info['username'])) { - $player = Player::where('player_name', $info['username'])->first(); - $this->uid = $player ? $player['uid'] : 0; - $this->model = UserModel::find($this->uid); - } else { - throw new \InvalidArgumentException('Invalid arguments'); - } - } - - $class_name = "App\Services\Cipher\\".config('secure.cipher'); - $this->cipher = new $class_name; - - if (!is_null($this->model)) { - $this->is_registered = true; - $this->uid = $this->model->uid; - $this->email = $this->model->email; - $this->password = $this->model->password; - $this->token = md5($this->email . $this->password . config('secure.salt')); - $this->closet = new Closet($this->uid); - $this->is_admin = $this->model->permission == 1 || $this->model->permission == 2; - } + return ($this->permission >= static::ADMIN); } + /** + * Get closet instance. + * + * @return App\Models\Closet + */ + public function getCloset() + { + if (!$this->closet) { + $this->closet = new Closet($this->uid); + } + + return $this->closet; + } + + /** + * Check if given password is correct. + * + * @param string $raw_passwd + * @return bool + */ public function checkPasswd($raw_passwd) { $responses = event(new \App\Events\CheckUserPassword($raw_passwd, $this)); @@ -90,87 +74,158 @@ class User if (isset($responses[0])) { return (bool) $responses[0]; } else { - return ($this->cipher->encrypt($raw_passwd, config('secure.salt')) == $this->password); + return (App::make('cipher')->encrypt($raw_passwd, config('secure.salt')) == $this->password); } } - public function changePasswd($new_passwd) - { - $this->model->password = $this->cipher->encrypt($new_passwd, config('secure.salt')); - return $this->model->save(); - } - - public function getPermission() - { - return $this->model->permission; - } - /** - * Set user permission - * @param int $permission - * -1 - banned - * 0 - normal - * 1 - admin - * 2 - super admin + * Register a new user. + * + * @param string $email + * @param string $password + * @param \Closure $callback + * @return User|bool + */ + public static function register($email, $password, \Closure $callback) { + $user = static::firstOrNew(['email' => $email]); + + // if the email is already registered + if ($user->uid) + return false; + + $user->password = App::make('cipher')->encrypt($password, config('secure.salt')); + + $callback($user); + + $user->save(); + + return $user; + } + + /** + * Change password of the user. + * + * @param string $new_passwd New password that will be set. + * @return bool + */ + public function changePasswd($new_passwd) + { + $this->password = App::make('cipher')->encrypt($new_passwd, config('secure.salt')); + return $this->save(); + } + + /** + * Get user permission. + * + * @return int + */ + public function getPermission() + { + return $this->permission; + } + + /** + * Set user permission. + * + * @param int $permission + * @return bool */ public function setPermission($permission) { - return $this->model->update(['permission' => $permission]); + return $this->update(['permission' => $permission]); } + /** + * Set new email for user. + * + * @param string $new_email + */ public function setEmail($new_email) { - $this->model->email = $new_email; - return $this->model->save(); + $this->email = $new_email; + return $this->save(); } + /** + * Return Email if nickname is not set. + * + * @return string + */ public function getNickName() { - if (!$this->is_registered) { + if (!$this->uid) { return trans('general.unexistent-user'); } else { - return ($this->model->nickname == "") ? $this->email : $this->model->nickname; + return ($this->nickname == "") ? $this->email : $this->nickname; } } + /** + * Set nickname for the user. + * + * @param string $new_nickname + * @return bool + */ public function setNickName($new_nickname) { - $this->model->nickname = $new_nickname; - return $this->model->save(); + $this->nickname = $new_nickname; + return $this->save(); } + /** + * Get user token or generate one. + * + * @param bool $refresh Refresh token forcely. + * @return string + */ public function getToken($refresh = false) { - if ($this->is_registered && ($this->token === "" || $refresh)) { - $this->token = md5($this->model->email . $this->model->password . config('secure.salt')); + if (!$this->token || $refresh) { + $this->token = md5($this->email . $this->password . config('secure.salt')); } return $this->token; } + /** + * Get current score of user. + * + * @return int + */ public function getScore() { - return $this->model->score; + return $this->score; } + /** + * Set user score. + * + * @param int $score + * @param string $mode What operation should be done, set, plus or minus. + */ public function setScore($score, $mode = "set") { switch ($mode) { case 'set': - $this->model->score = $score; + $this->score = $score; break; case 'plus': - $this->model->score += $score; + $this->score += $score; break; case 'minus': - $this->model->score -= $score; + $this->score -= $score; break; } - return $this->model->save(); + return $this->save(); } + /** + * Get the size of storage units used by the user. + * + * @return int Size in KiloBytes. + */ public function getStorageUsed() { if (is_null($this->storage_used)) { @@ -183,103 +238,110 @@ class User return $this->storage_used; } + /** + * Check in for the user, return false if unavailable. + * + * @return int|bool + */ public function checkIn() { if ($this->canCheckIn()) { - $sign_score = explode(',', Option::get('sign_score')); + $sign_score = explode(',', option('sign_score')); $aquired_score = rand($sign_score[0], $sign_score[1]); $this->setScore($aquired_score, 'plus'); - $this->model->last_sign_at = Utils::getTimeFormatted(); - $this->model->save(); + $this->last_sign_at = Utils::getTimeFormatted(); + $this->save(); return $aquired_score; } else { return false; } } + /** + * Check if checking in is available now. + * + * @param bool $return_remaining_time Return remaining time. + * @return int|bool + */ public function canCheckIn($return_remaining_time = false) { // convert to timestamp $last_sign_at = strtotime($this->getLastSignTime()); - if (Option::get('sign_after_zero') == "1") { + if (option('sign_after_zero') == "1") { $remaining_time = (Carbon::tomorrow()->timestamp - time()) / 3600; $can_check_in = $last_sign_at <= Carbon::today()->timestamp; } else { - $remaining_time = ($last_sign_at + Option::get('sign_gap_time') * 3600 - time()) / 3600; + $remaining_time = ($last_sign_at + option('sign_gap_time') * 3600 - time()) / 3600; $can_check_in = $remaining_time <= 0; } return $return_remaining_time ? round($remaining_time) : $can_check_in; } + /** + * Get the last time of checking in. + * + * @return string Formatted time string. + */ public function getLastSignTime() { - return $this->model->last_sign_at; + return $this->last_sign_at; } /** - * Register a new user - * @param string $password - * @param string $ip - * @return object, instance of App\Models\User + * Get the texture id of user's avatar. + * + * @return int */ - public function register($password, $ip) - { - $user = new UserModel(); - - $user->email = $this->email; - $user->password = $this->cipher->encrypt($password, config('secure.salt')); - $user->ip = $ip; - $user->score = Option::get('user_initial_score'); - $user->register_at = Utils::getTimeFormatted(); - $user->last_sign_at = Utils::getTimeFormatted(time() - 86400); - $user->permission = 0; - $user->save(); - - $closet = new Closet($user->uid); - $this->model = $user; - $this->uid = $user->uid; - $this->is_registered = true; - - return $this; - } - - public function getPlayers() - { - return Player::where('uid', $this->uid)->get(); - } - public function getAvatarId() { - return $this->model->avatar; + return $this->avatar; } + /** + * Set user avatar. + * + * @param int $tid + * @return bool + */ public function setAvatar($tid) { - $this->model->avatar = $tid; - return $this->model->save(); + $this->avatar = $tid; + return $this->save(); } + /** + * Delete the user. + * + * @return bool + */ public function delete() { + // delete the players he owned Player::where('uid', $this->uid)->delete(); + // delete his closet DB::table('closets')->where('uid', $this->uid)->delete(); - return $this->model->delete(); + + return parent::delete(); } -} - -class UserModel extends \Illuminate\Database\Eloquent\Model -{ - public $primaryKey = 'uid'; - protected $table = 'users'; - public $timestamps = false; - - protected $fillable = ['email', 'nickname', 'permission']; + /** + * Get the players which are owned by the user. + * + * @return Illuminate\Database\Eloquent\Collection + */ + public function players() + { + return $this->hasMany('App\Models\Player', 'uid'); + } + /** + * Expand like scope for Eloquent Model. + */ public function scopeLike($query, $field, $value) { return $query->where($field, 'LIKE', "%$value%"); } + } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index eb2010cc..e559f1e8 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -18,7 +18,7 @@ class AppServiceProvider extends ServiceProvider // replace HTTP_HOST with site url setted in options to prevent CDN source problems preg_match('/https?:\/\/([^\/]+)\/?.*/', option('site_url'), $host); - if (option('auto_detect_asset_url') == "0") { + if (!option('auto_detect_asset_url')) { // check if host is valid if (isset($host[1]) && '' === preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host[1])) { $this->app['request']->headers->set('host', $host[1]); @@ -35,5 +35,9 @@ class AppServiceProvider extends ServiceProvider { $this->app->singleton('database', \App\Services\Database\Database::class); $this->app->singleton('option', \App\Services\Repositories\OptionRepository::class); + // register default cipher + $this->app->singleton('cipher', "App\Services\Cipher\\".config('secure.cipher')); + + $this->app->singleton('users', \App\Services\Repositories\UserRepository::class); } } diff --git a/app/Services/Repositories/UserRepository.php b/app/Services/Repositories/UserRepository.php new file mode 100644 index 00000000..0dabb58d --- /dev/null +++ b/app/Services/Repositories/UserRepository.php @@ -0,0 +1,58 @@ +items, $identification); + } else { + Arr::where((array) $this->items, function($key, $value) use ($identification, $type) { + return ($user->$type == $identification); + }); + } + } + + /** + * Get a user from repository and cache it. + * + * @param string $identification + * @param string $type + * @return mixed + */ + public function get($identification, $type = 'uid') + { + if (!$this->has($identification, $type)) { + if ($type == "username") { + $player = Player::where('player_name', $identification)->first(); + + if ($player) { + $identification = $player->uid; + $type = "uid"; + } + } + + $user = User::where($type, $identification)->first(); + + if ($user) { + $this->set($user->uid, $user); + return $user; + } + } + + return Arr::get($this->items, $identification, null); + } +} diff --git a/app/helpers.php b/app/helpers.php index 46b3e016..cc0ace4d 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -248,3 +248,23 @@ if (! function_exists('validate')) { } } } + +if (! function_exists('delete_cookies')) { + + function delete_cookies() + { + Cookie::queue(Cookie::forget('uid')); + Cookie::queue(Cookie::forget('token')); + } +} + +if (! function_exists('delete_sessions')) { + + function delete_sessions() + { + Session::forget('uid'); + Session::forget('token'); + + Session::save(); + } +} diff --git a/resources/views/admin/index.tpl b/resources/views/admin/index.tpl index c216057e..d87b3324 100644 --- a/resources/views/admin/index.tpl +++ b/resources/views/admin/index.tpl @@ -26,7 +26,7 @@
注册用户 - {{ App\Models\UserModel::all()->count() }} + {{ App\Models\User::all()->count() }}
@@ -99,7 +99,7 @@ $time = Carbon\Carbon::createFromTimestamp($today - $i * 86400); $labels[] = $time->format('m-d'); - $data['user_register'][] = App\Models\UserModel::like('register_at', $time->toDateString())->count(); + $data['user_register'][] = App\Models\User::like('register_at', $time->toDateString())->count(); $data['texture_upload'][] = App\Models\Texture::like('upload_at', $time->toDateString())->count(); } ?> diff --git a/resources/views/admin/master.tpl b/resources/views/admin/master.tpl index b01a2e3d..6b15829a 100644 --- a/resources/views/admin/master.tpl +++ b/resources/views/admin/master.tpl @@ -13,7 +13,7 @@ @yield('style') - +get(session('uid')); ?>
diff --git a/resources/views/admin/users.tpl b/resources/views/admin/users.tpl index 93e2c609..8cb335ad 100644 --- a/resources/views/admin/users.tpl +++ b/resources/views/admin/users.tpl @@ -26,7 +26,7 @@ - + get(session('uid')); ?>
diff --git a/resources/views/skinlib/item.tpl b/resources/views/skinlib/item.tpl index d69d4593..5d6259e4 100644 --- a/resources/views/skinlib/item.tpl +++ b/resources/views/skinlib/item.tpl @@ -12,7 +12,7 @@ @if (Session::has('uid')) - @if ($user->closet->has($texture['tid'])) + @if ($user->getCloset()->has($texture['tid'])) @else diff --git a/resources/views/skinlib/show.tpl b/resources/views/skinlib/show.tpl index 87ba6a23..032b562d 100644 --- a/resources/views/skinlib/show.tpl +++ b/resources/views/skinlib/show.tpl @@ -26,7 +26,7 @@ @else - @if ($user->closet->has($texture->tid)) + @if ($user->getCloset()->has($texture->tid)) {{ trans('skinlib.item.remove-from-closet') }} @else {{ trans('skinlib.item.add-to-closet') }} @@ -50,7 +50,7 @@ {{ trans('skinlib.show.name') }} {{ $texture->name }} - @if (!is_null($user) && ($texture->uploader == $user->uid || $user->is_admin)) + @if (!is_null($user) && ($texture->uploader == $user->uid || $user->isAdmin())) {{ trans('skinlib.show.edit-name') }} @@ -75,7 +75,7 @@ {{ trans('skinlib.show.uploader') }} - uploader); ?> + get($texture->uploader); ?> {{ $uploader->getNickName() }} @@ -94,7 +94,7 @@ 'message' => trans('skinlib.show.notice') ]) - @elseif ($user->is_admin) + @elseif ($user->isAdmin()) @include('vendor.manage-panel', [ 'title' => trans('skinlib.show.manage-panel'), 'message' => trans('skinlib.show.notice-admin') diff --git a/resources/views/user/closet.tpl b/resources/views/user/closet.tpl index 755df1c2..d0ecd0dc 100644 --- a/resources/views/user/closet.tpl +++ b/resources/views/user/closet.tpl @@ -126,7 +126,7 @@