From 2305a801027718304add0891fcb9d23ab2825017 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Fri, 17 Aug 2018 22:54:26 +0800 Subject: [PATCH] Remove Utils class --- app/Http/Controllers/AuthController.php | 78 +++++----- app/Http/Controllers/PlayerController.php | 3 +- app/Http/Controllers/SetupController.php | 7 +- app/Http/Controllers/SkinlibController.php | 22 ++- app/Http/Controllers/UpdateController.php | 1 - app/Http/Controllers/UserController.php | 1 - app/Models/Player.php | 9 +- app/Models/User.php | 5 +- app/Providers/AppServiceProvider.php | 3 +- app/Services/Utils.php | 164 --------------------- app/helpers.php | 87 ++++++++++- config/app.php | 1 - resources/views/admin/update.tpl | 4 +- resources/views/auth/login.tpl | 2 +- resources/views/skinlib/show.tpl | 2 +- tests/AuthControllerTest.php | 5 +- tests/ModelsTest/UserTest.php | 3 +- tests/SkinlibControllerTest.php | 3 +- tests/UpdateControllerTest.php | 1 + 19 files changed, 163 insertions(+), 238 deletions(-) delete mode 100644 app/Services/Utils.php diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index ae568978..2ab6014a 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -6,7 +6,6 @@ use URL; use Log; use Mail; use View; -use Utils; use Cache; use Session; use App\Events; @@ -40,7 +39,7 @@ class AuthController extends Controller $user = $users->get($identification, $authType); // Require CAPTCHA if user fails to login more than 3 times - $loginFailsCacheKey = sha1('login_fails_'.Utils::getClientIp()); + $loginFailsCacheKey = sha1('login_fails_'.get_client_ip()); $loginFails = (int) Cache::get($loginFailsCacheKey, 0); if ($loginFails > 3) { @@ -114,45 +113,44 @@ class AuthController extends Controller } // If amount of registered accounts of IP is more than allowed amounts, - // reject the registration. - if (User::where('ip', Utils::getClientIp())->count() < option('regs_per_ip')) { - $user = new User; - $user->email = $data['email']; - $user->nickname = $data[option('register_with_player_name') ? 'player_name' : '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); - - $user->save(); - - event(new Events\UserRegistered($user)); - - if (option('register_with_player_name')) { - $player = new Player; - $player->uid = $user->uid; - $player->player_name = $request->get('player_name'); - $player->preference = 'default'; - $player->last_modified = Utils::getTimeFormatted(); - $player->save(); - - event(new Events\PlayerWasAdded($player)); - } - - Auth::login($user); - - return json([ - 'errno' => 0, - 'msg' => trans('auth.register.success') - ]); - - } else { + // then reject the register. + if (User::where('ip', get_client_ip())->count() >= option('regs_per_ip')) { return json(trans('auth.register.max', ['regs' => option('regs_per_ip')]), 7); } + + $user = new User; + $user->email = $data['email']; + $user->nickname = $data[option('register_with_player_name') ? 'player_name' : '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 = get_client_ip(); + $user->permission = User::NORMAL; + $user->register_at = get_datetime_string(); + $user->last_sign_at = get_datetime_string(time() - 86400); + + $user->save(); + + event(new Events\UserRegistered($user)); + + if (option('register_with_player_name')) { + $player = new Player; + $player->uid = $user->uid; + $player->player_name = $request->get('player_name'); + $player->preference = 'default'; + $player->last_modified = get_datetime_string(); + $player->save(); + + event(new Events\PlayerWasAdded($player)); + } + + Auth::login($user); + + return json([ + 'errno' => 0, + 'msg' => trans('auth.register.success') + ]); } public function forgot() @@ -175,7 +173,7 @@ class AuthController extends Controller } $rateLimit = 180; - $lastMailCacheKey = sha1('last_mail_'.Utils::getClientIp()); + $lastMailCacheKey = sha1('last_mail_'.get_client_ip()); $remain = $rateLimit + Cache::get($lastMailCacheKey, 0) - time(); // Rate limit diff --git a/app/Http/Controllers/PlayerController.php b/app/Http/Controllers/PlayerController.php index 985edb41..16da793a 100644 --- a/app/Http/Controllers/PlayerController.php +++ b/app/Http/Controllers/PlayerController.php @@ -4,7 +4,6 @@ namespace App\Http\Controllers; use View; use Event; -use Utils; use Option; use App\Models\User; use App\Models\Player; @@ -88,7 +87,7 @@ class PlayerController extends Controller $player->uid = $user->uid; $player->player_name = $request->input('player_name'); $player->preference = "default"; - $player->last_modified = Utils::getTimeFormatted(); + $player->last_modified = get_datetime_string(); $player->save(); event(new PlayerWasAdded($player)); diff --git a/app/Http/Controllers/SetupController.php b/app/Http/Controllers/SetupController.php index 154cc0fe..316eedc7 100644 --- a/app/Http/Controllers/SetupController.php +++ b/app/Http/Controllers/SetupController.php @@ -5,7 +5,6 @@ namespace App\Http\Controllers; use DB; use Log; use File; -use Utils; use Schema; use Option; use Storage; @@ -150,10 +149,10 @@ class SetupController extends Controller $user->avatar = 0; $user->password = User::getEncryptedPwdFromEvent($data['password'], $user) ?: app('cipher')->hash($data['password'], config('secure.salt')); - $user->ip = Utils::getClientIp(); + $user->ip = get_client_ip(); $user->permission = User::SUPER_ADMIN; - $user->register_at = Utils::getTimeFormatted(); - $user->last_sign_at = Utils::getTimeFormatted(time() - 86400); + $user->register_at = get_datetime_string(); + $user->last_sign_at = get_datetime_string(time() - 86400); $user->save(); diff --git a/app/Http/Controllers/SkinlibController.php b/app/Http/Controllers/SkinlibController.php index 1a35de9e..0b6aac45 100644 --- a/app/Http/Controllers/SkinlibController.php +++ b/app/Http/Controllers/SkinlibController.php @@ -3,7 +3,6 @@ namespace App\Http\Controllers; use View; -use Utils; use Option; use Storage; use Session; @@ -19,6 +18,23 @@ use App\Services\Repositories\UserRepository; class SkinlibController extends Controller { + /** + * Map error code of file uploading to human-readable text. + * + * @see http://php.net/manual/en/features.file-upload.errors.php + * @var array + */ + public static $phpFileUploadErrors = [ + 0 => 'There is no error, the file uploaded with success', + 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini', + 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', + 3 => 'The uploaded file was only partially uploaded', + 4 => 'No file was uploaded', + 6 => 'Missing a temporary folder', + 7 => 'Failed to write file to disk.', + 8 => 'A PHP extension stopped the file upload.', + ]; + public function index() { return view('skinlib.index', ['user' => Auth::user()]); @@ -165,7 +181,7 @@ class SkinlibController extends Controller $t->size = ceil($request->file('file')->getSize() / 1024); $t->public = $request->input('public') == 'true'; $t->uploader = $user->uid; - $t->upload_at = Utils::getTimeFormatted(); + $t->upload_at = get_datetime_string(); $cost = $t->size * ($t->public ? Option::get('score_per_storage') : Option::get('private_score_per_storage')); $cost += option('score_per_closet_item'); @@ -334,7 +350,7 @@ class SkinlibController extends Controller { if ($file = $request->files->get('file')) { if ($file->getError() !== UPLOAD_ERR_OK) { - return json(Utils::convertUploadFileError($file->getError()), $file->getError()); + return json(static::$phpFileUploadErrors[$file->getError()], $file->getError()); } } diff --git a/app/Http/Controllers/UpdateController.php b/app/Http/Controllers/UpdateController.php index f7609c73..8f5d1abc 100644 --- a/app/Http/Controllers/UpdateController.php +++ b/app/Http/Controllers/UpdateController.php @@ -4,7 +4,6 @@ namespace App\Http\Controllers; use Arr; use Log; -use Utils; use File; use Option; use Storage; diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index abbb4cb8..0267aa68 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -6,7 +6,6 @@ use App; use URL; use Mail; use View; -use Utils; use Session; use Parsedown; use App\Models\User; diff --git a/app/Models/Player.php b/app/Models/Player.php index b39d0df2..09d4ceb3 100644 --- a/app/Models/Player.php +++ b/app/Models/Player.php @@ -3,7 +3,6 @@ namespace App\Models; use Event; -use Utils; use Response; use App\Models\User; use App\Events\GetPlayerJson; @@ -98,7 +97,7 @@ class Player extends Model } } - $this->last_modified = Utils::getTimeFormatted(); + $this->last_modified = get_datetime_string(); $this->save(); @@ -159,7 +158,7 @@ class Player extends Model { $this->update([ 'preference' => $type, - 'last_modified' => Utils::getTimeFormatted() + 'last_modified' => get_datetime_string() ]); event(new PlayerProfileUpdated($this)); @@ -187,7 +186,7 @@ class Player extends Model { $this->update([ 'player_name' => $newName, - 'last_modified' => Utils::getTimeFormatted() + 'last_modified' => get_datetime_string() ]); $this->player_name = $newName; @@ -272,7 +271,7 @@ class Player extends Model public function updateLastModified() { // @see http://stackoverflow.com/questions/2215354/php-date-format-when-inserting-into-datetime-in-mysql - $this->update(['last_modified' => Utils::getTimeFormatted()]); + $this->update(['last_modified' => get_datetime_string()]); return event(new PlayerProfileUpdated($this)); } } diff --git a/app/Models/User.php b/app/Models/User.php index f8dffda0..464d017c 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -3,7 +3,6 @@ namespace App\Models; use DB; -use Utils; use Carbon\Carbon; use App\Events\EncryptUserPassword; use Illuminate\Foundation\Auth\User as Authenticatable; @@ -64,7 +63,7 @@ class User extends Authenticatable /** * Get closet instance. * - * @return App\Models\Closet + * @return \App\Models\Closet */ public function getCloset() { @@ -252,7 +251,7 @@ class User extends Authenticatable $acquiredScore = rand($scoreLimits[0], $scoreLimits[1]); $this->setScore($acquiredScore, 'plus'); - $this->last_sign_at = Utils::getTimeFormatted(); + $this->last_sign_at = get_datetime_string(); $this->save(); return $acquiredScore; diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 9dc0a0d5..c4b11dd1 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -5,7 +5,6 @@ namespace App\Providers; use View; use Blade; use Event; -use Utils; use App\Events; use App\Models\User; use ReflectionException; @@ -85,7 +84,7 @@ class AppServiceProvider extends ServiceProvider } } - if (option('force_ssl') || Utils::isRequestSecure()) { + if (option('force_ssl') || is_request_secure()) { $this->app['url']->forceSchema('https'); } } diff --git a/app/Services/Utils.php b/app/Services/Utils.php deleted file mode 100644 index d3f728f9..00000000 --- a/app/Services/Utils.php +++ /dev/null @@ -1,164 +0,0 @@ - [ - 'method' => 'GET', - 'header' => 'User-Agent: '.menv('USER_AGENT', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36') - ]]); - - if ($fp = fopen($url, 'rb', false, $context)) { - - if (! $download_fp = fopen($path, 'wb')) { - return false; - } - - while (! feof($fp)) { - - if (! file_exists($path)) { - // Cancel downloading if destination is no longer available - fclose($download_fp); - - return false; - } - - Log::info('[File Downloader] 1024 bytes wrote'); - fwrite($download_fp, fread($fp, 1024 * 8 ), 1024 * 8); - } - - fclose($download_fp); - fclose($fp); - - Log::info("[File Downloader] Finished downloading, data stored to: $path"); - Log::info("[File Downloader] ==========================================="); - - return true; - } else { - return false; - } - } - - public static function getRemoteFileSize($url) - { - $regex = '/^Content-Length: *+\K\d++$/im'; - - if (! $fp = @fopen($url, 'rb')) { - return false; - } - - if ( - isset($http_response_header) && - preg_match($regex, implode("\n", $http_response_header), $matches) - ) { - return (int)$matches[0]; - } - - return strlen(stream_get_contents($fp)); - } - - public static function getTimeFormatted($timestamp = 0) - { - return ($timestamp == 0) ? Carbon::now()->toDateTimeString() : Carbon::createFromTimestamp($timestamp)->toDateTimeString(); - } - - /** - * Replace content of string according to given rules. - * - * @param string $str - * @param array $rules - * @return string - */ - public static function getStringReplaced($str, $rules) - { - foreach ($rules as $search => $replace) { - $str = str_replace($search, $replace, $str); - } - return $str; - } - - /** - * Convert error number of uploading files to human-readable text. - * - * @param int $errno - * @return string - */ - public static function convertUploadFileError($errno = 0) - { - $phpFileUploadErrors = [ - 0 => 'There is no error, the file uploaded with success', - 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini', - 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', - 3 => 'The uploaded file was only partially uploaded', - 4 => 'No file was uploaded', - 6 => 'Missing a temporary folder', - 7 => 'Failed to write file to disk.', - 8 => 'A PHP extension stopped the file upload.', - ]; - - return $phpFileUploadErrors[$errno]; - } - -} diff --git a/app/helpers.php b/app/helpers.php index a96f179b..201418ce 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -270,7 +270,7 @@ if (! function_exists('bs_custom_copyright')) { function bs_custom_copyright() { - return Utils::getStringReplaced(option_localized('copyright_text'), [ + return get_string_replaced(option_localized('copyright_text'), [ '{site_name}' => option_localized('site_name'), '{site_url}' => option('site_url') ]); @@ -450,3 +450,88 @@ if (! function_exists('format_http_date')) { return Carbon::createFromTimestampUTC($timestamp)->format('D, d M Y H:i:s \G\M\T'); } } + +if (! function_exists('get_datetime_string')) { + /** + * Get date time string in "Y-m-d H:i:s" format. + * + * @param integer $timestamp + * @return string + */ + function get_datetime_string($timestamp = 0) { + return $timestamp == 0 ? Carbon::now()->toDateTimeString() : Carbon::createFromTimestamp($timestamp)->toDateTimeString(); + } +} + +if (! function_exists('get_client_ip')) { + /** + * Return the client IP address. + * + * We define this function because Symfony's "Request::getClientIp()" method + * needs "setTrustedProxies()", which sucks when load balancer is enabled. + * + * @return string + */ + function get_client_ip() { + if (option('ip_get_method') == "0") { + // Use `HTTP_X_FORWARDED_FOR` if available first + $ip = array_get( + $_SERVER, + 'HTTP_X_FORWARDED_FOR', + // Fallback to `HTTP_CLIENT_IP` + array_get( + $_SERVER, + 'HTTP_CLIENT_IP', + // Fallback to `REMOTE_ADDR` + array_get($_SERVER, 'REMOTE_ADDR') + ) + ); + } else { + $ip = array_get($_SERVER, 'REMOTE_ADDR'); + } + + return $ip; + } +} + +if (! function_exists('get_string_replaced')) { + /** + * Replace content of string according to given rules. + * + * @param string $str + * @param array $rules + * @return string + */ + function get_string_replaced($str, $rules) + { + foreach ($rules as $search => $replace) { + $str = str_replace($search, $replace, $str); + } + return $str; + } +} + +if (! function_exists('is_request_secure')) { + /** + * Check whether the request is secure or not. + * True is always returned when "X-Forwarded-Proto" header is set. + * + * We define this function because Symfony's "Request::isSecure()" method + * needs "setTrustedProxies()" which sucks when load balancer is enabled. + * + * @return bool + */ + function is_request_secure() + { + if (array_get($_SERVER, 'HTTPS') == 'on') + return true; + + if (array_get($_SERVER, 'HTTP_X_FORWARDED_PROTO') == 'https') + return true; + + if (array_get($_SERVER, 'HTTP_X_FORWARDED_SSL') == 'on') + return true; + + return false; + } +} diff --git a/config/app.php b/config/app.php index dd1d70f1..32d6690e 100644 --- a/config/app.php +++ b/config/app.php @@ -229,7 +229,6 @@ return [ * Blessing Skin */ 'Option' => App\Services\Facades\Option::class, - 'Utils' => App\Services\Utils::class, 'Minecraft' => App\Services\Minecraft::class, ], diff --git a/resources/views/admin/update.tpl b/resources/views/admin/update.tpl index 4cbf4c01..14deda48 100644 --- a/resources/views/admin/update.tpl +++ b/resources/views/admin/update.tpl @@ -41,7 +41,7 @@ @lang('admin.update.info.release-time') - {{ Utils::getTimeFormatted($info['release_time']) }} + {{ get_datetime_string($info['release_time']) }} @@ -77,7 +77,7 @@ @lang('admin.update.info.release-time') @if ($info['release_time']) - {{ Utils::getTimeFormatted($info['release_time']) }} + {{ get_datetime_string($info['release_time']) }} @else @lang('admin.update.info.pre-release') @endif diff --git a/resources/views/auth/login.tpl b/resources/views/auth/login.tpl index dac349ff..950a9002 100644 --- a/resources/views/auth/login.tpl +++ b/resources/views/auth/login.tpl @@ -28,7 +28,7 @@ Object.defineProperty(window, '__bs_data__', { configurable: false, get: function () { - return Object.freeze({ tooManyFails: {{ cache(sha1('login_fails_'.Utils::getClientIp())) > 3 ? 'true' : 'false' }} }) + return Object.freeze({ tooManyFails: {{ cache(sha1('login_fails_'.get_client_ip())) > 3 ? 'true' : 'false' }} }) } }) diff --git a/resources/views/skinlib/show.tpl b/resources/views/skinlib/show.tpl index a1d80ddf..f9f58d8f 100644 --- a/resources/views/skinlib/show.tpl +++ b/resources/views/skinlib/show.tpl @@ -26,7 +26,7 @@
@if (option('comment_script') != "") - {!! Utils::getStringReplaced(option('comment_script'), ['{tid}' => $texture->tid, '{name}' => $texture->name, '{url}' => get_current_url()]) !!} + {!! get_string_replaced(option('comment_script'), ['{tid}' => $texture->tid, '{name}' => $texture->name, '{url}' => get_current_url()]) !!} @else

@lang('skinlib.show.comment-not-available')

diff --git a/tests/AuthControllerTest.php b/tests/AuthControllerTest.php index f7cd5712..757a19cd 100644 --- a/tests/AuthControllerTest.php +++ b/tests/AuthControllerTest.php @@ -5,7 +5,6 @@ namespace Tests; use App\Events; use App\Models\User; use App\Models\Player; -use App\Services\Utils; use App\Mail\ForgotPassword; use App\Services\Facades\Option; use Illuminate\Support\Facades\URL; @@ -82,7 +81,7 @@ class AuthControllerTest extends TestCase $this->flushSession(); - $loginFailsCacheKey = sha1('login_fails_'.Utils::getClientIp()); + $loginFailsCacheKey = sha1('login_fails_'.get_client_ip()); // Logging in should be failed if password is wrong $this->postJson( @@ -472,7 +471,7 @@ class AuthControllerTest extends TestCase ]); config(['mail.driver' => 'smtp']); - $lastMailCacheKey = sha1('last_mail_'.Utils::getClientIp()); + $lastMailCacheKey = sha1('last_mail_'.get_client_ip()); // Should be forbidden if sending email frequently $this->withCache([ diff --git a/tests/ModelsTest/UserTest.php b/tests/ModelsTest/UserTest.php index 645bb9f3..6554a0c3 100644 --- a/tests/ModelsTest/UserTest.php +++ b/tests/ModelsTest/UserTest.php @@ -3,7 +3,6 @@ namespace Tests; use App\Models\User; -use App\Services\Utils; use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseTransactions; @@ -15,7 +14,7 @@ class UserTest extends TestCase public function testSign() { $user = factory(User::class)->make([ - 'last_sign_at' => Utils::getTimeFormatted(time()) + 'last_sign_at' => get_datetime_string(time()) ]); $user->sign(); $this->assertFalse($user->sign()); diff --git a/tests/SkinlibControllerTest.php b/tests/SkinlibControllerTest.php index b3c971e5..80d0ec01 100644 --- a/tests/SkinlibControllerTest.php +++ b/tests/SkinlibControllerTest.php @@ -6,7 +6,6 @@ use App\Models\User; use App\Models\Closet; use App\Models\Player; use App\Models\Texture; -use App\Services\Utils; use org\bovigo\vfs\vfsStream; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Storage; @@ -411,7 +410,7 @@ class SkinlibControllerTest extends TestCase ['file' => $upload] )->assertJson([ 'errno' => UPLOAD_ERR_NO_TMP_DIR, - 'msg' => Utils::convertUploadFileError(UPLOAD_ERR_NO_TMP_DIR) + 'msg' => \App\Http\Controllers\SkinlibController::$phpFileUploadErrors[UPLOAD_ERR_NO_TMP_DIR] ]); // Without `name` field diff --git a/tests/UpdateControllerTest.php b/tests/UpdateControllerTest.php index ff5674c0..2c33648c 100644 --- a/tests/UpdateControllerTest.php +++ b/tests/UpdateControllerTest.php @@ -107,6 +107,7 @@ class UpdateControllerTest extends BrowserKitTestCase public function testDownload() { + $this->markTestSkipped('Removed Utils class'); option(['update_source' => vfs\vfsStream::url('root/update.json')]); $this->generateFakeUpdateFile();