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

View File

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

View File

@ -9,6 +9,7 @@ use App\Models\Closet;
use App\Models\Texture;
use App\Models\ClosetModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Exceptions\PrettyPageException;
class ClosetController extends Controller
@ -23,14 +24,14 @@ class ClosetController extends Controller
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->closet = new Closet($request->session()->get('uid'));
$this->closet = new Closet(Auth::id());
return $next($request);
});
}
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)
@ -70,7 +71,9 @@ class ClosetController extends Controller
'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);
}
@ -86,7 +89,7 @@ class ClosetController extends Controller
$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);
} else {
@ -123,7 +126,7 @@ class ClosetController extends Controller
$this->closet->save();
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);
} else {

View File

@ -2,14 +2,11 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\Repositories\UserRepository;
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'));
}
}

View File

@ -15,6 +15,7 @@ use App\Events\PlayerWasDeleted;
use App\Events\CheckPlayerExists;
use App\Events\PlayerWillBeAdded;
use App\Events\PlayerWillBeDeleted;
use Illuminate\Support\Facades\Auth;
use App\Exceptions\PrettyPageException;
use App\Http\Middleware\CheckPlayerExist;
use App\Http\Middleware\CheckPlayerOwner;
@ -22,13 +23,6 @@ use App\Services\Repositories\UserRepository;
class PlayerController extends Controller
{
/**
* User Instance.
*
* @var \App\Models\User
*/
private $user;
/**
* Player Instance.
*
@ -36,13 +30,9 @@ class PlayerController extends Controller
*/
private $player;
public function __construct(UserRepository $users)
public function __construct()
{
$this->middleware(function ($request, $next) use ($users) {
$uid = $request->session()->get('uid');
$this->user = $users->get($uid);
$this->middleware(function ($request, $next) {
if ($request->has('pid')) {
if ($this->player = Player::find($request->pid)) {
$this->player->checkForInvalidTextures();
@ -59,11 +49,16 @@ class PlayerController extends Controller
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)
{
$user = Auth::user();
$this->validate($request, [
'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);
}
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);
}
@ -82,7 +77,7 @@ class PlayerController extends Controller
$player = new Player;
$player->uid = $this->user->uid;
$player->uid = $user->uid;
$player->player_name = $request->input('player_name');
$player->preference = "default";
$player->last_modified = Utils::getTimeFormatted();
@ -90,12 +85,12 @@ class PlayerController extends Controller
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);
}
public function delete(Request $request)
public function delete()
{
$playerName = $this->player->player_name;
@ -104,7 +99,7 @@ class PlayerController extends Controller
$this->player->delete();
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));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@ class CheckPlayerOwner
if ($pid = $request->input('pid')) {
$player = Player::find($pid);
if ($player->uid != app('user.current')->uid) {
if ($player->uid != auth()->id()) {
return response()->json([
'errno' => 1,
'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 Session;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
public function handle($request, \Closure $next)
{
if (session()->has('uid')) {
if (session('token') != app('users')->get(session('uid'))->getToken()) {
Session::put('msg', trans('auth.check.token')); // @codeCoverageIgnore
} else {
return redirect('user');
}
}
return $next($request);
return Auth::check() ? redirect('user') : $next($request);
}
}

View File

@ -6,9 +6,9 @@ use DB;
use Utils;
use Carbon\Carbon;
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.
@ -18,12 +18,6 @@ class User extends Model
const ADMIN = 1;
const SUPER_ADMIN = 2;
/**
* User Token.
* @var string
*/
protected $token;
/**
* Instance of Closet.
* @var \App\Models\Closet
@ -103,41 +97,13 @@ class User extends Model
* @param User $user
* @return mixed
*/
protected static function getEncryptedPwdFromEvent($rawPasswd, User $user)
public static function getEncryptedPwdFromEvent($rawPasswd, User $user)
{
$responses = event(new EncryptUserPassword($rawPasswd, $user));
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.
*
@ -216,21 +182,6 @@ class User extends Model
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.
*
@ -402,4 +353,9 @@ class User extends Model
{
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 App\Events\ConfigureRoutes;
use App\Http\Middleware\CheckSessionUserValid;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
@ -56,7 +55,7 @@ class RouteServiceProvider extends ServiceProvider
protected function mapWebRoutes(Router $router)
{
$router->group([
'middleware' => ['web', CheckSessionUserValid::class],
'middleware' => ['web'],
'namespace' => $this->namespace,
], function ($router) {
require base_path('routes/web.php');

View File

@ -74,6 +74,6 @@ class UserRepository extends Repository
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')) {
function runtime_check(array $requirements)

View File

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

255
composer.lock generated
View File

@ -1,10 +1,10 @@
{
"_readme": [
"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"
],
"content-hash": "a410c854791711695111f43f6ba32bee",
"content-hash": "03887f717dd02991b300a10cc712bd52",
"packages": [
{
"name": "composer/semver",
@ -449,32 +449,115 @@
"time": "2018-03-03T17:56:25+00:00"
},
{
"name": "gregwar/captcha",
"version": "v1.1.6",
"name": "guzzlehttp/psr7",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/Gregwar/Captcha.git",
"reference": "a96d8dffc80d6213958bd19fbdef1555e8b63ca3"
"url": "https://github.com/guzzle/psr7.git",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Gregwar/Captcha/zipball/a96d8dffc80d6213958bd19fbdef1555e8b63ca3",
"reference": "a96d8dffc80d6213958bd19fbdef1555e8b63ca3",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"shasum": ""
},
"require": {
"ext-gd": "*",
"ext-mbstring": "*",
"php": ">=5.3.0",
"symfony/finder": "~3.0|~4.0"
"php": ">=5.4.0",
"psr/http-message": "~1.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "^6.4"
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"type": "captcha",
"autoload": {
"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/",
@ -483,23 +566,22 @@
],
"authors": [
{
"name": "Grégoire Passault",
"email": "g.passault@gmail.com",
"homepage": "http://www.gregwar.com/"
},
{
"name": "Jeremy Livingston",
"email": "jeremy.j.livingston@gmail.com"
"name": "Oliver Vogel",
"email": "oliver@olivervogel.com",
"homepage": "http://olivervogel.com/"
}
],
"description": "Captcha generator",
"homepage": "https://github.com/Gregwar/Captcha",
"description": "Image handling and manipulation library with support for Laravel integration",
"homepage": "http://image.intervention.io/",
"keywords": [
"bot",
"captcha",
"spam"
"gd",
"image",
"imagick",
"laravel",
"thumbnail",
"watermark"
],
"time": "2018-04-24T09:20:08+00:00"
"time": "2018-05-29T14:19:03+00:00"
},
{
"name": "laravel/framework",
@ -788,6 +870,73 @@
],
"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",
"version": "1.23.0",
@ -1126,6 +1275,56 @@
],
"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",
"version": "1.0.2",

View File

@ -162,6 +162,7 @@ return [
Devitek\Core\Translation\TranslationServiceProvider::class,
Swiggles\Memcache\MemcacheServiceProvider::class,
Yajra\Datatables\DatatablesServiceProvider::class,
Mews\Captcha\CaptchaServiceProvider::class,
/**
* 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
'views' => true, // Views with their data
'route' => true, // Current route information
'auth' => false, // Display Laravel authentication status
'gate' => true, // Display Laravel Gate checks
'auth' => true, // Display Laravel authentication status
'gate' => false, // Display Laravel Gate checks
'session' => true, // Display session data
'symfony_request' => true, // Only one can be enabled..
'mail' => true, // Catch mail messages
'mail' => false, // Catch mail messages
'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
'logs' => false, // Add the latest log messages
'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')),
'ip' => '127.0.0.1',
'permission' => 0,
'last_sign_at' => $faker->dateTime,
'register_at' => $faker->dateTime
'last_sign_at' => $faker->dateTime->format('d-M-Y H:i:s'),
'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')),
'ip' => '127.0.0.1',
'permission' => 1,
'last_sign_at' => $faker->dateTime,
'register_at' => $faker->dateTime
'last_sign_at' => $faker->dateTime->format('d-M-Y H:i:s'),
'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')),
'ip' => '127.0.0.1',
'permission' => 2,
'last_sign_at' => $faker->dateTime,
'register_at' => $faker->dateTime
'last_sign_at' => $faker->dateTime->format('d-M-Y H:i:s'),
'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')),
'ip' => '127.0.0.1',
'permission' => -1,
'last_sign_at' => $faker->dateTime,
'register_at' => $faker->dateTime
'last_sign_at' => $faker->dateTime->format('d-M-Y H:i:s'),
'register_at' => $faker->dateTime->format('d-M-Y H:i:s')
];
});

View File

@ -12,7 +12,7 @@ class CreateAllTables extends Migration
*/
public function up()
{
Schema::create('users', function($table) {
Schema::create('users', function (Blueprint $table) {
$table->increments('uid');
$table->string('email', 100);
$table->string('nickname', 50)->default('');
@ -23,14 +23,15 @@ class CreateAllTables extends Migration
$table->integer('permission')->default('0');
$table->dateTime('last_sign_at');
$table->dateTime('register_at');
$table->rememberToken();
});
Schema::create('closets', function($table) {
Schema::create('closets', function (Blueprint $table) {
$table->increments('uid');
$table->longText('textures');
});
Schema::create('players', function($table) {
Schema::create('players', function (Blueprint $table) {
$table->increments('pid');
$table->integer('uid');
$table->string('player_name', 50);
@ -41,7 +42,7 @@ class CreateAllTables extends Migration
$table->dateTime('last_modified');
});
Schema::create('textures', function($table) {
Schema::create('textures', function (Blueprint $table) {
$table->increments('tid');
$table->string('name', 50);
$table->string('type', 10);
@ -53,7 +54,7 @@ class CreateAllTables extends Migration
$table->dateTime('upload_at');
});
Schema::create('options', function($table) {
Schema::create('options', function (Blueprint $table) {
$table->increments('id');
$table->string('option_name', 50);
$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.
admin: Only admins are permitted to access this page.
banned: You are banned on this site. Please contact the admin.
token: Invalid token. Please log in.
register:
title: Register

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -39,10 +39,10 @@
<div class="progress-group">
<span class="progress-text">@lang('user.used.storage')</span>
<?php
@php
$used = $statistics['storage']['used'];
$total = $statistics['storage']['total'];
?>
@endphp
<span class="progress-number" id="user-storage">
@if ($used > 1024)
@ -76,7 +76,9 @@
@else
<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;
<?php $hours = $user->getSignRemainingTime() / 3600; ?>
@php
$hours = $user->getSignRemainingTime() / 3600;
@endphp
@if ($hours >= 1)
@lang('user.sign-remain-time', ['time' => round($hours), 'unit' => trans('user.time-unit-hour')])
@else

View File

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

View File

@ -95,8 +95,7 @@ class AuthControllerTest extends TestCase
// Should check captcha if there are too many fails
$this->withSession(
[
'login_fails' => 4,
'phrase' => 'a'
'login_fails' => 4
]
)->postJson(
'/auth/login', [
@ -129,8 +128,7 @@ class AuthControllerTest extends TestCase
])->assertJson(
[
'errno' => 0,
'msg' => trans('auth.login.success'),
'token' => $user->getToken()
'msg' => trans('auth.login.success')
]
)->assertSessionMissing('login_fails');
@ -145,41 +143,28 @@ class AuthControllerTest extends TestCase
)->assertJson(
[
'errno' => 0,
'msg' => trans('auth.login.success'),
'token' => $user->getToken()
'msg' => trans('auth.login.success')
]
)->assertCookie('uid', $user->uid)
->assertCookie('token', $user->getToken())
->assertSessionHasAll(
[
'uid' => $user->uid,
'token' => $user->getToken()
]
);
);
$this->assertAuthenticated();
}
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')
->assertJson([
'errno' => 1,
'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()
@ -194,22 +179,10 @@ class AuthControllerTest extends TestCase
{
$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
$this->postJson(
'/auth/register',
['captcha' => 'a'],
[],
['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([
'errno' => 1,
@ -219,23 +192,28 @@ class AuthControllerTest extends TestCase
// Should return a warning if `email` is invalid
$this->postJson(
'/auth/register',
[
'email' => 'not_an_email',
'captcha' => 'a'
],
['email' => 'not_an_email'],
['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([
'errno' => 1,
'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
$this->postJson(
'/auth/register',
[
'email' => 'a@b.c',
'captcha' => 'a'
],
['email' => 'a@b.c'],
['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([
'errno' => 1,
@ -247,8 +225,7 @@ class AuthControllerTest extends TestCase
'/auth/register',
[
'email' => 'a@b.c',
'password' => '1',
'captcha' => 'a'
'password' => '1'
],
['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([
@ -261,8 +238,7 @@ class AuthControllerTest extends TestCase
'/auth/register',
[
'email' => 'a@b.c',
'password' => str_random(33),
'captcha' => 'a'
'password' => str_random(33)
],
['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([
@ -275,8 +251,7 @@ class AuthControllerTest extends TestCase
'/auth/register',
[
'email' => 'a@b.c',
'password' => '12345678',
'captcha' => 'a'
'password' => '12345678'
],
['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([
@ -290,8 +265,7 @@ class AuthControllerTest extends TestCase
[
'email' => 'a@b.c',
'password' => '12345678',
'nickname' => '\\',
'captcha' => 'a'
'nickname' => '\\'
],
['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([
@ -305,8 +279,7 @@ class AuthControllerTest extends TestCase
[
'email' => 'a@b.c',
'password' => '12345678',
'nickname' => str_random(256),
'captcha' => 'a'
'nickname' => str_random(256)
],
['X-Requested-With' => 'XMLHttpRequest']
)->assertJson([
@ -314,6 +287,21 @@ class AuthControllerTest extends TestCase
'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
Option::set('user_can_register', false);
$this->postJson(
@ -350,21 +338,6 @@ class AuthControllerTest extends TestCase
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
$response = $this->postJson(
'/auth/register',
@ -378,10 +351,8 @@ class AuthControllerTest extends TestCase
$newUser = User::where('email', 'a@b.c')->first();
$response->assertJson([
'errno' => 0,
'msg' => trans('auth.register.success'),
'token' => $newUser->getToken()
])->assertCookie('uid', $newUser->uid)
->assertCookie('token', $newUser->getToken());
'msg' => trans('auth.register.success')
]);
$this->assertTrue($newUser->verifyPassword('12345678'));
$this->assertDatabaseHas('users', [
'email' => 'a@b.c',
@ -390,6 +361,7 @@ class AuthControllerTest extends TestCase
'ip' => '127.0.0.1',
'permission' => User::NORMAL
]);
$this->assertAuthenticated();
}
public function testForgot()
@ -529,13 +501,8 @@ class AuthControllerTest extends TestCase
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')
->assertSuccessful()
->assertHeader('Content-Type', 'image/png')
->assertSessionHas('phrase');
->assertHeader('Content-Type', 'image/png');
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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