From 44c750234aa9de0709ab6b6db736100c179ac8e2 Mon Sep 17 00:00:00 2001 From: xiaomlove Date: Fri, 3 Jun 2022 03:42:53 +0800 Subject: [PATCH] support plugin --- .gitignore | 1 + app/Console/Commands/Plugin.php | 51 +++++++++++++++++++ app/Console/Commands/Test.php | 60 ++-------------------- app/Exceptions/Handler.php | 4 ++ app/Http/Kernel.php | 1 + app/Http/Middleware/NexusAuth.php | 21 ++++++++ app/Providers/AuthServiceProvider.php | 33 ++++++++++++- composer.json | 3 +- composer.lock | 2 +- config/auth.php | 3 ++ include/constants.php | 4 +- include/core.php | 3 ++ include/globalfunctions.php | 28 +++++++++++ nexus/Install/Update.php | 3 +- nexus/Nexus.php | 1 + nexus/Plugin/BasePlugin.php | 27 ++++++++++ nexus/Plugin/Hook.php | 71 +++++++++++++++++++++++++++ nexus/Plugin/Plugin.php | 57 +++++++++++++++++++++ public/delacctadmin.php | 22 +++++++-- public/deletedisabled.php | 1 + public/forums.php | 5 +- 21 files changed, 333 insertions(+), 68 deletions(-) create mode 100644 app/Console/Commands/Plugin.php create mode 100644 app/Http/Middleware/NexusAuth.php create mode 100644 nexus/Plugin/BasePlugin.php create mode 100644 nexus/Plugin/Hook.php create mode 100644 nexus/Plugin/Plugin.php diff --git a/.gitignore b/.gitignore index d094d04e..7ae86a85 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ yarn-error.log /imdb/images /resources/geoip .DS_Store +/plugins diff --git a/app/Console/Commands/Plugin.php b/app/Console/Commands/Plugin.php new file mode 100644 index 00000000..74928c35 --- /dev/null +++ b/app/Console/Commands/Plugin.php @@ -0,0 +1,51 @@ +argument('action'); + $name = $this->argument('name'); + $mainClass = $plugin->getMainClass($name); + if (!$mainClass) { + $this->error("Can not find plugin: $name"); + return 1; + } + if ($action == 'install') { + call_user_func([$mainClass, 'install']); + } elseif ($action == 'uninstall') { + call_user_func([$mainClass, 'uninstall']); + } else { + $this->error("Not support action: $action"); + return 1; + } + $log = sprintf("[%s], %s plugin: %s successfully !", nexus()->getRequestId(), $action, $name); + $this->info($log); + do_log($log); + return 0; + } +} diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php index d0a873b5..d94f7c1e 100644 --- a/app/Console/Commands/Test.php +++ b/app/Console/Commands/Test.php @@ -39,6 +39,7 @@ use JeroenG\Explorer\Infrastructure\Scout\ElasticEngine; use League\Flysystem\StorageAttributes; use Nexus\Database\NexusDB; use Nexus\Imdb\Imdb; +use NexusPlugin\PostLike\PostLike; use Rhilip\Bencode\Bencode; class Test extends Command @@ -74,62 +75,9 @@ class Test extends Command */ public function handle() { -// $searchRep = new SearchRepository(); -// $r = $searchRep->deleteIndex(); -// $r = $searchRep->createIndex(); -// $r = $searchRep->import(); -// dd($r); -// -// $arr = [ -// 'cat' => 'category', -// 'source' => 'source', -// 'medium' => 'medium', -// 'codec' => 'codec', -// 'audiocodec' => 'audiocodec', -// 'standard' => 'standard', -// 'processing' => 'processing', -// 'team' => 'team', -// ]; - $queryString = 'cat401=1&cat404=1&source2=1&medium2=1&medium3=1&codec3=1&audiocodec3=1&standard2=1&standard3=1&processing2=1&team3=1&team4=1&incldead=1&spstate=0&inclbookmarked=0&search=&search_area=0&search_mode=0'; - $userSetting = '[cat401][cat404][sou1][med1][cod1][sta2][sta3][pro2][tea2][aud2][incldead=0][spstate=3][inclbookmarked=2]'; -// foreach ($arr as $queryField => $value) { -//// $pattern = sprintf("/\[%s([\d]+)\]/", substr($queryField, 0, 3)); -// $pattern = "/{$queryField}([\d]+)=/"; -// if (preg_match_all($pattern, $queryString, $matches)) { -// dump($matches); -// echo '----------------------' . PHP_EOL; -// } -// } -// $r = preg_match("/\[incldead=([\d]+)\]/", $userSetting, $matches); -// dump($matches); - - $params = [ - 'tag_id' => 1, -// 'incldead' => 0, -// 'spstate' => 0, -// 'inclbookmarked' => 0, -// 'search' => '5034', -// 'search_area' => 4, -// 'search_mode' => 0, - ]; - $queryString = "cat401=1&cat404=1&cat405=1&cat402=1&cat403=1&cat406=1&cat407=1&cat409=1&cat408=1&incldead=0&spstate=0&inclbookmarked=0&search=5034838&search_area=4&search_mode=0"; -// $r = $searchRep->listTorrentFromEs($params, 1, ''); - -// $r = $searchRep->updateTorrent(1); -// $r = $searchRep->updateUser(1); -// $r = $searchRep->addTorrent(1); -// $r = $searchRep->deleteBookmark(1); -// $r = $searchRep->addBookmark(1); - -// $rep = new AttendanceRepository(); -// $uid = 1; -// $attendance = $rep->getAttendance($uid); -// $r = $rep->migrateAttendanceLogs($uid); -// $r = $rep->getContinuousDays($attendance); -// $r = $rep->getContinuousPoints(11); - - $r = trim(exec('command -v 7z.exe')); - dd($r); + $postLike = new PostLike(); + $postLike->install(); +// $postLike->uninstall(); } diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 9bd38444..18df3a23 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -41,6 +41,10 @@ class Handler extends ExceptionHandler */ public function register() { + if (!request()->expectsJson()) { + return; + } + $this->reportable(function (Throwable $e) { // }); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 250b41d6..c0a84b56 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -57,6 +57,7 @@ class Kernel extends HttpKernel protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, + 'auth.nexus' => \App\Http\Middleware\NexusAuth::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, diff --git a/app/Http/Middleware/NexusAuth.php b/app/Http/Middleware/NexusAuth.php new file mode 100644 index 00000000..883c75aa --- /dev/null +++ b/app/Http/Middleware/NexusAuth.php @@ -0,0 +1,21 @@ +expectsJson()) { + return getSchemeAndHttpHost() . '/login.php'; + } + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index ce744916..1e41d5a2 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -2,7 +2,10 @@ namespace App\Providers; +use App\Models\User; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Gate; class AuthServiceProvider extends ServiceProvider @@ -25,6 +28,34 @@ class AuthServiceProvider extends ServiceProvider { $this->registerPolicies(); - // + Auth::viaRequest('nexus-cookie', function (Request $request) { + return $this->getUserByCookie($request->cookie()); + }); + } + + private function getUserByCookie($cookie) + { + if (empty($cookie["c_secure_pass"]) || empty($cookie["c_secure_uid"]) || empty($cookie["c_secure_login"])) { + return null; + } + $b_id = base64($cookie["c_secure_uid"],false); + $id = intval($b_id ?? 0); + if (!$id || !is_valid_id($id) || strlen($cookie["c_secure_pass"]) != 32) { + return null; + } + $user = User::query()->find($id); + if (!$user) { + return null; + } + if ($cookie["c_secure_login"] == base64("yeah")) { + if ($cookie["c_secure_pass"] != md5($user->passhash . $_SERVER["REMOTE_ADDR"])) { + return null; + } + } else { + if ($cookie["c_secure_pass"] !== md5($user->passhash)) { + return null; + } + } + return $user; } } diff --git a/composer.json b/composer.json index 665acd2a..0529fcb0 100644 --- a/composer.json +++ b/composer.json @@ -84,7 +84,8 @@ "config": { "optimize-autoloader": true, "preferred-install": "dist", - "sort-packages": true + "sort-packages": true, + "secure-http": false }, "minimum-stability": "dev", "prefer-stable": true diff --git a/composer.lock b/composer.lock index 2245040d..d3eceb65 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1f44d54112683e0d2cd0738ac87d54d6", + "content-hash": "3387b3f52798b9a38c8eb3c895498916", "packages": [ { "name": "asm89/stack-cors", diff --git a/config/auth.php b/config/auth.php index ba1a4d8c..1999fc4c 100644 --- a/config/auth.php +++ b/config/auth.php @@ -46,6 +46,9 @@ return [ 'provider' => 'users', 'hash' => false, ], + 'nexus' => [ + 'driver' => 'nexus-cookie', + ], ], /* diff --git a/include/constants.php b/include/constants.php index 6b1f6161..780b97d4 100644 --- a/include/constants.php +++ b/include/constants.php @@ -1,6 +1,6 @@ addFilter($name, $function, $priority, $argc); +} + +function apply_filter($name, $value) +{ + global $hook; + do_log("[APPLY_FILTER]: $name"); + return $hook->applyFilter($name, func_get_args()); +} + +function add_action($name, $function, $priority = 10, $argc = 1) +{ + global $hook; + $hook->addAction($name, $function, $priority, $argc); +} + +function do_action($name, ...$args) +{ + global $hook; + do_log("[DO_ACTION]: $name"); + return $hook->doAction($name, ...$args); +} + + diff --git a/nexus/Install/Update.php b/nexus/Install/Update.php index 3641130d..4f8d31f0 100644 --- a/nexus/Install/Update.php +++ b/nexus/Install/Update.php @@ -231,12 +231,11 @@ class Update extends Install ]; $table = 'sysoppanel'; $this->addMenu($table, $menus); - $menuToDel = ['amountupload.php', 'amountattendancecard.php', 'amountbonus.php']; + $menuToDel = ['amountupload.php', 'amountattendancecard.php', 'amountbonus.php', 'deletedisabled.php']; $this->removeMenu('sysoppanel', $menuToDel); $this->removeMenu('adminpanel', $menuToDel); $this->removeMenu('modpanel', $menuToDel); - } public function runExtraMigrate() diff --git a/nexus/Nexus.php b/nexus/Nexus.php index 87598fd5..0802ad4e 100644 --- a/nexus/Nexus.php +++ b/nexus/Nexus.php @@ -3,6 +3,7 @@ namespace Nexus; use Illuminate\Support\Arr; use Illuminate\Support\Str; +use Nexus\Plugin\Hook; final class Nexus { diff --git a/nexus/Plugin/BasePlugin.php b/nexus/Plugin/BasePlugin.php new file mode 100644 index 00000000..b229685a --- /dev/null +++ b/nexus/Plugin/BasePlugin.php @@ -0,0 +1,27 @@ +buildUniqueId($function); + $isPriorityExists = isset(self::$callbacks[$priority]); + self::$callbacks[$name][$priority][$id] = ['function' => $function, 'argc' => $argc]; + if (!$isPriorityExists && count(self::$callbacks) > 1) { + krsort(self::$callbacks, SORT_NUMERIC); + } + } + + private function buildUniqueId($function): string + { + if (is_string($function)) { + return $function; + } elseif (is_object($function) && ($function instanceof \Closure)) { + //Closure + return spl_object_hash($function); + } elseif (is_array($function)) { + if (is_object($function[0])) { + return spl_object_hash($function[0]).$function[1]; + } elseif (is_string($function[0])) { + return $function[0].'::'.$function[1]; + } + } + throw new \InvalidArgumentException("Invalid function, type: " . gettype($function)); + } + + public function applyFilter($name, $value = '') + { + if (!isset(self::$callbacks[$name])) { + do_log("No this hook: $name"); + return null; + } + $args = func_get_args(); + reset(self::$callbacks[$name]); + do_log("name: $name, args: " . json_encode($args)); + do { + foreach ((array)current(self::$callbacks[$name]) as $callback) { + $args[1] = $value; + $value = call_user_func_array($callback['function'], array_slice($args, 1, $callback['argc'])); + } + } + while (next(self::$callbacks[$name]) !== false); + return $value; + } + + public function addAction($name, $function, $priority, $argc) + { + return $this->addFilter($name, $function, $priority, $argc); + } + + public function doAction($name, ...$args) + { + $this->applyFilter(...func_get_args()); + } + + public function dump() + { + echo '
';
+        var_dump(self::$callbacks);
+        echo '
'; + } +} diff --git a/nexus/Plugin/Plugin.php b/nexus/Plugin/Plugin.php new file mode 100644 index 00000000..b1c96de2 --- /dev/null +++ b/nexus/Plugin/Plugin.php @@ -0,0 +1,57 @@ +loadProviders(); + if (!isRunningInConsole()) { + $this->bootPlugins(); + } + } + + public function enabled($name): bool + { + return !empty(self::$providers[$name]['providers']); + } + + public function getMainClass($name) + { + if (isset(self::$providers[$name]['providers'][0])) { + $className = self::$providers[$name]['providers'][0]; + $className = str_replace('ServiceProvider', '', $className); + if (class_exists($className)) { + return new $className; + } + } + } + + private function bootPlugins() + { + foreach (self::$providers as $name => $providers) { + $provider = $providers['providers'][0]; + $parts = explode('\\', $provider); + if ($parts[0] == 'NexusPlugin') { + $className = str_replace('ServiceProvider', '', $provider); + call_user_func([new $className, 'boot']); + } + } + } + + private function loadProviders() + { + if (is_null(self::$providers)) { + $path = ROOT_PATH . 'bootstrap/cache/packages.php'; + if (file_exists($path)) { + self::$providers = require $path; + } else { + self::$providers = []; + } + } + } + + +} diff --git a/public/delacctadmin.php b/public/delacctadmin.php index fcf8ab34..8a382fe2 100644 --- a/public/delacctadmin.php +++ b/public/delacctadmin.php @@ -18,9 +18,25 @@ $arr = mysql_fetch_assoc($res); $id = $arr['id']; $name = $arr['username']; -$res = sql_query("DELETE FROM users WHERE id=$id") or sqlerr(); -if (mysql_affected_rows() != 1) - stderr("Error", "Unable to delete the account."); +try { + \Nexus\Database\NexusDB::transaction(function () use ($id) { + $affectedRows = \Nexus\Database\NexusDB::table('users')->where('id', $id)->delete(); + if ($affectedRows != 1) { + throw new \RuntimeException("Unable to delete the account."); + } + $tables = [ + 'hit_and_runs' => 'uid', + 'claims' => 'uid', + 'exam_users' => 'uid', + 'exam_progress' => 'uid', + ]; + foreach ($tables as $table => $key) { + \Nexus\Database\NexusDB::table($table)->where($key, $id)->delete(); + } + }); +} catch (\Exception $exception) { + stderr("Error", $exception->getMessage()); +} stderr("Success", "The account ".htmlspecialchars($name)." was deleted.",false); } stdhead("Delete account"); diff --git a/public/deletedisabled.php b/public/deletedisabled.php index d4d066ed..ed7c40ad 100644 --- a/public/deletedisabled.php +++ b/public/deletedisabled.php @@ -7,6 +7,7 @@ if (get_user_class() < UC_SYSOP) permissiondenied(); $shownotice=false; +stderr("Error", "Hard deletion of users is not recommended and can cause many problems."); if ($_SERVER["REQUEST_METHOD"] == "POST") { if ($_POST['sure']) diff --git a/public/forums.php b/public/forums.php index e01ae2e7..9f9c1a3d 100644 --- a/public/forums.php +++ b/public/forums.php @@ -4,7 +4,6 @@ dbconn(); require_once(get_langfile_path()); loggedinorreturn(); parked(); - if ($enableextforum == 'yes') //check whether internal forum is disabled permissiondenied(); @@ -635,7 +634,6 @@ if ($action == "viewtopic") $userInfoArr = \App\Models\User::query()->with(['wearing_medals'])->find($uidArr, $neededColumns)->keyBy('id'); $pn = 0; $lpr = get_last_read_post_id($topicid); - if ($Advertisement->enable_ad()) $forumpostad=$Advertisement->get_ad('forumpost'); foreach ($allPosts as $arr) @@ -728,6 +726,8 @@ if ($action == "viewtopic") print("".("'".$arr2['last_access']."'">$dt?"\"Online\"":"\"Offline\"" )."\"PM\"\"Report\""); print(""); + do_action('post_toolbox', $arr, $allPosts, $CURUSER['id']); + if ($maypost) print("\"Quote\""); @@ -833,6 +833,7 @@ if ($action == "viewtopic") else print($lang_forums['text_unpermitted_posting_here']); print(key_shortcut($page,$pages-1)); + do_action('page_forums_js'); stdfoot(); die; }