Use Laravel's auth system and use another captcha generator

This commit is contained in:
Pig Fang 2018-07-20 14:42:43 +08:00
parent c783285a16
commit fdf618b2be
41 changed files with 655 additions and 548 deletions

View File

@ -11,6 +11,7 @@ use App\Models\Player;
use App\Models\Texture; use App\Models\Texture;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Services\OptionForm; use App\Services\OptionForm;
use Illuminate\Support\Facades\Auth;
use App\Services\Repositories\UserRepository; use App\Services\Repositories\UserRepository;
class AdminController extends Controller class AdminController extends Controller
@ -247,7 +248,7 @@ class AdminController extends Controller
return $user->email ?: 'EMPTY'; return $user->email ?: 'EMPTY';
}) })
->setRowId('uid') ->setRowId('uid')
->addColumn('operations', app('user.current')->getPermission()) ->addColumn('operations', Auth::user()->permission)
->addColumn('players_count', function ($user) { ->addColumn('players_count', function ($user) {
return $user->players->count(); return $user->players->count();
}) })
@ -271,19 +272,20 @@ class AdminController extends Controller
* Handle ajax request from /admin/users * Handle ajax request from /admin/users
* *
* @param Request $request * @param Request $request
* @return Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function userAjaxHandler(Request $request, UserRepository $users) public function userAjaxHandler(Request $request, UserRepository $users)
{ {
$action = $request->input('action'); $action = $request->input('action');
$user = $users->get($request->input('uid')); $user = $users->get($request->input('uid'));
$currentUser = Auth::user();
if (! $user) { if (! $user) {
return json(trans('admin.users.operations.non-existent'), 1); return json(trans('admin.users.operations.non-existent'), 1);
} }
if ($user->uid !== app('user.current')->uid) { if ($user->uid !== $currentUser->uid) {
if ($user->permission >= app('user.current')->permission) { if ($user->permission >= $currentUser->permission) {
return json(trans('admin.users.operations.no-permission'), 1); return json(trans('admin.users.operations.no-permission'), 1);
} }
} }
@ -367,15 +369,15 @@ class AdminController extends Controller
public function playerAjaxHandler(Request $request, UserRepository $users) public function playerAjaxHandler(Request $request, UserRepository $users)
{ {
$action = $request->input('action'); $action = $request->input('action');
$currentUser = Auth::user();
$player = Player::find($request->input('pid')); $player = Player::find($request->input('pid'));
if (! $player) { if (! $player) {
return json(trans('general.unexistent-player'), 1); return json(trans('general.unexistent-player'), 1);
} }
if ($player->user()->first()->uid !== app('user.current')->uid) { if ($player->user()->first()->uid !== $currentUser->uid) {
if ($player->user->permission >= app('user.current')->permission) { if ($player->user->permission >= $currentUser->permission) {
return json(trans('admin.players.no-permission'), 1); return json(trans('admin.players.no-permission'), 1);
} }
} }
@ -445,7 +447,7 @@ class AdminController extends Controller
$user = $users->get(intval($uid)); $user = $users->get(intval($uid));
if ($user) { if ($user) {
return json('success', 0, ['user' => $user->makeHidden([ return json('success', 0, ['user' => $user->makeHidden([
'password', 'ip', 'last_sign_at', 'register_at' 'password', 'ip', 'last_sign_at', 'register_at', 'remember_token'
])->toArray()]); ])->toArray()]);
} else { } else {
return json('No such user.', 1); return json('No such user.', 1);

View File

@ -14,16 +14,12 @@ use App\Events;
use App\Models\User; use App\Models\User;
use App\Mail\ForgotPassword; use App\Mail\ForgotPassword;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Exceptions\PrettyPageException; use App\Exceptions\PrettyPageException;
use App\Services\Repositories\UserRepository; use App\Services\Repositories\UserRepository;
class AuthController extends Controller class AuthController extends Controller
{ {
public function login()
{
return view('auth.login');
}
public function handleLogin(Request $request, UserRepository $users) public function handleLogin(Request $request, UserRepository $users)
{ {
$this->validate($request, [ $this->validate($request, [
@ -54,21 +50,13 @@ class AuthController extends Controller
if ($user->verifyPassword($request->input('password'))) { if ($user->verifyPassword($request->input('password'))) {
Session::forget('login_fails'); Session::forget('login_fails');
Session::put('uid' , $user->uid); Auth::login($user, $request->input('keep') == 'true');
Session::put('token', $user->getToken());
// Time in minutes
$time = $request->input('keep') == true ? 10080 : 60;
event(new Events\UserLoggedIn($user)); event(new Events\UserLoggedIn($user));
session()->forget('last_requested_path'); session()->forget('last_requested_path');
return json(trans('auth.login.success'), 0, [ return json(trans('auth.login.success'), 0);
'token' => $user->getToken()
]) // Set cookies
->withCookie('uid', $user->uid, $time)
->withCookie('token', $user->getToken(), $time);
} else { } else {
Session::put('login_fails', session('login_fails', 0) + 1); Session::put('login_fails', session('login_fails', 0) + 1);
@ -79,16 +67,11 @@ class AuthController extends Controller
} }
} }
public function logout(Request $request) public function logout()
{ {
if (Session::has('uid') && Session::has('token')) { if (Auth::check()) {
// Flush sessions Auth::logout();
Session::flush(); 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 { } else {
return json(trans('auth.logout.fail'), 1); return json(trans('auth.logout.fail'), 1);
} }
@ -103,15 +86,13 @@ class AuthController extends Controller
} }
} }
public function handleRegister(Request $request, UserRepository $users) public function handleRegister(Request $request)
{ {
if (! $this->checkCaptcha($request)) $data = $this->validate($request, [
return json(trans('auth.validation.captcha'), 1); 'email' => 'required|email|unique:users',
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:8|max:32', 'password' => 'required|min:8|max:32',
'nickname' => 'required|no_special_chars|max:255' 'nickname' => 'required|no_special_chars|max:255',
'captcha' => 'required'.(app()->environment('testing') ? '' : '|captcha')
]); ]);
if (! option('user_can_register')) { if (! option('user_can_register')) {
@ -119,37 +100,30 @@ class AuthController extends Controller
} }
// If amount of registered accounts of IP is more than allowed amounts, // If amount of registered accounts of IP is more than allowed amounts,
// then reject the register. // reject the registration.
if (User::where('ip', Utils::getClientIp())->count() < option('regs_per_ip')) if (User::where('ip', Utils::getClientIp())->count() < option('regs_per_ip')) {
{ $user = new User;
// Register a new user. $user->email = $data['email'];
// If the email is already registered, $user->nickname = $data['nickname'];
// it will return a false value. $user->score = option('user_initial_score');
$user = User::register( $user->avatar = 0;
$request->input('email'), $user->password = User::getEncryptedPwdFromEvent($data['password'], $user)
$request->input('password'), function($user) use ($request) ?: app('cipher')->hash($data['password'], config('secure.salt'));
{ $user->ip = Utils::getClientIp();
$user->ip = Utils::getClientIp(); $user->permission = User::NORMAL;
$user->score = option('user_initial_score'); $user->register_at = Utils::getTimeFormatted();
$user->register_at = Utils::getTimeFormatted(); $user->last_sign_at = Utils::getTimeFormatted(time() - 86400);
$user->last_sign_at = Utils::getTimeFormatted(time() - 86400);
$user->permission = User::NORMAL;
$user->nickname = $request->input('nickname');
});
if (! $user) { $user->save();
return json(trans('auth.register.registered'), 5);
}
event(new Events\UserRegistered($user)); event(new Events\UserRegistered($user));
Auth::login($user);
return json([ return json([
'errno' => 0, 'errno' => 0,
'msg' => trans('auth.register.success'), 'msg' => trans('auth.register.success')
'token' => $user->getToken(), ]);
]) // Set cookies
->withCookie('uid', $user->uid, 60)
->withCookie('token', $user->getToken(), 60);
} else { } else {
return json(trans('auth.register.max', ['regs' => option('regs_per_ip')]), 7); return json(trans('auth.register.max', ['regs' => option('regs_per_ip')]), 7);
@ -216,16 +190,7 @@ class AuthController extends Controller
public function captcha() public function captcha()
{ {
$builder = new \Gregwar\Captcha\CaptchaBuilder; return captcha();
$builder->build($width = 100, $height = 34);
Session::put('phrase', $builder->getPhrase());
ob_start();
$builder->output();
$captcha = ob_get_contents();
ob_end_clean();
return \Response::png($captcha);
} }
protected function checkCaptcha($request) protected function checkCaptcha($request)

View File

@ -9,6 +9,7 @@ use App\Models\Closet;
use App\Models\Texture; use App\Models\Texture;
use App\Models\ClosetModel; use App\Models\ClosetModel;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Exceptions\PrettyPageException; use App\Exceptions\PrettyPageException;
class ClosetController extends Controller class ClosetController extends Controller
@ -23,14 +24,14 @@ class ClosetController extends Controller
public function __construct() public function __construct()
{ {
$this->middleware(function ($request, $next) { $this->middleware(function ($request, $next) {
$this->closet = new Closet($request->session()->get('uid')); $this->closet = new Closet(Auth::id());
return $next($request); return $next($request);
}); });
} }
public function index() public function index()
{ {
return view('user.closet')->with('user', app('user.current')); return view('user.closet')->with('user', Auth::user());
} }
public function getClosetData(Request $request) public function getClosetData(Request $request)
@ -70,7 +71,9 @@ class ClosetController extends Controller
'name' => 'required|no_special_chars' 'name' => 'required|no_special_chars'
]); ]);
if (app('user.current')->getScore() < option('score_per_closet_item')) { $currentUser = Auth::user();
if ($currentUser->getScore() < option('score_per_closet_item')) {
return json(trans('user.closet.add.lack-score'), 7); return json(trans('user.closet.add.lack-score'), 7);
} }
@ -86,7 +89,7 @@ class ClosetController extends Controller
$this->closet->save(); $this->closet->save();
app('user.current')->setScore(option('score_per_closet_item'), 'minus'); $currentUser->setScore(option('score_per_closet_item'), 'minus');
return json(trans('user.closet.add.success', ['name' => $request->input('name')]), 0); return json(trans('user.closet.add.success', ['name' => $request->input('name')]), 0);
} else { } else {
@ -123,7 +126,7 @@ class ClosetController extends Controller
$this->closet->save(); $this->closet->save();
if (option('return_score')) if (option('return_score'))
app('user.current')->setScore(option('score_per_closet_item'), 'plus'); Auth::user()->setScore(option('score_per_closet_item'), 'plus');
return json(trans('user.closet.remove.success'), 0); return json(trans('user.closet.remove.success'), 0);
} else { } else {

View File

@ -2,14 +2,11 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\Repositories\UserRepository;
class HomeController extends Controller class HomeController extends Controller
{ {
public function index(UserRepository $users, Request $request) public function index()
{ {
return view('index')->with('user', $users->getCurrentUser()) return view('index')->with('user', auth()->user())
->with('home_pic_url', option('home_pic_url') ?: config('options.home_pic_url')); ->with('home_pic_url', option('home_pic_url') ?: config('options.home_pic_url'));
} }
} }

View File

@ -15,6 +15,7 @@ use App\Events\PlayerWasDeleted;
use App\Events\CheckPlayerExists; use App\Events\CheckPlayerExists;
use App\Events\PlayerWillBeAdded; use App\Events\PlayerWillBeAdded;
use App\Events\PlayerWillBeDeleted; use App\Events\PlayerWillBeDeleted;
use Illuminate\Support\Facades\Auth;
use App\Exceptions\PrettyPageException; use App\Exceptions\PrettyPageException;
use App\Http\Middleware\CheckPlayerExist; use App\Http\Middleware\CheckPlayerExist;
use App\Http\Middleware\CheckPlayerOwner; use App\Http\Middleware\CheckPlayerOwner;
@ -22,13 +23,6 @@ use App\Services\Repositories\UserRepository;
class PlayerController extends Controller class PlayerController extends Controller
{ {
/**
* User Instance.
*
* @var \App\Models\User
*/
private $user;
/** /**
* Player Instance. * Player Instance.
* *
@ -36,13 +30,9 @@ class PlayerController extends Controller
*/ */
private $player; private $player;
public function __construct(UserRepository $users) public function __construct()
{ {
$this->middleware(function ($request, $next) use ($users) { $this->middleware(function ($request, $next) {
$uid = $request->session()->get('uid');
$this->user = $users->get($uid);
if ($request->has('pid')) { if ($request->has('pid')) {
if ($this->player = Player::find($request->pid)) { if ($this->player = Player::find($request->pid)) {
$this->player->checkForInvalidTextures(); $this->player->checkForInvalidTextures();
@ -59,11 +49,16 @@ class PlayerController extends Controller
public function index() public function index()
{ {
return view('user.player')->with('players', $this->user->players->toArray())->with('user', $this->user); $user = Auth::user();
return view('user.player')
->with('players', $user->players->toArray())
->with('user', $user);
} }
public function add(Request $request) public function add(Request $request)
{ {
$user = Auth::user();
$this->validate($request, [ $this->validate($request, [
'player_name' => 'required|player_name|min:'.option('player_name_length_min').'|max:'.option('player_name_length_max') 'player_name' => 'required|player_name|min:'.option('player_name_length_min').'|max:'.option('player_name_length_max')
]); ]);
@ -74,7 +69,7 @@ class PlayerController extends Controller
return json(trans('user.player.add.repeated'), 6); return json(trans('user.player.add.repeated'), 6);
} }
if ($this->user->getScore() < Option::get('score_per_player')) { if ($user->getScore() < Option::get('score_per_player')) {
return json(trans('user.player.add.lack-score'), 7); return json(trans('user.player.add.lack-score'), 7);
} }
@ -82,7 +77,7 @@ class PlayerController extends Controller
$player = new Player; $player = new Player;
$player->uid = $this->user->uid; $player->uid = $user->uid;
$player->player_name = $request->input('player_name'); $player->player_name = $request->input('player_name');
$player->preference = "default"; $player->preference = "default";
$player->last_modified = Utils::getTimeFormatted(); $player->last_modified = Utils::getTimeFormatted();
@ -90,12 +85,12 @@ class PlayerController extends Controller
event(new PlayerWasAdded($player)); event(new PlayerWasAdded($player));
$this->user->setScore(option('score_per_player'), 'minus'); $user->setScore(option('score_per_player'), 'minus');
return json(trans('user.player.add.success', ['name' => $request->input('player_name')]), 0); return json(trans('user.player.add.success', ['name' => $request->input('player_name')]), 0);
} }
public function delete(Request $request) public function delete()
{ {
$playerName = $this->player->player_name; $playerName = $this->player->player_name;
@ -104,7 +99,7 @@ class PlayerController extends Controller
$this->player->delete(); $this->player->delete();
if (option('return_score')) { if (option('return_score')) {
$this->user->setScore(Option::get('score_per_player'), 'plus'); Auth::user()->setScore(Option::get('score_per_player'), 'plus');
} }
event(new PlayerWasDeleted($playerName)); event(new PlayerWasDeleted($playerName));

View File

@ -59,7 +59,7 @@ class SetupController extends Controller
public function finish(Request $request) public function finish(Request $request)
{ {
$this->validate($request, [ $data = $this->validate($request, [
'email' => 'required|email', 'email' => 'required|email',
'password' => 'required|min:8|max:32|confirmed', 'password' => 'required|min:8|max:32|confirmed',
'site_name' => 'required' 'site_name' => 'required'
@ -70,11 +70,6 @@ class SetupController extends Controller
if (is_writable(app()->environmentFile())) { if (is_writable(app()->environmentFile())) {
Artisan::call('key:random'); Artisan::call('key:random');
Artisan::call('salt:random'); Artisan::call('salt:random');
Log::info("[SetupWizard] Random application key & salt set successfully.", [
'key' => config('app.key'),
'salt' => config('secure.salt')
]);
} else { } else {
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
Log::warning("[SetupWizard] Failed to set application key. No write permission."); Log::warning("[SetupWizard] Failed to set application key. No write permission.");
@ -97,20 +92,21 @@ class SetupController extends Controller
Option::set('site_url', $siteUrl); Option::set('site_url', $siteUrl);
// Register super admin // Register super admin
$user = User::register( $user = new User;
$request->input('email'), $user->email = $data['email'];
$request->input('password'), function ($user) $user->nickname = '';
{ $user->score = option('user_initial_score');
$user->ip = Utils::getClientIp(); $user->avatar = 0;
$user->score = option('user_initial_score'); $user->password = User::getEncryptedPwdFromEvent($data['password'], $user)
$user->register_at = Utils::getTimeFormatted(); ?: app('cipher')->hash($data['password'], config('secure.salt'));
$user->last_sign_at = Utils::getTimeFormatted(time() - 86400); $user->ip = Utils::getClientIp();
$user->permission = User::SUPER_ADMIN; $user->permission = User::SUPER_ADMIN;
}); $user->register_at = Utils::getTimeFormatted();
Log::info("[SetupWizard] Super Admin registered.", ['user' => $user]); $user->last_sign_at = Utils::getTimeFormatted(time() - 86400);
$user->save();
$this->createDirectories(); $this->createDirectories();
Log::info("[SetupWizard] Installation completed.");
return view('setup.wizard.finish')->with([ return view('setup.wizard.finish')->with([
'email' => $request->input('email'), 'email' => $request->input('email'),

View File

@ -13,24 +13,15 @@ use App\Models\Player;
use App\Models\Texture; use App\Models\Texture;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use App\Exceptions\PrettyPageException; use App\Exceptions\PrettyPageException;
use App\Services\Repositories\UserRepository; use App\Services\Repositories\UserRepository;
class SkinlibController extends Controller class SkinlibController extends Controller
{ {
protected $user = null;
public function __construct(UserRepository $users)
{
$this->middleware(function ($request, $next) use ($users) {
$this->user = $users->get($request->session()->get('uid'));
return $next($request);
});
}
public function index() public function index()
{ {
return view('skinlib.index', ['user' => $this->user]); return view('skinlib.index', ['user' => Auth::user()]);
} }
/** /**
@ -42,6 +33,7 @@ class SkinlibController extends Controller
*/ */
public function getSkinlibFiltered(Request $request) public function getSkinlibFiltered(Request $request)
{ {
$currentUser = Auth::user();
// Available filters: skin, steve, alex, cape // Available filters: skin, steve, alex, cape
$filter = $request->input('filter', 'skin'); $filter = $request->input('filter', 'skin');
@ -65,7 +57,7 @@ class SkinlibController extends Controller
$keyword = $request->input('keyword', ''); $keyword = $request->input('keyword', '');
// Check if user logged in // Check if user logged in
$anonymous = is_null($this->user); $anonymous = !Auth::check();
if ($filter == "skin") { if ($filter == "skin") {
$query = Texture::where(function ($innerQuery) { $query = Texture::where(function ($innerQuery) {
@ -89,9 +81,9 @@ class SkinlibController extends Controller
$query = $query->where('public', true); $query = $query->where('public', true);
} else { } else {
// Show private textures when show uploaded textures of current user // Show private textures when show uploaded textures of current user
if ($uploader != $this->user->uid && !$this->user->isAdmin()) { if ($uploader != $currentUser->uid && !$currentUser->isAdmin()) {
$query = $query->where(function ($innerQuery) { $query = $query->where(function ($innerQuery) use ($currentUser) {
$innerQuery->where('public', true)->orWhere('uploader', '=', $this->user->uid); $innerQuery->where('public', true)->orWhere('uploader', '=', $currentUser->uid);
}); });
} }
} }
@ -104,7 +96,7 @@ class SkinlibController extends Controller
->get(); ->get();
if (! $anonymous) { if (! $anonymous) {
$closet = new Closet($this->user->uid); $closet = new Closet($currentUser->uid);
foreach ($textures as $item) { foreach ($textures as $item) {
$item->liked = $closet->has($item->tid); $item->liked = $closet->has($item->tid);
} }
@ -120,6 +112,7 @@ class SkinlibController extends Controller
public function show($tid) public function show($tid)
{ {
$texture = Texture::find($tid); $texture = Texture::find($tid);
$user = Auth::user();
if (! $texture || $texture && !Storage::disk('textures')->has($texture->hash)) { if (! $texture || $texture && !Storage::disk('textures')->has($texture->hash)) {
if (option('auto_del_invalid_texture')) { if (option('auto_del_invalid_texture')) {
@ -133,11 +126,14 @@ class SkinlibController extends Controller
} }
if (!$texture->public) { if (!$texture->public) {
if (is_null($this->user) || ($this->user->uid != $texture->uploader && !$this->user->isAdmin())) if (!Auth::check() || ($user->uid != $texture->uploader && !$user->isAdmin()))
abort(403, trans('skinlib.show.private')); abort(403, trans('skinlib.show.private'));
} }
return view('skinlib.show')->with('texture', $texture)->with('with_out_filter', true)->with('user', $this->user); return view('skinlib.show')
->with('texture', $texture)
->with('with_out_filter', true)
->with('user', $user);
} }
public function info($tid) public function info($tid)
@ -151,15 +147,14 @@ class SkinlibController extends Controller
public function upload() public function upload()
{ {
return view('skinlib.upload')->with('user', $this->user)->with('with_out_filter', true); return view('skinlib.upload')
->with('user', Auth::user())
->with('with_out_filter', true);
} }
public function handleUpload(Request $request) public function handleUpload(Request $request)
{ {
// Hacking for testing $user = Auth::user();
if (config('app.env') == 'testing') {
$this->user = User::find($this->user->uid);
}
if (($response = $this->checkUpload($request)) instanceof JsonResponse) { if (($response = $this->checkUpload($request)) instanceof JsonResponse) {
return $response; return $response;
@ -172,13 +167,13 @@ class SkinlibController extends Controller
$t->hash = bs_hash_file($request->file('file')); $t->hash = bs_hash_file($request->file('file'));
$t->size = ceil($request->file('file')->getSize() / 1024); $t->size = ceil($request->file('file')->getSize() / 1024);
$t->public = $request->input('public') == 'true'; $t->public = $request->input('public') == 'true';
$t->uploader = $this->user->uid; $t->uploader = $user->uid;
$t->upload_at = Utils::getTimeFormatted(); $t->upload_at = Utils::getTimeFormatted();
$cost = $t->size * ($t->public ? Option::get('score_per_storage') : Option::get('private_score_per_storage')); $cost = $t->size * ($t->public ? Option::get('score_per_storage') : Option::get('private_score_per_storage'));
$cost += option('score_per_closet_item'); $cost += option('score_per_closet_item');
if ($this->user->getScore() < $cost) if ($user->getScore() < $cost)
return json(trans('skinlib.upload.lack-score'), 7); return json(trans('skinlib.upload.lack-score'), 7);
$results = Texture::where('hash', $t->hash)->get(); $results = Texture::where('hash', $t->hash)->get();
@ -201,9 +196,9 @@ class SkinlibController extends Controller
$t->save(); $t->save();
$this->user->setScore($cost, 'minus'); $user->setScore($cost, 'minus');
if ($this->user->getCloset()->add($t->tid, $t->name)) { if ($user->getCloset()->add($t->tid, $t->name)) {
return json(trans('skinlib.upload.success', ['name' => $request->input('name')]), 0, [ return json(trans('skinlib.upload.success', ['name' => $request->input('name')]), 0, [
'tid' => $t->tid 'tid' => $t->tid
]); ]);
@ -213,12 +208,13 @@ class SkinlibController extends Controller
public function delete(Request $request, UserRepository $users) public function delete(Request $request, UserRepository $users)
{ {
$result = Texture::find($request->tid); $result = Texture::find($request->tid);
$user = Auth::user();
if (! $result) { if (! $result) {
return json(trans('skinlib.non-existent'), 1); return json(trans('skinlib.non-existent'), 1);
} }
if ($result->uploader != $this->user->uid && !$this->user->isAdmin()) { if ($result->uploader != $user->uid && !$user->isAdmin()) {
return json(trans('skinlib.no-permission'), 1); return json(trans('skinlib.no-permission'), 1);
} }
@ -249,11 +245,12 @@ class SkinlibController extends Controller
public function privacy(Request $request, UserRepository $users) public function privacy(Request $request, UserRepository $users)
{ {
$t = Texture::find($request->input('tid')); $t = Texture::find($request->input('tid'));
$user = Auth::user();
if (! $t) if (! $t)
return json(trans('skinlib.non-existent'), 1); return json(trans('skinlib.non-existent'), 1);
if ($t->uploader != $this->user->uid && !$this->user->isAdmin()) if ($t->uploader != $user->uid && !$user->isAdmin())
return json(trans('skinlib.no-permission'), 1); return json(trans('skinlib.no-permission'), 1);
$score_diff = $t->size * (option('private_score_per_storage') - option('score_per_storage')) * ($t->public ? -1 : 1); $score_diff = $t->size * (option('private_score_per_storage') - option('score_per_storage')) * ($t->public ? -1 : 1);
@ -285,13 +282,13 @@ class SkinlibController extends Controller
'tid' => 'required|integer', 'tid' => 'required|integer',
'new_name' => 'required|no_special_chars' 'new_name' => 'required|no_special_chars'
]); ]);
$user = Auth::user();
$t = Texture::find($request->input('tid')); $t = Texture::find($request->input('tid'));
if (! $t) if (! $t)
return json(trans('skinlib.non-existent'), 1); return json(trans('skinlib.non-existent'), 1);
if ($t->uploader != $this->user->uid && !$this->user->isAdmin()) if ($t->uploader != $user->uid && !$user->isAdmin())
return json(trans('skinlib.no-permission'), 1); return json(trans('skinlib.no-permission'), 1);
$t->name = $request->input('new_name'); $t->name = $request->input('new_name');

View File

@ -9,33 +9,20 @@ use App\Models\User;
use App\Models\Texture; use App\Models\Texture;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Events\UserProfileUpdated; use App\Events\UserProfileUpdated;
use Illuminate\Support\Facades\Auth;
use App\Exceptions\PrettyPageException; use App\Exceptions\PrettyPageException;
use App\Services\Repositories\UserRepository; use App\Services\Repositories\UserRepository;
class UserController extends Controller class UserController extends Controller
{ {
/**
* Current user instance.
*
* @var App\Models\User
*/
private $user = null;
public function __construct(UserRepository $users)
{
$this->middleware(function ($request, $next) use ($users) {
$this->user = $users->get($request->session()->get('uid'));
return $next($request);
});
}
public function index() public function index()
{ {
$user = Auth::user();
return view('user.index')->with([ return view('user.index')->with([
'user' => $this->user, 'user' => $user,
'statistics' => [ 'statistics' => [
'players' => $this->calculatePercentageUsed($this->user->players->count(), option('score_per_player')), 'players' => $this->calculatePercentageUsed($user->players->count(), option('score_per_player')),
'storage' => $this->calculatePercentageUsed($this->user->getStorageUsed(), option('score_per_storage')) 'storage' => $this->calculatePercentageUsed($user->getStorageUsed(), option('score_per_storage'))
] ]
]); ]);
} }
@ -49,13 +36,14 @@ class UserController extends Controller
*/ */
protected function calculatePercentageUsed($used, $rate) protected function calculatePercentageUsed($used, $rate)
{ {
$user = Auth::user();
// Initialize default value to avoid division by zero. // Initialize default value to avoid division by zero.
$result['used'] = $used; $result['used'] = $used;
$result['total'] = 'UNLIMITED'; $result['total'] = 'UNLIMITED';
$result['percentage'] = 0; $result['percentage'] = 0;
if ($rate != 0) { if ($rate != 0) {
$result['total'] = $used + floor($this->user->getScore() / $rate); $result['total'] = $used + floor($user->getScore() / $rate);
$result['percentage'] = $result['total'] ? $used / $result['total'] * 100 : 100; $result['percentage'] = $result['total'] ? $used / $result['total'] * 100 : 100;
} }
@ -69,14 +57,15 @@ class UserController extends Controller
*/ */
public function sign() public function sign()
{ {
if ($this->user->canSign()) { $user = Auth::user();
$acquiredScore = $this->user->sign(); if ($user->canSign()) {
$acquiredScore = $user->sign();
return json([ return json([
'errno' => 0, 'errno' => 0,
'msg' => trans('user.sign-success', ['score' => $acquiredScore]), 'msg' => trans('user.sign-success', ['score' => $acquiredScore]),
'score' => $this->user->getScore(), 'score' => $user->getScore(),
'storage' => $this->calculatePercentageUsed($this->user->getStorageUsed(), option('score_per_storage')), 'storage' => $this->calculatePercentageUsed($user->getStorageUsed(), option('score_per_storage')),
'remaining_time' => $this->getUserSignRemainingTimeWithPrecision() 'remaining_time' => $this->getUserSignRemainingTimeWithPrecision()
]); ]);
} else { } else {
@ -92,14 +81,14 @@ class UserController extends Controller
public function getUserSignRemainingTimeWithPrecision() public function getUserSignRemainingTimeWithPrecision()
{ {
$hours = $this->user->getSignRemainingTime() / 3600; $hours = Auth::user()->getSignRemainingTime() / 3600;
return $hours > 1 ? round($hours) : $hours; return $hours > 1 ? round($hours) : $hours;
} }
public function profile() public function profile()
{ {
return view('user.profile')->with('user', $this->user); return view('user.profile')->with('user', Auth::user());
} }
/** /**
@ -112,6 +101,7 @@ class UserController extends Controller
public function handleProfile(Request $request, UserRepository $users) public function handleProfile(Request $request, UserRepository $users)
{ {
$action = $request->input('action', ''); $action = $request->input('action', '');
$user = Auth::user();
switch ($action) { switch ($action) {
case 'nickname': case 'nickname':
@ -121,8 +111,8 @@ class UserController extends Controller
$nickname = $request->input('new_nickname'); $nickname = $request->input('new_nickname');
if ($this->user->setNickName($nickname)) { if ($user->setNickName($nickname)) {
event(new UserProfileUpdated($action, $this->user)); event(new UserProfileUpdated($action, $user));
return json(trans('user.profile.nickname.success', ['nickname' => $nickname]), 0); return json(trans('user.profile.nickname.success', ['nickname' => $nickname]), 0);
} }
@ -134,17 +124,15 @@ class UserController extends Controller
'new_password' => 'required|min:8|max:32' 'new_password' => 'required|min:8|max:32'
]); ]);
if (! $this->user->verifyPassword($request->input('current_password'))) if (! $user->verifyPassword($request->input('current_password')))
return json(trans('user.profile.password.wrong-password'), 1); return json(trans('user.profile.password.wrong-password'), 1);
if ($this->user->changePassword($request->input('new_password'))) { if ($user->changePassword($request->input('new_password'))) {
event(new UserProfileUpdated($action, $this->user)); event(new UserProfileUpdated($action, $user));
session()->flush(); Auth::logout();
return json(trans('user.profile.password.success'), 0) return json(trans('user.profile.password.success'), 0);
->withCookie(cookie()->forget('uid'))
->withCookie(cookie()->forget('token'));
} }
break; // @codeCoverageIgnore break; // @codeCoverageIgnore
@ -159,15 +147,15 @@ class UserController extends Controller
return json(trans('user.profile.email.existed'), 1); return json(trans('user.profile.email.existed'), 1);
} }
if (! $this->user->verifyPassword($request->input('password'))) if (! $user->verifyPassword($request->input('password')))
return json(trans('user.profile.email.wrong-password'), 1); return json(trans('user.profile.email.wrong-password'), 1);
if ($this->user->setEmail($request->input('new_email'))) { if ($user->setEmail($request->input('new_email'))) {
event(new UserProfileUpdated($action, $this->user)); event(new UserProfileUpdated($action, $user));
return json(trans('user.profile.email.success'), 0) Auth::logout();
->withCookie(cookie()->forget('uid'))
->withCookie(cookie()->forget('token')); return json(trans('user.profile.email.success'), 0);
} }
break; // @codeCoverageIgnore break; // @codeCoverageIgnore
@ -177,10 +165,10 @@ class UserController extends Controller
'password' => 'required|min:6|max:32' 'password' => 'required|min:6|max:32'
]); ]);
if (! $this->user->verifyPassword($request->input('password'))) if (! $user->verifyPassword($request->input('password')))
return json(trans('user.profile.delete.wrong-password'), 1); return json(trans('user.profile.delete.wrong-password'), 1);
Auth::logout();
if ($this->user->delete()) { if ($user->delete()) {
session()->flush(); session()->flush();
return response() return response()
@ -215,7 +203,7 @@ class UserController extends Controller
if ($result->type == "cape") if ($result->type == "cape")
return json(trans('user.profile.avatar.wrong-type'), 1); return json(trans('user.profile.avatar.wrong-type'), 1);
if ($this->user->setAvatar($request->input('tid'))) { if (Auth::user()->setAvatar($request->input('tid'))) {
return json(trans('user.profile.avatar.success'), 0); return json(trans('user.profile.avatar.success'), 0);
} }
} else { } else {

View File

@ -6,13 +6,7 @@ class CheckAdministrator
{ {
public function handle($request, \Closure $next) public function handle($request, \Closure $next)
{ {
$result = (new CheckAuthenticated)->handle($request, $next, true); if (! auth()->user()->isAdmin()) {
if ($result instanceof \Illuminate\Http\RedirectResponse) {
return $result;
}
if (! $result->isAdmin()) {
abort(403, trans('auth.check.admin')); abort(403, trans('auth.check.admin'));
} }

View File

@ -10,29 +10,18 @@ use Session;
use Closure; use Closure;
use App\Models\User; use App\Models\User;
use App\Events\UserAuthenticated; use App\Events\UserAuthenticated;
use Illuminate\Support\Facades\Auth;
class CheckAuthenticated class CheckAuthenticated
{ {
public function handle($request, Closure $next, $returnUser = false) public function handle($request, Closure $next)
{ {
if (Session::has('uid')) { if (Auth::check()) {
if (! app()->bound('user.current')) { $user = Auth::user();
// Bind current user to container
$user = app('users')->get(session('uid'));
app()->instance('user.current', $user);
} else {
$user = app('user.current');
}
if (session('token') != $user->getToken()) { if ($user->permission == User::BANNED) {
$this->flashLastRequestedPath(); Auth::logout();
return redirect('auth/login')->with('msg', trans('auth.check.token'));
}
if ($user->getPermission() == "-1") {
delete_sessions();
delete_cookies();
abort(403, trans('auth.check.banned')); abort(403, trans('auth.check.banned'));
} }
@ -44,29 +33,24 @@ class CheckAuthenticated
event(new UserAuthenticated($user)); event(new UserAuthenticated($user));
return $returnUser ? $user : $next($request); return $next($request);
} else { } else {
$this->flashLastRequestedPath(); $this->flashLastRequestedPath();
return redirect('auth/login')->with('msg', trans('auth.check.anonymous')); return redirect('auth/login')->with('msg', trans('auth.check.anonymous'));
} }
return $next($request);
} }
public function askForFillingEmail($request, Closure $next) public function askForFillingEmail($request, Closure $next)
{ {
$user = app('user.current'); $user = Auth::user();
if (isset($request->email)) { if (isset($request->email)) {
if (filter_var($request->email, FILTER_VALIDATE_EMAIL)) { if (filter_var($request->email, FILTER_VALIDATE_EMAIL)) {
if (User::where('email', $request->email)->get()->isEmpty()) { if (User::where('email', $request->email)->get()->isEmpty()) {
$user->setEmail($request->email); $user->setEmail($request->email);
// Refresh token
Session::put('token', $user->getToken(true));
Cookie::queue('token', $user->getToken(), 60);
return $next($request); return $next($request);
} else { } else {

View File

@ -19,7 +19,7 @@ class CheckPlayerOwner
if ($pid = $request->input('pid')) { if ($pid = $request->input('pid')) {
$player = Player::find($pid); $player = Player::find($pid);
if ($player->uid != app('user.current')->uid) { if ($player->uid != auth()->id()) {
return response()->json([ return response()->json([
'errno' => 1, 'errno' => 1,
'msg' => trans('admin.players.no-permission') 'msg' => trans('admin.players.no-permission')

View File

@ -1,39 +0,0 @@
<?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 into repository
app('users')->set($user->uid, $user);
// Bind current user to container
app()->instance('user.current', $user);
} else {
// Remove sessions & cookies
delete_sessions();
delete_cookies();
return redirect('auth/login')->with('msg', trans('auth.check.token'));
}
}
return $next($request);
}
}

View File

@ -4,20 +4,12 @@ namespace App\Http\Middleware;
use App; use App;
use Session; use Session;
use App\Models\User; use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated class RedirectIfAuthenticated
{ {
public function handle($request, \Closure $next) public function handle($request, \Closure $next)
{ {
if (session()->has('uid')) { return Auth::check() ? redirect('user') : $next($request);
if (session('token') != app('users')->get(session('uid'))->getToken()) {
Session::put('msg', trans('auth.check.token')); // @codeCoverageIgnore
} else {
return redirect('user');
}
}
return $next($request);
} }
} }

View File

@ -6,9 +6,9 @@ use DB;
use Utils; use Utils;
use Carbon\Carbon; use Carbon\Carbon;
use App\Events\EncryptUserPassword; use App\Events\EncryptUserPassword;
use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Model class User extends Authenticatable
{ {
/** /**
* Permissions. * Permissions.
@ -18,12 +18,6 @@ class User extends Model
const ADMIN = 1; const ADMIN = 1;
const SUPER_ADMIN = 2; const SUPER_ADMIN = 2;
/**
* User Token.
* @var string
*/
protected $token;
/** /**
* Instance of Closet. * Instance of Closet.
* @var \App\Models\Closet * @var \App\Models\Closet
@ -103,41 +97,13 @@ class User extends Model
* @param User $user * @param User $user
* @return mixed * @return mixed
*/ */
protected static function getEncryptedPwdFromEvent($rawPasswd, User $user) public static function getEncryptedPwdFromEvent($rawPasswd, User $user)
{ {
$responses = event(new EncryptUserPassword($rawPasswd, $user)); $responses = event(new EncryptUserPassword($rawPasswd, $user));
return array_get($responses, 0); return array_get($responses, 0);
} }
/**
* 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;
// Pass the user instance to the callback
call_user_func($callback, $user);
// Save once to get uid
$user->password = '';
$user->save();
// Save again with password
$user->password = static::getEncryptedPwdFromEvent($password, $user) ?: app('cipher')->hash($password, config('secure.salt'));
$user->save();
return $user;
}
/** /**
* Change password of the user. * Change password of the user.
* *
@ -216,21 +182,6 @@ class User extends Model
return $this->save(); return $this->save();
} }
/**
* Get user token or generate one.
*
* @param bool $refresh Refresh token forcely.
* @return string
*/
public function getToken($refresh = false)
{
if (! $this->token || $refresh) {
$this->token = md5($this->email . $this->password . config('secure.salt'));
}
return $this->token;
}
/** /**
* Get current score of user. * Get current score of user.
* *
@ -402,4 +353,9 @@ class User extends Model
{ {
return $query->where($field, 'LIKE', "%$value%"); return $query->where($field, 'LIKE', "%$value%");
} }
public function getAuthIdentifier()
{
return $this->uid;
}
} }

View File

@ -4,7 +4,6 @@ namespace App\Providers;
use Illuminate\Routing\Router; use Illuminate\Routing\Router;
use App\Events\ConfigureRoutes; use App\Events\ConfigureRoutes;
use App\Http\Middleware\CheckSessionUserValid;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider class RouteServiceProvider extends ServiceProvider
@ -56,7 +55,7 @@ class RouteServiceProvider extends ServiceProvider
protected function mapWebRoutes(Router $router) protected function mapWebRoutes(Router $router)
{ {
$router->group([ $router->group([
'middleware' => ['web', CheckSessionUserValid::class], 'middleware' => ['web'],
'namespace' => $this->namespace, 'namespace' => $this->namespace,
], function ($router) { ], function ($router) {
require base_path('routes/web.php'); require base_path('routes/web.php');

View File

@ -74,6 +74,6 @@ class UserRepository extends Repository
public function getCurrentUser() public function getCurrentUser()
{ {
return $this->get(session('uid')); return auth()->user();
} }
} }

View File

@ -406,26 +406,6 @@ 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();
}
}
if (! function_exists('runtime_check')) { if (! function_exists('runtime_check')) {
function runtime_check(array $requirements) function runtime_check(array $requirements)

View File

@ -6,7 +6,6 @@
"php": ">=7.1.3", "php": ">=7.1.3",
"filp/whoops": "^2.1", "filp/whoops": "^2.1",
"predis/predis": "~1.0", "predis/predis": "~1.0",
"gregwar/captcha": "^1.1",
"erusev/parsedown": "^1.6", "erusev/parsedown": "^1.6",
"swiggles/memcache": "^2.0", "swiggles/memcache": "^2.0",
"doctrine/inflector": "1.1.0", "doctrine/inflector": "1.1.0",
@ -14,7 +13,8 @@
"nesbot/carbon": "^1.32.0", "nesbot/carbon": "^1.32.0",
"devitek/yaml-translation": "^4.1.0", "devitek/yaml-translation": "^4.1.0",
"printempw/laravel-datatables-lite": "^1.0", "printempw/laravel-datatables-lite": "^1.0",
"composer/semver": "^1.4" "composer/semver": "^1.4",
"mews/captcha": "^2.2"
}, },
"require-dev": { "require-dev": {
"fzaninotto/faker": "~1.4", "fzaninotto/faker": "~1.4",

255
composer.lock generated
View File

@ -1,10 +1,10 @@
{ {
"_readme": [ "_readme": [
"This file locks the dependencies of your project to a known state", "This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "a410c854791711695111f43f6ba32bee", "content-hash": "03887f717dd02991b300a10cc712bd52",
"packages": [ "packages": [
{ {
"name": "composer/semver", "name": "composer/semver",
@ -449,32 +449,115 @@
"time": "2018-03-03T17:56:25+00:00" "time": "2018-03-03T17:56:25+00:00"
}, },
{ {
"name": "gregwar/captcha", "name": "guzzlehttp/psr7",
"version": "v1.1.6", "version": "1.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Gregwar/Captcha.git", "url": "https://github.com/guzzle/psr7.git",
"reference": "a96d8dffc80d6213958bd19fbdef1555e8b63ca3" "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Gregwar/Captcha/zipball/a96d8dffc80d6213958bd19fbdef1555e8b63ca3", "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"reference": "a96d8dffc80d6213958bd19fbdef1555e8b63ca3", "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-gd": "*", "php": ">=5.4.0",
"ext-mbstring": "*", "psr/http-message": "~1.0"
"php": ">=5.3.0", },
"symfony/finder": "~3.0|~4.0" "provide": {
"psr/http-message-implementation": "1.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.4" "phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
}, },
"type": "captcha",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Gregwar\\": "src/Gregwar" "GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2017-03-20T17:10:46+00:00"
},
{
"name": "intervention/image",
"version": "2.4.2",
"source": {
"type": "git",
"url": "https://github.com/Intervention/image.git",
"reference": "e82d274f786e3d4b866a59b173f42e716f0783eb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Intervention/image/zipball/e82d274f786e3d4b866a59b173f42e716f0783eb",
"reference": "e82d274f786e3d4b866a59b173f42e716f0783eb",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"guzzlehttp/psr7": "~1.1",
"php": ">=5.4.0"
},
"require-dev": {
"mockery/mockery": "~0.9.2",
"phpunit/phpunit": "^4.8 || ^5.7"
},
"suggest": {
"ext-gd": "to use GD library based image processing.",
"ext-imagick": "to use Imagick based image processing.",
"intervention/imagecache": "Caching extension for the Intervention Image library"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.4-dev"
},
"laravel": {
"providers": [
"Intervention\\Image\\ImageServiceProvider"
],
"aliases": {
"Image": "Intervention\\Image\\Facades\\Image"
}
}
},
"autoload": {
"psr-4": {
"Intervention\\Image\\": "src/Intervention/Image"
} }
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
@ -483,23 +566,22 @@
], ],
"authors": [ "authors": [
{ {
"name": "Grégoire Passault", "name": "Oliver Vogel",
"email": "g.passault@gmail.com", "email": "oliver@olivervogel.com",
"homepage": "http://www.gregwar.com/" "homepage": "http://olivervogel.com/"
},
{
"name": "Jeremy Livingston",
"email": "jeremy.j.livingston@gmail.com"
} }
], ],
"description": "Captcha generator", "description": "Image handling and manipulation library with support for Laravel integration",
"homepage": "https://github.com/Gregwar/Captcha", "homepage": "http://image.intervention.io/",
"keywords": [ "keywords": [
"bot", "gd",
"captcha", "image",
"spam" "imagick",
"laravel",
"thumbnail",
"watermark"
], ],
"time": "2018-04-24T09:20:08+00:00" "time": "2018-05-29T14:19:03+00:00"
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
@ -788,6 +870,73 @@
], ],
"time": "2017-06-12T11:04:56+00:00" "time": "2017-06-12T11:04:56+00:00"
}, },
{
"name": "mews/captcha",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/mewebstudio/captcha.git",
"reference": "c9885e31bb2c30fe185c1af6078a53a3bef5db8f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mewebstudio/captcha/zipball/c9885e31bb2c30fe185c1af6078a53a3bef5db8f",
"reference": "c9885e31bb2c30fe185c1af6078a53a3bef5db8f",
"shasum": ""
},
"require": {
"ext-gd": "*",
"illuminate/config": "~5.0",
"illuminate/filesystem": "~5.0",
"illuminate/hashing": "~5.0",
"illuminate/support": "~5.0",
"intervention/image": "~2.2",
"php": ">=5.4"
},
"require-dev": {
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~4.1"
},
"type": "package",
"extra": {
"laravel": {
"providers": [
"Mews\\Captcha\\CaptchaServiceProvider"
],
"aliases": {
"Captcha": "Mews\\Captcha\\Facades\\Captcha"
}
}
},
"autoload": {
"psr-4": {
"Mews\\Captcha\\": "src/"
},
"files": [
"src/helpers.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Muharrem ERİN",
"email": "me@mewebstudio.com",
"homepage": "https://github.com/mewebstudio",
"role": "Developer"
}
],
"description": "Laravel 5 Captcha Package",
"homepage": "https://github.com/mewebstudio/captcha",
"keywords": [
"captcha",
"laravel5 Captcha",
"laravel5 Security"
],
"time": "2018-04-25T13:44:49+00:00"
},
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "1.23.0", "version": "1.23.0",
@ -1126,6 +1275,56 @@
], ],
"time": "2017-02-14T16:28:37+00:00" "time": "2017-02-14T16:28:37+00:00"
}, },
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{ {
"name": "psr/log", "name": "psr/log",
"version": "1.0.2", "version": "1.0.2",

View File

@ -162,6 +162,7 @@ return [
Devitek\Core\Translation\TranslationServiceProvider::class, Devitek\Core\Translation\TranslationServiceProvider::class,
Swiggles\Memcache\MemcacheServiceProvider::class, Swiggles\Memcache\MemcacheServiceProvider::class,
Yajra\Datatables\DatatablesServiceProvider::class, Yajra\Datatables\DatatablesServiceProvider::class,
Mews\Captcha\CaptchaServiceProvider::class,
/** /**
* Application Service Providers... * Application Service Providers...

102
config/auth.php Normal file
View File

@ -0,0 +1,102 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
],
];

45
config/captcha.php Normal file
View File

@ -0,0 +1,45 @@
<?php
return [
'characters' => '2346789abcdefghjmnpqrtuxyzABCDEFGHJMNPQRTUXYZ',
'default' => [
'length' => 5,
'width' => 100,
'height' => 34,
'quality' => 90,
],
'flat' => [
'length' => 6,
'width' => 160,
'height' => 46,
'quality' => 90,
'lines' => 6,
'bgImage' => false,
'bgColor' => '#ecf2f4',
'fontColors'=> ['#2c3e50', '#c0392b', '#16a085', '#c0392b', '#8e44ad', '#303f9f', '#f57c00', '#795548'],
'contrast' => -5,
],
'mini' => [
'length' => 3,
'width' => 60,
'height' => 32,
],
'inverse' => [
'length' => 5,
'width' => 120,
'height' => 36,
'quality' => 90,
'sensitive' => true,
'angle' => 12,
'sharpen' => 10,
'blur' => 2,
'invert' => true,
'contrast' => -5,
]
];

View File

@ -110,13 +110,13 @@ return [
'db' => true, // Show database (PDO) queries and bindings 'db' => true, // Show database (PDO) queries and bindings
'views' => true, // Views with their data 'views' => true, // Views with their data
'route' => true, // Current route information 'route' => true, // Current route information
'auth' => false, // Display Laravel authentication status 'auth' => true, // Display Laravel authentication status
'gate' => true, // Display Laravel Gate checks 'gate' => false, // Display Laravel Gate checks
'session' => true, // Display session data 'session' => true, // Display session data
'symfony_request' => true, // Only one can be enabled.. 'symfony_request' => true, // Only one can be enabled..
'mail' => true, // Catch mail messages 'mail' => false, // Catch mail messages
'laravel' => false, // Laravel version and environment 'laravel' => false, // Laravel version and environment
'events' => false, // All events fired 'events' => true, // All events fired
'default_request' => false, // Regular or special Symfony request logger 'default_request' => false, // Regular or special Symfony request logger
'logs' => false, // Add the latest log messages 'logs' => false, // Add the latest log messages
'files' => false, // Show the included files 'files' => false, // Show the included files

View File

@ -11,8 +11,8 @@ $factory->define(User::class, function (Faker\Generator $faker) {
'password' => app('cipher')->hash(str_random(10), config('secure.salt')), 'password' => app('cipher')->hash(str_random(10), config('secure.salt')),
'ip' => '127.0.0.1', 'ip' => '127.0.0.1',
'permission' => 0, 'permission' => 0,
'last_sign_at' => $faker->dateTime, 'last_sign_at' => $faker->dateTime->format('d-M-Y H:i:s'),
'register_at' => $faker->dateTime 'register_at' => $faker->dateTime->format('d-M-Y H:i:s')
]; ];
}); });
@ -25,8 +25,8 @@ $factory->defineAs(User::class, 'admin', function (Faker\Generator $faker) {
'password' => app('cipher')->hash(str_random(10), config('secure.salt')), 'password' => app('cipher')->hash(str_random(10), config('secure.salt')),
'ip' => '127.0.0.1', 'ip' => '127.0.0.1',
'permission' => 1, 'permission' => 1,
'last_sign_at' => $faker->dateTime, 'last_sign_at' => $faker->dateTime->format('d-M-Y H:i:s'),
'register_at' => $faker->dateTime 'register_at' => $faker->dateTime->format('d-M-Y H:i:s')
]; ];
}); });
@ -39,8 +39,8 @@ $factory->defineAs(User::class, 'superAdmin', function (Faker\Generator $faker)
'password' => app('cipher')->hash(str_random(10), config('secure.salt')), 'password' => app('cipher')->hash(str_random(10), config('secure.salt')),
'ip' => '127.0.0.1', 'ip' => '127.0.0.1',
'permission' => 2, 'permission' => 2,
'last_sign_at' => $faker->dateTime, 'last_sign_at' => $faker->dateTime->format('d-M-Y H:i:s'),
'register_at' => $faker->dateTime 'register_at' => $faker->dateTime->format('d-M-Y H:i:s')
]; ];
}); });
@ -53,7 +53,7 @@ $factory->defineAs(User::class, 'banned', function (Faker\Generator $faker) {
'password' => app('cipher')->hash(str_random(10), config('secure.salt')), 'password' => app('cipher')->hash(str_random(10), config('secure.salt')),
'ip' => '127.0.0.1', 'ip' => '127.0.0.1',
'permission' => -1, 'permission' => -1,
'last_sign_at' => $faker->dateTime, 'last_sign_at' => $faker->dateTime->format('d-M-Y H:i:s'),
'register_at' => $faker->dateTime 'register_at' => $faker->dateTime->format('d-M-Y H:i:s')
]; ];
}); });

View File

@ -12,7 +12,7 @@ class CreateAllTables extends Migration
*/ */
public function up() public function up()
{ {
Schema::create('users', function($table) { Schema::create('users', function (Blueprint $table) {
$table->increments('uid'); $table->increments('uid');
$table->string('email', 100); $table->string('email', 100);
$table->string('nickname', 50)->default(''); $table->string('nickname', 50)->default('');
@ -23,14 +23,15 @@ class CreateAllTables extends Migration
$table->integer('permission')->default('0'); $table->integer('permission')->default('0');
$table->dateTime('last_sign_at'); $table->dateTime('last_sign_at');
$table->dateTime('register_at'); $table->dateTime('register_at');
$table->rememberToken();
}); });
Schema::create('closets', function($table) { Schema::create('closets', function (Blueprint $table) {
$table->increments('uid'); $table->increments('uid');
$table->longText('textures'); $table->longText('textures');
}); });
Schema::create('players', function($table) { Schema::create('players', function (Blueprint $table) {
$table->increments('pid'); $table->increments('pid');
$table->integer('uid'); $table->integer('uid');
$table->string('player_name', 50); $table->string('player_name', 50);
@ -41,7 +42,7 @@ class CreateAllTables extends Migration
$table->dateTime('last_modified'); $table->dateTime('last_modified');
}); });
Schema::create('textures', function($table) { Schema::create('textures', function (Blueprint $table) {
$table->increments('tid'); $table->increments('tid');
$table->string('name', 50); $table->string('name', 50);
$table->string('type', 10); $table->string('type', 10);
@ -53,7 +54,7 @@ class CreateAllTables extends Migration
$table->dateTime('upload_at'); $table->dateTime('upload_at');
}); });
Schema::create('options', function($table) { Schema::create('options', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('option_name', 50); $table->string('option_name', 50);
$table->longText('option_value'); $table->longText('option_value');

View File

@ -0,0 +1,8 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
Schema::table('users', function (Blueprint $table) {
$table->rememberToken();
});

View File

@ -9,7 +9,6 @@ check:
anonymous: Illegal access. Please log in first. anonymous: Illegal access. Please log in first.
admin: Only admins are permitted to access this page. admin: Only admins are permitted to access this page.
banned: You are banned on this site. Please contact the admin. banned: You are banned on this site. Please contact the admin.
token: Invalid token. Please log in.
register: register:
title: Register title: Register

View File

@ -19,6 +19,7 @@ between:
string: 'The :attribute must be between :min and :max characters.' string: 'The :attribute must be between :min and :max characters.'
array: 'The :attribute must have between :min and :max items.' array: 'The :attribute must have between :min and :max items.'
boolean: 'The :attribute field must be true or false.' boolean: 'The :attribute field must be true or false.'
captcha: 'Incorrect captcha.'
confirmed: 'The :attribute confirmation does not match.' confirmed: 'The :attribute confirmation does not match.'
date: 'The :attribute is not a valid date.' date: 'The :attribute is not a valid date.'
date_format: 'The :attribute does not match the format :format.' date_format: 'The :attribute does not match the format :format.'

View File

@ -9,7 +9,6 @@ check:
anonymous: 非法访问,请先登录 anonymous: 非法访问,请先登录
admin: 看起来你并不是管理员哦 admin: 看起来你并不是管理员哦
banned: 你已经被本站封禁啦,请联系管理员解决 banned: 你已经被本站封禁啦,请联系管理员解决
token: 无效的 token请重新登录
register: register:
title: 注册 title: 注册

View File

@ -19,6 +19,7 @@ between:
string: ':attribute 必须介于 :min - :max 个字符之间。' string: ':attribute 必须介于 :min - :max 个字符之间。'
array: ':attribute 必须只有 :min - :max 个单元。' array: ':attribute 必须只有 :min - :max 个单元。'
boolean: ':attribute 必须为布尔值。' boolean: ':attribute 必须为布尔值。'
captcha: '验证码不正确。'
confirmed: ':attribute 两次输入不一致。' confirmed: ':attribute 两次输入不一致。'
date: ':attribute 不是一个有效的日期。' date: ':attribute 不是一个有效的日期。'
date_format: ':attribute 的格式必须为 :format。' date_format: ':attribute 的格式必须为 :format。'

View File

@ -13,7 +13,9 @@
@yield('style') @yield('style')
</head> </head>
<?php $user = app('users')->get(session('uid')); ?> @php
$user = auth()->user();
@endphp
<body class="hold-transition {{ option('color_scheme') }} sidebar-mini"> <body class="hold-transition {{ option('color_scheme') }} sidebar-mini">
<div class="wrapper"> <div class="wrapper">

View File

@ -37,14 +37,14 @@
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
@include('common.language') @include('common.language')
@if (!is_null($user)) @auth
@include('common.user-menu') @include('common.user-menu')
@else {{-- Anonymous User --}} @else {{-- Anonymous User --}}
<!-- User Account Menu --> <!-- User Account Menu -->
<li class="dropdown user user-menu"> <li class="dropdown user user-menu">
<a href="{{ url('auth/login') }}" class="btn btn-login">@lang('general.login')</a> <a href="{{ url('auth/login') }}" class="btn btn-login">@lang('general.login')</a>
</li> </li>
@endif @endauth
</ul> </ul>
</div><!-- /.navbar-custom-menu --> </div><!-- /.navbar-custom-menu -->
</div><!-- /.container-fluid --> </div><!-- /.container-fluid -->
@ -58,7 +58,7 @@
{{ option_localized('site_description') }} {{ option_localized('site_description') }}
</p> </p>
<p> <p>
@if (is_null($user)) @guest
@if (option('user_can_register')) @if (option('user_can_register'))
<a href="{{ url('auth/register') }}" id="btn-register" class="button">@lang('general.register')</a> <a href="{{ url('auth/register') }}" id="btn-register" class="button">@lang('general.register')</a>
@else @else
@ -66,7 +66,7 @@
@endif @endif
@else @else
<a href="{{ url('user') }}" class="button">@lang('general.user-center')</a> <a href="{{ url('user') }}" class="button">@lang('general.user-center')</a>
@endif @endguest
</p> </p>
</div> </div>
</div> <!--/ .container --> </div> <!--/ .container -->

View File

@ -39,10 +39,10 @@
<div class="progress-group"> <div class="progress-group">
<span class="progress-text">@lang('user.used.storage')</span> <span class="progress-text">@lang('user.used.storage')</span>
<?php @php
$used = $statistics['storage']['used']; $used = $statistics['storage']['used'];
$total = $statistics['storage']['total']; $total = $statistics['storage']['total'];
?> @endphp
<span class="progress-number" id="user-storage"> <span class="progress-number" id="user-storage">
@if ($used > 1024) @if ($used > 1024)
@ -76,7 +76,9 @@
@else @else
<button class="btn btn-primary pull-left" title="@lang('user.last-sign', ['time' => $user->getLastSignTime()])" disabled="disabled"> <button class="btn btn-primary pull-left" title="@lang('user.last-sign', ['time' => $user->getLastSignTime()])" disabled="disabled">
<i class="fa fa-calendar-check-o" aria-hidden="true"></i> &nbsp; <i class="fa fa-calendar-check-o" aria-hidden="true"></i> &nbsp;
<?php $hours = $user->getSignRemainingTime() / 3600; ?> @php
$hours = $user->getSignRemainingTime() / 3600;
@endphp
@if ($hours >= 1) @if ($hours >= 1)
@lang('user.sign-remain-time', ['time' => round($hours), 'unit' => trans('user.time-unit-hour')]) @lang('user.sign-remain-time', ['time' => round($hours), 'unit' => trans('user.time-unit-hour')])
@else @else

View File

@ -42,7 +42,7 @@ Route::group(['prefix' => 'auth'], function ()
/** /**
* User Center * User Center
*/ */
Route::group(['middleware' => 'auth', 'prefix' => 'user'], function () Route::group(['middleware' => ['web', 'auth'], 'prefix' => 'user'], function ()
{ {
Route::any ('', 'UserController@index'); Route::any ('', 'UserController@index');
Route::any ('/sign', 'UserController@sign'); Route::any ('/sign', 'UserController@sign');
@ -94,7 +94,7 @@ Route::group(['prefix' => 'skinlib'], function ()
/** /**
* Admin Panel * Admin Panel
*/ */
Route::group(['middleware' => 'admin', 'prefix' => 'admin'], function () Route::group(['middleware' => ['auth', 'admin'], 'prefix' => 'admin'], function ()
{ {
Route::get('/', 'AdminController@index'); Route::get('/', 'AdminController@index');

View File

@ -95,8 +95,7 @@ class AuthControllerTest extends TestCase
// Should check captcha if there are too many fails // Should check captcha if there are too many fails
$this->withSession( $this->withSession(
[ [
'login_fails' => 4, 'login_fails' => 4
'phrase' => 'a'
] ]
)->postJson( )->postJson(
'/auth/login', [ '/auth/login', [
@ -129,8 +128,7 @@ class AuthControllerTest extends TestCase
])->assertJson( ])->assertJson(
[ [
'errno' => 0, 'errno' => 0,
'msg' => trans('auth.login.success'), 'msg' => trans('auth.login.success')
'token' => $user->getToken()
] ]
)->assertSessionMissing('login_fails'); )->assertSessionMissing('login_fails');
@ -145,41 +143,28 @@ class AuthControllerTest extends TestCase
)->assertJson( )->assertJson(
[ [
'errno' => 0, 'errno' => 0,
'msg' => trans('auth.login.success'), 'msg' => trans('auth.login.success')
'token' => $user->getToken()
] ]
)->assertCookie('uid', $user->uid) );
->assertCookie('token', $user->getToken()) $this->assertAuthenticated();
->assertSessionHasAll(
[
'uid' => $user->uid,
'token' => $user->getToken()
]
);
} }
public function testLogout() public function testLogout()
{ {
$user = factory(User::class)->create();
$this->withSession(
[
'uid' => $user->uid,
'token' => $user->getToken()
]
)->postJson('/auth/logout')->assertJson(
[
'errno' => 0,
'msg' => trans('auth.logout.success')
]
)->assertSessionMissing(['uid', 'token']);
$this->flushSession();
$this->postJson('/auth/logout') $this->postJson('/auth/logout')
->assertJson([ ->assertJson([
'errno' => 1, 'errno' => 1,
'msg' => trans('auth.logout.fail') 'msg' => trans('auth.logout.fail')
]); ]);
$user = factory(User::class)->create();
$this->actingAs($user)->postJson('/auth/logout')->assertJson(
[
'errno' => 0,
'msg' => trans('auth.logout.success')
]
);
$this->assertGuest();
} }
public function testRegister() public function testRegister()
@ -194,22 +179,10 @@ class AuthControllerTest extends TestCase
{ {
$this->expectsEvents(Events\UserRegistered::class); $this->expectsEvents(Events\UserRegistered::class);
// Should return a warning if `captcha` is wrong
$this->withSession(['phrase' => 'a'])
->postJson(
'/auth/register', [], [
'X-Requested-With' => 'XMLHttpRequest'
])->assertJson([
'errno' => 1,
'msg' => trans('auth.validation.captcha')
]);
// Once we have sent session in the last assertion,
// we don't need to send it again until we flush it.
// Should return a warning if `email` is empty // Should return a warning if `email` is empty
$this->postJson( $this->postJson(
'/auth/register', '/auth/register',
['captcha' => 'a'], [],
['X-Requested-With' => 'XMLHttpRequest'] ['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([ )->assertJson([
'errno' => 1, 'errno' => 1,
@ -219,23 +192,28 @@ class AuthControllerTest extends TestCase
// Should return a warning if `email` is invalid // Should return a warning if `email` is invalid
$this->postJson( $this->postJson(
'/auth/register', '/auth/register',
[ ['email' => 'not_an_email'],
'email' => 'not_an_email',
'captcha' => 'a'
],
['X-Requested-With' => 'XMLHttpRequest'] ['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([ )->assertJson([
'errno' => 1, 'errno' => 1,
'msg' => trans('validation.email', ['attribute' => 'email']) 'msg' => trans('validation.email', ['attribute' => 'email'])
]); ]);
// An existed user
$existedUser = factory(User::class)->create();
$this->postJson(
'/auth/register',
['email' => $existedUser->email],
['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([
'errno' => 1,
'msg' => trans('validation.unique', ['attribute' => 'email'])
]);
// Should return a warning if `password` is empty // Should return a warning if `password` is empty
$this->postJson( $this->postJson(
'/auth/register', '/auth/register',
[ ['email' => 'a@b.c'],
'email' => 'a@b.c',
'captcha' => 'a'
],
['X-Requested-With' => 'XMLHttpRequest'] ['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([ )->assertJson([
'errno' => 1, 'errno' => 1,
@ -247,8 +225,7 @@ class AuthControllerTest extends TestCase
'/auth/register', '/auth/register',
[ [
'email' => 'a@b.c', 'email' => 'a@b.c',
'password' => '1', 'password' => '1'
'captcha' => 'a'
], ],
['X-Requested-With' => 'XMLHttpRequest'] ['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([ )->assertJson([
@ -261,8 +238,7 @@ class AuthControllerTest extends TestCase
'/auth/register', '/auth/register',
[ [
'email' => 'a@b.c', 'email' => 'a@b.c',
'password' => str_random(33), 'password' => str_random(33)
'captcha' => 'a'
], ],
['X-Requested-With' => 'XMLHttpRequest'] ['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([ )->assertJson([
@ -275,8 +251,7 @@ class AuthControllerTest extends TestCase
'/auth/register', '/auth/register',
[ [
'email' => 'a@b.c', 'email' => 'a@b.c',
'password' => '12345678', 'password' => '12345678'
'captcha' => 'a'
], ],
['X-Requested-With' => 'XMLHttpRequest'] ['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([ )->assertJson([
@ -290,8 +265,7 @@ class AuthControllerTest extends TestCase
[ [
'email' => 'a@b.c', 'email' => 'a@b.c',
'password' => '12345678', 'password' => '12345678',
'nickname' => '\\', 'nickname' => '\\'
'captcha' => 'a'
], ],
['X-Requested-With' => 'XMLHttpRequest'] ['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([ )->assertJson([
@ -305,8 +279,7 @@ class AuthControllerTest extends TestCase
[ [
'email' => 'a@b.c', 'email' => 'a@b.c',
'password' => '12345678', 'password' => '12345678',
'nickname' => str_random(256), 'nickname' => str_random(256)
'captcha' => 'a'
], ],
['X-Requested-With' => 'XMLHttpRequest'] ['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([ )->assertJson([
@ -314,6 +287,21 @@ class AuthControllerTest extends TestCase
'msg' => trans('validation.max.string', ['attribute' => 'nickname', 'max' => 255]) 'msg' => trans('validation.max.string', ['attribute' => 'nickname', 'max' => 255])
]); ]);
// Should return a warning if `captcha` is empty
$this->postJson(
'/auth/register',
[
'email' => 'a@b.c',
'password' => '12345678',
'nickname' => 'nickname'
],
['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([
'errno' => 1,
'msg' => trans('validation.required', ['attribute' => 'captcha'])
]);
// Should be forbidden if registering is closed // Should be forbidden if registering is closed
Option::set('user_can_register', false); Option::set('user_can_register', false);
$this->postJson( $this->postJson(
@ -350,21 +338,6 @@ class AuthControllerTest extends TestCase
Option::set('regs_per_ip', 100); Option::set('regs_per_ip', 100);
// Should return a warning if using a duplicated email
$existedUser = factory(User::class)->create();
$this->postJson(
'/auth/register',
[
'email' => $existedUser->email,
'password' => '12345678',
'nickname' => 'nickname',
'captcha' => 'a'
]
)->assertJson([
'errno' => 5,
'msg' => trans('auth.register.registered')
]);
// Database should be updated if succeeded // Database should be updated if succeeded
$response = $this->postJson( $response = $this->postJson(
'/auth/register', '/auth/register',
@ -378,10 +351,8 @@ class AuthControllerTest extends TestCase
$newUser = User::where('email', 'a@b.c')->first(); $newUser = User::where('email', 'a@b.c')->first();
$response->assertJson([ $response->assertJson([
'errno' => 0, 'errno' => 0,
'msg' => trans('auth.register.success'), 'msg' => trans('auth.register.success')
'token' => $newUser->getToken() ]);
])->assertCookie('uid', $newUser->uid)
->assertCookie('token', $newUser->getToken());
$this->assertTrue($newUser->verifyPassword('12345678')); $this->assertTrue($newUser->verifyPassword('12345678'));
$this->assertDatabaseHas('users', [ $this->assertDatabaseHas('users', [
'email' => 'a@b.c', 'email' => 'a@b.c',
@ -390,6 +361,7 @@ class AuthControllerTest extends TestCase
'ip' => '127.0.0.1', 'ip' => '127.0.0.1',
'permission' => User::NORMAL 'permission' => User::NORMAL
]); ]);
$this->assertAuthenticated();
} }
public function testForgot() public function testForgot()
@ -529,13 +501,8 @@ class AuthControllerTest extends TestCase
public function testCaptcha() public function testCaptcha()
{ {
if (!function_exists('imagettfbbox') || getenv('TRAVIS_PHP_VERSION' == '5.5')) {
$this->markTestSkipped('There are some problems with PHP 5.5 on Travis CI');
}
$this->get('/auth/captcha') $this->get('/auth/captcha')
->assertSuccessful() ->assertSuccessful()
->assertHeader('Content-Type', 'image/png') ->assertHeader('Content-Type', 'image/png');
->assertSessionHas('phrase');
} }
} }

View File

@ -40,7 +40,7 @@ class BrowserKitTestCase extends Laravel\BrowserKitTesting\TestCase
$role = factory(\App\Models\User::class, $role)->create(); $role = factory(\App\Models\User::class, $role)->create();
} }
} }
return $this->withSession(['uid' => $role->uid, 'token' => $role->getToken()]); return $this->actingAs($role);
} }
protected function tearDown() protected function tearDown()

View File

@ -14,52 +14,38 @@ class MiddlewareTest extends TestCase
{ {
// Not logged in // Not logged in
$this->get('/user')->assertRedirect('auth/login'); $this->get('/user')->assertRedirect('auth/login');
$this->assertGuest();
// Normal user // Normal user
$this->actAs('normal') $this->actAs('normal')
->get('/user') ->assertAuthenticated();
->assertViewIs('user.index')
->assertSuccessful();
// Banned User // Banned User
$this->actAs('banned') $this->actAs('banned')
->get('/user') ->get('/user')
->assertSee('banned') ->assertSee('banned')
->assertDontSee('User Center')
->assertStatus(403); ->assertStatus(403);
// Binding email // Binding email
$noEmailUser = factory(App\Models\User::class)->create(['email' => '']); $noEmailUser = factory(App\Models\User::class)->create(['email' => '']);
$this->withSession([ $this->actingAs($noEmailUser)
'uid' => $noEmailUser->uid, ->get('/user')
'token' => $noEmailUser->getToken() ->assertSee('Bind')
])->get('/user')->assertSee('Bind')->assertDontSee('User Center'); ->assertDontSee('User Center');
$this->actAs($noEmailUser) $this->actingAs($noEmailUser)
->get('/user?email=email') ->get('/user?email=email')
->assertSee('Bind'); ->assertSee('Bind');
$other = factory(User::class)->create(); $other = factory(User::class)->create();
$this->actAs($noEmailUser) $this->actingAs($noEmailUser)
->get('/user?email='.$other->email) ->get('/user?email='.$other->email)
->assertSee(trans('auth.bind.registered')); ->assertSee(trans('auth.bind.registered'));
$this->actAs($noEmailUser) $this->actingAs($noEmailUser)
->get('/user?email=a@b.c') ->get('/user?email=a@b.c')
->assertSee('User Center'); ->assertSee('User Center');
$this->assertEquals('a@b.c', User::find($noEmailUser->uid)->email); $this->assertEquals('a@b.c', User::find($noEmailUser->uid)->email);
// Without token
$this->withSession([
'uid' => 0
])->get('/user')->assertRedirect('/auth/login');
// Without invalid token
$user = factory(User::class)->create();
$this->withSession([
'uid' => $user->uid,
'token' => 'invalid'
])->get('/user')->assertRedirect('/auth/login');
} }
public function testCheckAdministrator() public function testCheckAdministrator()
@ -177,17 +163,7 @@ class MiddlewareTest extends TestCase
->assertViewIs('auth.login') ->assertViewIs('auth.login')
->assertDontSee('User Center'); ->assertDontSee('User Center');
$user = factory(\App\Models\User::class)->create(); $this->actingAs(factory(User::class)->create())
$this->withSession(['uid' => $user->uid])
->get('/auth/login')
->assertRedirect('/auth/login');
$this->withSession(['uid' => $user->uid, 'token' => 'nothing'])
->get('/auth/login')
->assertRedirect('/auth/login');
$this->actAs('normal')
->get('/auth/login') ->get('/auth/login')
->assertRedirect('/user'); ->assertRedirect('/user');
} }

View File

@ -102,10 +102,11 @@ class PlayerControllerTest extends TestCase
public function testDelete() public function testDelete()
{ {
$player = factory(Player::class)->create(); $user = factory(User::class)->create();
$user = $player->user; $player = factory(Player::class)->create(['uid' => $user->uid]);
$score = $user->score;
$this->expectsEvents(Events\PlayerWillBeDeleted::class); $this->expectsEvents(Events\PlayerWillBeDeleted::class);
$this->actAs($user) $this->actingAs($user)
->postJson('/user/player/delete', ['pid' => $player->pid]) ->postJson('/user/player/delete', ['pid' => $player->pid])
->assertJson([ ->assertJson([
'errno' => 0, 'errno' => 0,
@ -114,7 +115,7 @@ class PlayerControllerTest extends TestCase
$this->assertNull(Player::find($player->pid)); $this->assertNull(Player::find($player->pid));
$this->expectsEvents(Events\PlayerWasDeleted::class); $this->expectsEvents(Events\PlayerWasDeleted::class);
$this->assertEquals( $this->assertEquals(
$user->score + option('score_per_player'), $score + option('score_per_player'),
User::find($user->uid)->score User::find($user->uid)->score
); );
@ -122,7 +123,7 @@ class PlayerControllerTest extends TestCase
option(['return_score' => false]); option(['return_score' => false]);
$player = factory(Player::class)->create(); $player = factory(Player::class)->create();
$user = $player->user; $user = $player->user;
$this->actAs($user) $this->actingAs($user)
->postJson('/user/player/delete', ['pid' => $player->pid]) ->postJson('/user/player/delete', ['pid' => $player->pid])
->assertJson([ ->assertJson([
'errno' => 0, 'errno' => 0,

View File

@ -40,7 +40,7 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase
$role = factory(\App\Models\User::class, $role)->create(); $role = factory(\App\Models\User::class, $role)->create();
} }
} }
return $this->withSession(['uid' => $role->uid, 'token' => $role->getToken()]); return $this->actingAs($role);
} }
protected function tearDown() protected function tearDown()

View File

@ -61,7 +61,6 @@ class UpdateControllerTest extends BrowserKitTestCase
option(['update_source' => 'http://xxx.xx/']); option(['update_source' => 'http://xxx.xx/']);
$this->visit('/admin/update') $this->visit('/admin/update')
->see(trans('admin.update.info.pre-release')) ->see(trans('admin.update.info.pre-release'))
->see(trans('admin.update.errors.connection'))
->see(config('app.version')) ->see(config('app.version'))
->uncheck('check_update') ->uncheck('check_update')
->type(vfs\vfsStream::url('root/update.json'), 'update_source') ->type(vfs\vfsStream::url('root/update.json'), 'update_source')

View File

@ -10,12 +10,6 @@ class UserControllerTest extends TestCase
{ {
use DatabaseTransactions; use DatabaseTransactions;
protected function setUp()
{
parent::setUp();
return $this->actAs('normal');
}
public function testIndex() public function testIndex()
{ {
$user = factory(User::class)->create(); $user = factory(User::class)->create();
@ -99,7 +93,8 @@ class UserControllerTest extends TestCase
public function testProfile() public function testProfile()
{ {
$this->get('/user/profile') $this->actAs('normal')
->get('/user/profile')
->assertViewHas('user'); ->assertViewHas('user');
} }
@ -245,7 +240,7 @@ class UserControllerTest extends TestCase
]); ]);
$this->assertTrue(User::find($user->uid)->verifyPassword('87654321')); $this->assertTrue(User::find($user->uid)->verifyPassword('87654321'));
// After changed password, user should re-login. // After changed password, user should re-login.
$this->get('/user')->assertRedirect('/auth/login'); $this->assertGuest();
$user = User::find($user->uid); $user = User::find($user->uid);
// Change email without `new_email` field // Change email without `new_email` field
@ -331,7 +326,7 @@ class UserControllerTest extends TestCase
]); ]);
$this->assertEquals('a@b.c', User::find($user->uid)->email); $this->assertEquals('a@b.c', User::find($user->uid)->email);
// After changed email, user should re-login. // After changed email, user should re-login.
$this->get('/user')->assertRedirect('/auth/login'); $this->assertGuest();
$user = User::find($user->uid); $user = User::find($user->uid);
// Delete account without `password` field // Delete account without `password` field