refactor models

This commit is contained in:
printempw 2016-10-23 11:41:52 +08:00
parent a877fa0788
commit e35fa9b85a
33 changed files with 568 additions and 327 deletions

View File

@ -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')))

View File

@ -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')));
}
}

View File

@ -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();
}

View File

@ -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)

View File

@ -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)

View File

@ -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');

View File

@ -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)

View File

@ -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()

View File

@ -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,
],

View File

@ -12,7 +12,7 @@ class CheckAdminMiddleware
return $user;
}
if (!$user->is_admin) {
if (!$user->isAdmin()) {
return redirect('user')->with('msg', '看起来你并不是管理员哦');
}

View File

@ -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 {

View File

@ -2,9 +2,9 @@
namespace App\Http\Middleware;
use Event;
use App\Models\Player;
use App\Events\CheckPlayerExists;
use Event;
class CheckPlayerExistMiddleware
{

View File

@ -0,0 +1,35 @@
<?php
namespace App\Http\Middleware;
use App;
use Cookie;
use Session;
use App\Models\User;
class CheckSessionUserValid
{
public function handle($request, \Closure $next)
{
// load session from cookie
if ($request->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);
}
}

View File

@ -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);
}
}

View File

@ -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');

View File

@ -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();

View File

@ -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.');
}
}

View File

@ -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;

View File

@ -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%");
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace App\Services\Repositories;
use App\Models\User;
use App\Models\Player;
use Illuminate\Support\Arr;
class UserRepository extends Repository
{
/**
* Determine if a user exists in the repository.
*
* @param string $identification
* @param string $type Must be one of properties defined in User class
* @return bool
*/
public function has($identification, $type = 'uid')
{
if ($type == "uid") {
return Arr::has($this->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);
}
}

View File

@ -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();
}
}

View File

@ -26,7 +26,7 @@
<span class="info-box-icon bg-aqua"><i class="fa fa-users"></i></span>
<div class="info-box-content">
<span class="info-box-text">注册用户</span>
<span class="info-box-number">{{ App\Models\UserModel::all()->count() }}</span>
<span class="info-box-number">{{ App\Models\User::all()->count() }}</span>
</div><!-- /.info-box-content -->
</a>
</div><!-- /.info-box -->
@ -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();
}
?>

View File

@ -13,7 +13,7 @@
@yield('style')
</head>
<?php $user = new App\Models\User(session('uid')); ?>
<?php $user = App::make('users')->get(session('uid')); ?>
<body class="hold-transition {{ option('color_scheme') }} sidebar-mini">
<div class="wrapper">

View File

@ -26,7 +26,7 @@
</h1>
</section>
<?php $current_user = new App\Models\User(session('uid')); ?>
<?php $current_user = App::make('users')->get(session('uid')); ?>
<!-- Main content -->
<section class="content">

View File

@ -12,7 +12,7 @@
@if (Session::has('uid'))
@if ($user->closet->has($texture['tid']))
@if ($user->getCloset()->has($texture['tid']))
<a title="{{ trans('skinlib.item.remove-from-closet') }}" class="more like liked" tid="{{ $texture['tid'] }}" href="javascript:removeFromCloset({{ $texture['tid'] }});" data-placement="top" data-toggle="tooltip"><i class="fa fa-heart"></i></a>
@else
<a title="{{ trans('skinlib.item.add-to-closet') }}" class="more like" tid="{{ $texture['tid'] }}" href="javascript:addToCloset({{ $texture['tid'] }});" data-placement="top" data-toggle="tooltip"><i class="fa fa-heart"></i></a>

View File

@ -26,7 +26,7 @@
<button disabled="disabled" title="{{ trans('skinlib.show.anonymous') }}" class="btn btn-primary pull-right">{{ trans('skinlib.item.add-to-closet') }}</button>
@else
@if ($user->closet->has($texture->tid))
@if ($user->getCloset()->has($texture->tid))
<a href="javascript:removeFromCloset({{ $texture->tid }});" id="{{ $texture->tid }}" class="btn btn-primary pull-right">{{ trans('skinlib.item.remove-from-closet') }}</a>
@else
<a href="javascript:addToCloset({{ $texture->tid }});" id="{{ $texture->tid }}" class="btn btn-primary pull-right">{{ trans('skinlib.item.add-to-closet') }}</a>
@ -50,7 +50,7 @@
<tr>
<td>{{ trans('skinlib.show.name') }}</td>
<td id="name">{{ $texture->name }}
@if (!is_null($user) && ($texture->uploader == $user->uid || $user->is_admin))
@if (!is_null($user) && ($texture->uploader == $user->uid || $user->isAdmin()))
<small>
<a href="javascript:changeTextureName({{ $texture->tid }});">{{ trans('skinlib.show.edit-name') }}</a>
</small>
@ -75,7 +75,7 @@
</tr>
<tr>
<td>{{ trans('skinlib.show.uploader') }}</td>
<?php $uploader = new App\Models\User($texture->uploader); ?>
<?php $uploader = App::make('users')->get($texture->uploader); ?>
<td><a href="{{ url('skinlib?filter=user&uid='.$uploader->uid) }}&sort=time">{{ $uploader->getNickName() }}</a></td>
</tr>
<tr>
@ -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')

View File

@ -126,7 +126,7 @@
<h4 class="modal-title">{{ trans('user.closet.use-as.title') }}</h4>
</div>
<div class="modal-body">
@forelse($user->getPlayers() as $player)
@forelse($user->players as $player)
<label class="model-label" for="{{ $player->pid }}">
<input type="radio" id="{{ $player->pid }}" name="player" /> {{ $player->player_name }}
</label><br />

View File

@ -33,10 +33,10 @@
<div class="progress-group">
<span class="progress-text">{{ trans('user.used.players') }}</span>
<?php
$players_available = count($user->getPlayers()) + floor($user->getScore() / option('score_per_player'));
$percent = ($players_available == 0) ? 0 : count($user->getPlayers()) / $players_available * 100
$players_available = $user->players->count() + floor($user->getScore() / option('score_per_player'));
$percent = ($players_available == 0) ? 0 : $user->players->count() / $players_available * 100
?>
<span class="progress-number"><b>{{ count($user->getPlayers()) }}</b>/{{ $players_available }}</span>
<span class="progress-number"><b>{{ $user->players->count() }}</b>/{{ $players_available }}</span>
<div class="progress sm">
<div class="progress-bar progress-bar-aqua" style="width: {{ $percent }}%"></div>
</div>

View File

@ -92,7 +92,7 @@
<li class="header">{{ trans('general.explore') }}</li>
<li><a href="{{ url('skinlib') }}"><i class="fa fa-archive"></i> <span>{{ trans('general.skinlib') }}</span></a></li>
@if ($user->is_admin)
@if ($user->isAdmin())
<li class="header">{{ trans('general.manage') }}</li>
<li><a href="{{ url('admin') }}"><i class="fa fa-cog"></i> <span>{{ trans('general.admin-panel') }}</span></a></li>
@endif

View File

@ -25,7 +25,7 @@
<tr>
<th>PID</th>
<th>{{ trans('user.player.player-name') }}</th>
<th>{{ trans('user.player.preference') }}</th>
<th>{{ trans('user.player.preference.title') }}</th>
<th>{{ trans('user.player.edit') }}</th>
<th>{{ trans('user.player.operation') }}</th>
</tr>

View File

@ -92,7 +92,7 @@
<h3 class="box-title">{{ trans('user.profile.delete.title') }}</h3>
</div><!-- /.box-header -->
<div class="box-body">
@if (!$user->is_admin)
@if (!$user->isAdmin())
<p>{{ trans('user.profile.delete.notice', ['site' => option('site_name')]) }}</p>
<button id="delete" class="btn btn-danger" data-toggle="modal" data-target="#modal-delete-account">{{ trans('user.profile.delete.button') }}</button>
@else

View File

@ -13,7 +13,7 @@
@elseif ($filter == "cape")
{{ trans('skinlib.filter.cape') }}
@elseif ($filter == "user")
{{ trans('skinlib.filter.uploader', ['name' => (new App\Models\User($_GET['uid']))->getNickName()]) }}
{{ trans('skinlib.filter.uploader', ['name' => App::make('users')->get($_GET['uid'])->getNickName()]) }}
@endif
</li>
<li class="active">