blessing-skin-server/app/Http/Controllers/UserController.php

346 lines
10 KiB
PHP
Raw Normal View History

2016-07-21 22:01:57 +08:00
<?php
2016-08-28 10:05:21 +08:00
namespace App\Http\Controllers;
2016-07-21 22:01:57 +08:00
2016-10-23 11:41:52 +08:00
use App;
2018-08-17 12:32:44 +08:00
use URL;
use Mail;
use View;
2018-08-17 12:32:44 +08:00
use Session;
2019-07-30 14:29:02 +08:00
use Carbon\Carbon;
2016-07-21 22:01:57 +08:00
use App\Models\User;
use App\Models\Texture;
use Illuminate\Http\Request;
2018-08-17 12:32:44 +08:00
use App\Mail\EmailVerification;
2016-11-18 23:06:15 +08:00
use App\Events\UserProfileUpdated;
use Illuminate\Support\Facades\Auth;
2016-07-21 22:01:57 +08:00
class UserController extends Controller
2016-07-21 22:01:57 +08:00
{
2018-08-17 12:32:44 +08:00
public function __construct()
{
$this->middleware(function ($request, $next) {
if (! Auth::user()->verified) {
$this->sendVerificationEmail();
}
return $next($request);
})->only(['index', 'profile']);
}
2019-04-27 23:10:21 +08:00
public function user()
{
return json('', 0, auth()->user()->makeHidden(['password', 'ip', 'remember_token'])->toArray());
}
2016-07-21 22:01:57 +08:00
public function index()
{
$user = Auth::user();
return view('user.index')->with([
'statistics' => [
'players' => $this->calculatePercentageUsed($user->players->count(), option('score_per_player')),
2019-07-30 14:29:02 +08:00
'storage' => $this->calculatePercentageUsed($this->getStorageUsed($user), option('score_per_storage')),
],
'announcement' => app('parsedown')->text(option_localized('announcement')),
2019-03-23 19:52:14 +08:00
'extra' => ['unverified' => option('require_verification') && ! $user->verified],
]);
}
2018-08-08 09:50:35 +08:00
public function scoreInfo()
{
$user = Auth::user();
2019-04-23 19:14:41 +08:00
return json('', 0, [
2018-08-08 09:50:35 +08:00
'user' => [
'score' => $user->score,
'lastSignAt' => $user->last_sign_at,
],
'stats' => [
'players' => $this->calculatePercentageUsed($user->players->count(), option('score_per_player')),
2019-07-30 14:29:02 +08:00
'storage' => $this->calculatePercentageUsed($this->getStorageUsed($user), option('score_per_storage')),
2018-08-08 09:50:35 +08:00
],
'signAfterZero' => option('sign_after_zero'),
'signGapTime' => option('sign_gap_time'),
2019-04-23 19:14:41 +08:00
]);
2018-08-08 09:50:35 +08:00
}
/**
* Calculate percentage of resources used by user.
*
* @param int $used
* @param int $rate
* @return array
*/
protected function calculatePercentageUsed($used, $rate)
{
$user = Auth::user();
2018-02-16 17:31:04 +08:00
// Initialize default value to avoid division by zero.
$result['used'] = $used;
$result['total'] = 'UNLIMITED';
$result['percentage'] = 0;
if ($rate != 0) {
2019-03-23 00:20:28 +08:00
$result['total'] = $used + floor($user->score / $rate);
$result['percentage'] = $result['total'] ? $used / $result['total'] * 100 : 100;
}
return $result;
2016-07-21 22:01:57 +08:00
}
2019-07-30 14:29:02 +08:00
protected function getStorageUsed(User $user)
{
return Texture::where('uploader', $user->uid)->select('size')->sum('size') ?: 0;
}
/**
2017-07-14 09:17:42 +08:00
* Handle user signing.
*
2017-11-18 13:25:08 +08:00
* @return \Illuminate\Http\JsonResponse
*/
2017-07-14 09:17:42 +08:00
public function sign()
2016-07-21 22:01:57 +08:00
{
$user = Auth::user();
2019-07-30 14:29:02 +08:00
if ($this->getSignRemainingTime($user) <= 0) {
$scoreLimits = explode(',', option('sign_score'));
$acquiredScore = rand($scoreLimits[0], $scoreLimits[1]);
$user->score += $acquiredScore;
$user->last_sign_at = Carbon::now()->toDateTimeString();
$user->save();
2019-02-16 18:16:57 +08:00
$gap = option('sign_gap_time');
2019-04-23 19:14:41 +08:00
return json(trans('user.sign-success', ['score' => $acquiredScore]), 0, [
'score' => $user->score,
2019-07-30 14:29:02 +08:00
'storage' => $this->calculatePercentageUsed($this->getStorageUsed($user), option('score_per_storage')),
'remaining_time' => $gap > 1 ? round($gap) : $gap,
2016-07-21 22:01:57 +08:00
]);
} else {
2019-07-30 14:29:02 +08:00
$remaining_time = $this->getUserSignRemainingTimeWithPrecision($user);
return json(trans('user.cant-sign-until', [
2017-11-18 13:25:08 +08:00
'time' => $remaining_time >= 1
? $remaining_time : round($remaining_time * 60),
'unit' => $remaining_time >= 1
? trans('user.time-unit-hour') : trans('user.time-unit-min'),
]), 1);
2016-07-21 22:01:57 +08:00
}
}
2019-07-30 14:29:02 +08:00
protected function getUserSignRemainingTimeWithPrecision(User $user)
{
2019-07-30 14:29:02 +08:00
$hours = $this->getSignRemainingTime($user) / 3600;
return $hours > 1 ? round($hours) : $hours;
}
2019-07-30 14:29:02 +08:00
protected function getSignRemainingTime(User $user)
{
$lastSignTime = Carbon::parse($user->last_sign_at);
if (option('sign_after_zero')) {
return Carbon::now()->diffInSeconds(
$lastSignTime <= Carbon::today() ? $lastSignTime : Carbon::tomorrow(),
false
);
}
return Carbon::now()->diffInSeconds($lastSignTime->addHours(option('sign_gap_time')), false);
}
2018-08-17 12:32:44 +08:00
public function sendVerificationEmail()
{
if (! option('require_verification')) {
return json(trans('user.verification.disabled'), 1);
}
// Rate limit of 60s
$remain = 60 + session('last_mail_time', 0) - time();
if ($remain > 0) {
2019-04-23 19:14:41 +08:00
return json(trans('user.verification.frequent-mail'), 1);
2018-08-17 12:32:44 +08:00
}
$user = Auth::user();
if ($user->verified) {
return json(trans('user.verification.verified'), 1);
}
$url = URL::signedRoute('auth.verify', ['uid' => $user->uid]);
try {
Mail::to($user->email)->send(new EmailVerification($url));
} catch (\Exception $e) {
// Write the exception to log
report($e);
2018-08-17 12:32:44 +08:00
return json(trans('user.verification.failed', ['msg' => $e->getMessage()]), 2);
}
Session::put('last_mail_time', time());
return json(trans('user.verification.success'), 0);
}
2016-07-21 22:01:57 +08:00
public function profile()
{
2019-03-23 19:52:14 +08:00
$user = Auth::user();
2019-04-19 19:36:36 +08:00
2019-03-23 19:52:14 +08:00
return view('user.profile')
->with('extra', [
'unverified' => option('require_verification') && ! $user->verified,
'admin' => $user->isAdmin(),
]);
2016-07-21 22:01:57 +08:00
}
2019-03-23 11:06:36 +08:00
public function handleProfile(Request $request)
2016-07-21 22:01:57 +08:00
{
$action = $request->input('action', '');
$user = Auth::user();
switch ($action) {
case 'nickname':
2019-03-22 21:40:12 +08:00
if (option('single_player', false)) {
return json(trans('user.profile.nickname.single'), 1);
}
$this->validate($request, [
'new_nickname' => 'required|no_special_chars|max:255',
]);
$nickname = $request->input('new_nickname');
2019-03-23 00:20:28 +08:00
$user->nickname = $nickname;
$user->save();
event(new UserProfileUpdated($action, $user));
2016-07-21 22:01:57 +08:00
2019-03-23 00:20:28 +08:00
return json(trans('user.profile.nickname.success', ['nickname' => $nickname]), 0);
case 'password':
$this->validate($request, [
2018-06-18 21:50:32 +08:00
'current_password' => 'required|min:6|max:32',
'new_password' => 'required|min:8|max:32',
]);
if (! $user->verifyPassword($request->input('current_password'))) {
2016-09-24 22:49:20 +08:00
return json(trans('user.profile.password.wrong-password'), 1);
}
if ($user->changePassword($request->input('new_password'))) {
event(new UserProfileUpdated($action, $user));
2018-02-16 19:54:07 +08:00
Auth::logout();
2018-02-16 19:54:07 +08:00
return json(trans('user.profile.password.success'), 0);
2017-11-18 13:25:08 +08:00
}
2016-07-21 22:01:57 +08:00
2017-11-18 13:25:08 +08:00
break; // @codeCoverageIgnore
2016-07-21 22:01:57 +08:00
case 'email':
$this->validate($request, [
'new_email' => 'required|email',
'password' => 'required|min:6|max:32',
]);
2016-07-21 22:01:57 +08:00
2019-03-23 11:06:36 +08:00
if (User::where('email', $request->new_email)->count() > 0) {
return json(trans('user.profile.email.existed'), 1);
}
if (! $user->verifyPassword($request->input('password'))) {
2016-09-24 22:49:20 +08:00
return json(trans('user.profile.email.wrong-password'), 1);
}
2016-07-21 22:01:57 +08:00
2019-03-23 00:20:28 +08:00
$user->email = $request->input('new_email');
$user->verified = false;
$user->save();
2018-02-16 19:54:07 +08:00
2019-03-23 00:20:28 +08:00
event(new UserProfileUpdated($action, $user));
2019-03-23 00:20:28 +08:00
Auth::logout();
2016-07-21 22:01:57 +08:00
2019-03-23 00:20:28 +08:00
return json(trans('user.profile.email.success'), 0);
2016-07-21 22:01:57 +08:00
case 'delete':
$this->validate($request, [
'password' => 'required|min:6|max:32',
]);
2016-07-21 22:01:57 +08:00
if ($user->isAdmin()) {
2018-08-02 10:21:25 +08:00
return json(trans('user.profile.delete.admin'), 1);
}
2018-08-02 10:21:25 +08:00
if (! $user->verifyPassword($request->input('password'))) {
2016-09-24 22:49:20 +08:00
return json(trans('user.profile.delete.wrong-password'), 1);
}
2018-08-02 10:21:25 +08:00
Auth::logout();
2018-08-02 10:21:25 +08:00
if ($user->delete()) {
2016-11-17 17:32:12 +08:00
session()->flush();
2019-04-23 19:14:41 +08:00
return json(trans('user.profile.delete.success'), 0);
}
2017-11-18 13:25:08 +08:00
break; // @codeCoverageIgnore
default:
2016-09-24 22:49:20 +08:00
return json(trans('general.illegal-parameters'), 1);
break;
2016-07-21 22:01:57 +08:00
}
}
// @codeCoverageIgnore
2016-07-21 22:01:57 +08:00
/**
* Set user avatar.
*
* @param Request $request
*/
public function setAvatar(Request $request)
2016-07-21 22:01:57 +08:00
{
$this->validate($request, [
'tid' => 'required|integer',
]);
2019-03-17 09:46:02 +08:00
$tid = $request->input('tid');
$user = auth()->user();
2019-03-17 09:46:02 +08:00
if ($tid == 0) {
$user->avatar = 0;
$user->save();
2019-04-19 19:36:36 +08:00
2019-03-17 09:46:02 +08:00
return json(trans('user.profile.avatar.success'), 0);
}
2016-07-21 22:01:57 +08:00
2019-03-17 09:46:02 +08:00
$result = Texture::find($tid);
2016-07-21 22:01:57 +08:00
if ($result) {
if ($result->type == 'cape') {
2016-09-24 22:49:20 +08:00
return json(trans('user.profile.avatar.wrong-type'), 1);
}
2016-07-21 22:01:57 +08:00
2019-03-23 00:20:28 +08:00
$user->avatar = $tid;
$user->save();
2019-04-19 19:36:36 +08:00
2019-03-23 00:20:28 +08:00
return json(trans('user.profile.avatar.success'), 0);
2016-07-21 22:01:57 +08:00
} else {
2017-08-07 13:48:20 +08:00
return json(trans('skinlib.non-existent'), 1);
2016-07-21 22:01:57 +08:00
}
}
2016-07-21 22:01:57 +08:00
2019-07-03 16:19:13 +08:00
public function readNotification($id)
{
$notification = auth()
->user()
->unreadNotifications
->first(function ($notification) use ($id) {
return $notification->id === $id;
});
$notification->markAsRead();
return [
'title' => $notification->data['title'],
'content' => app('parsedown')->text($notification->data['content']),
'time' => $notification->created_at->toDateTimeString(),
];
}
2016-07-21 22:01:57 +08:00
}