From 87dff56946699593b1600581416e713c1bd718c1 Mon Sep 17 00:00:00 2001 From: Twilight Date: Fri, 21 Jul 2023 02:04:05 +0800 Subject: [PATCH] add files --- includes/hooks/loliart.php | 112 +++++++ .../addons/LoliArtAccount/LoliArtAccount.php | 106 +++++++ modules/addons/LoliArtAccount/hooks.php | 51 +++ oauth/callback.php | 300 ++++++++++++++++++ oauth/redirect.php | 28 ++ 5 files changed, 597 insertions(+) create mode 100644 includes/hooks/loliart.php create mode 100644 modules/addons/LoliArtAccount/LoliArtAccount.php create mode 100644 modules/addons/LoliArtAccount/hooks.php create mode 100644 oauth/callback.php create mode 100644 oauth/redirect.php diff --git a/includes/hooks/loliart.php b/includes/hooks/loliart.php new file mode 100644 index 0000000..26b7fd4 --- /dev/null +++ b/includes/hooks/loliart.php @@ -0,0 +1,112 @@ +where('module', 'LoliArtAccount')->get(); + + foreach ( $moduleconfig as $key => $value ) { + $config[$value->setting] = $value->value; + } + + $url = $config['token_url']; + + $fields = [ + 'grant_type' => 'password', + 'client_id' => $config['password_client_id'], + 'client_secret' => $config['password_client_secret'], + 'username' => $username, + 'password' => $password, + 'scope' => 'user realname' + ]; + + + $fields_string = http_build_query($fields); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + + $result = curl_exec($ch); + + $tokens = json_decode($result); + + if (curl_errno($ch)) { + return false; + } + + + $ch = curl_init($config['user_info_url']); + + + $headers[] = 'Authorization: Bearer ' . $tokens->access_token; + + curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + $response = curl_exec($ch); + $oauth_user = json_decode($response); + + if (empty($oauth_user)) { + return false; + } + + if ($oauth_user->real_name_verified_at !== null) { + $_SESSION['realnamed'] = true; + } else { + $_SESSION['realnamed'] = false; + } + + return $oauth_user; +} + +add_hook('UserLogout', 1, function () { + if (isset($_SESSION['loliart_user_id'])) { + unset($_SESSION['loliart_user_id']); + } +}); + +add_hook('ClientLoginShare', 1, function ($vars) { + $username = $vars['username']; + $password = $vars['password']; + + // 检测邮箱是否合法 + if (!filter_var($username, FILTER_VALIDATE_EMAIL)) { + return false; + } + + $oauth_user = attemptUser($username, $password); + + // 查询用户 + $user_query = Capsule::table('tblusers')->where('email', $oauth_user->email); + + $user = $user_query->first(); + + + if ($user) { + return [ + 'email' => $oauth_user->email + ]; + } + + if (empty($oauth_user)) { + return false; + } + + return [ + 'create' => true, + 'email' => $oauth_user->email, + 'firstname' => $oauth_user->name, + 'lastname' => $oauth_user->id, + 'country' => 'CN', + 'password' => $vars['password'], + ]; +}); diff --git a/modules/addons/LoliArtAccount/LoliArtAccount.php b/modules/addons/LoliArtAccount/LoliArtAccount.php new file mode 100644 index 0000000..4b1f122 --- /dev/null +++ b/modules/addons/LoliArtAccount/LoliArtAccount.php @@ -0,0 +1,106 @@ + 'LoliArt Account', + 'description' => 'LoliArt 账户系统', + 'version' => '1.0', + 'author' => 'iVampireSP.com', + 'fields' => [] + ); + + + $configarray['fields']['auth_url'] = [ + 'FriendlyName' => 'Auth URL', + 'Type' => 'text', + 'Size' => '50', + 'Default' => 'https://oauth.laecloud.com/oauth/authorize' + ]; + + $configarray['fields']['token_url'] = [ + 'FriendlyName' => 'Token URL', + 'Type' => 'text', + 'Size' => '50', + 'Default' => 'https://oauth.laecloud.com/oauth/token' + ]; + + $configarray['fields']['user_info_url'] = [ + 'FriendlyName' => 'User Info URL', + 'Type' => 'text', + 'Size' => '50', + 'Default' => 'https://oauth.laecloud.com/api/user', + ]; + + $configarray['fields']['client_id'] = [ + 'FriendlyName' => 'Client ID', + 'Type' => 'text', + 'Size' => '25', + ]; + + $configarray['fields']['client_secret'] = [ + 'FriendlyName' => 'Client secret', + 'Type' => 'text', + 'Size' => '25', + ]; + + $configarray['fields']['password_client_id'] = [ + 'FriendlyName' => 'Password Client ID', + 'Type' => 'text', + 'Size' => '25', + ]; + + $configarray['fields']['password_client_secret'] = [ + 'FriendlyName' => 'Password Client secret', + 'Type' => 'text', + 'Size' => '25', + ]; + + $configarray['fields']['callback_uri'] = [ + 'FriendlyName' => 'Callback URL', + 'Type' => 'text', + 'Size' => '50', + 'Default' => 'https://stack.laecloud.com/oauth/callback.php', + ]; + + + + return $configarray; +} + + + +// function loliartaccount_activate() { + +// try { +// Capsule::schema() +// ->create( +// 'tblclients_realname', +// function ($table) { +// $table->increments('id')->primary(); +// $table->unsignedBitintger('user_id')->index(); +// $table->text('real_name')->nullable(); +// $table->text('verified_at')->nullable()->index(); +// } +// ); + +// return [ +// 'status' => 'success', +// 'description' => '模块激活成功. 点击 配置 对模块进行设置。' +// ]; +// } catch (\Exception $e) { +// return [ +// 'status' => "error", +// 'description' => '无法创建数据库: ' . $e->getMessage(), +// ]; +// } + + +// } + +// function loliartaccount_deactivate() { +// return [ +// 'status' => 'success', +// 'description' => '模块卸载成功' +// ]; +// } diff --git a/modules/addons/LoliArtAccount/hooks.php b/modules/addons/LoliArtAccount/hooks.php new file mode 100644 index 0000000..946fb36 --- /dev/null +++ b/modules/addons/LoliArtAccount/hooks.php @@ -0,0 +1,51 @@ +where('userid', $userID)->first()->real_name; + +// if ( $verifyinfo != '' ) { +// $verifyinfo = '已通过实名认证'; +// } else { +// $verifyinfo = '未通过实名认证'; +// } + +// return $verifyinfo; +// }); + + + +// add_hook('ClientAreaPage', 1, function($vars) { + +// $moduleconfig = Capsule::table('tbladdonmodules')->where('module', 'Oauth')->get(); + +// foreach ( $moduleconfig as $key => $value ) { +// $config[$value->setting] = $value->value; +// } + +// if($vars['templatefile'] == 'login' or $vars['templatefile'] == 'clientregister'){ +// $state = Str::random(40); +// $query = http_build_query([ +// 'client_id' => $config['client_id'], +// 'redirect_uri' => $config['callback_uri'], +// 'response_type' => 'code', +// 'scope' => '', +// 'state' => $state, +// ]); + +// header("Location: ".$config['auth_url']. '?' . $query); + +// die(); + + +// } +// }); \ No newline at end of file diff --git a/oauth/callback.php b/oauth/callback.php new file mode 100644 index 0000000..c77a526 --- /dev/null +++ b/oauth/callback.php @@ -0,0 +1,300 @@ +where('module', 'LoliArtAccount')->get(); + +foreach ($moduleconfig as $key => $value) { + $config[$value->setting] = $value->value; +} + +if ($_GET['code']) { + $url = $config['token_url']; + + $fields = [ + 'grant_type' => 'authorization_code', + 'client_id' => $config['client_id'], + 'client_secret' => $config['client_secret'], + 'redirect_uri' => $config['callback_uri'], + 'code' => $_GET['code'], + ]; + + + $fields_string = http_build_query($fields); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + + $result = curl_exec($ch); + + $data = json_decode($result); + + $ch = curl_init($config['user_info_url']); + + + $headers[] = 'Authorization: Bearer ' . $data->access_token; + + + curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + $response = curl_exec($ch); + + // exit($response); + $data = json_decode($response); + + if (empty($data)) { + exit(curl_error($ch)); + // die(''); + } + + + // // 验证 iso_code 是否为 CN + // $validate_ch = curl_init('https://www.lae.email/api/geoip?ip=' . $_SESSION['user_ip']); + // curl_setopt($validate_ch, CURLOPT_RETURNTRANSFER, TRUE); + // curl_setopt($validate_ch, CURLOPT_SSL_VERIFYPEER, 0); + // curl_setopt($validate_ch, CURLOPT_SSL_VERIFYHOST, 0); + // $validate_ch = json_decode(curl_exec($validate_ch)); + + // if (empty($validate_ch)) { + // die('Something went wrong, please contact us or try again later.'); + // } + + // // exit($validate_ch->iso_code == 'CN'); + // if ($validate_ch->iso_code == 'CN') { + // // 如果用户的区域在 中国大陆,则将用户带去实名认证 + // if (is_null($data->verified_at)) { + // die(''); + // } + // } + + // 我不认为 WHMCS 国家代码这边设计的很合理,所以监测到HK和TW时,必须将他们强制修改为CN + + // if ($validate_ch->iso_code == 'HK' || $validate_ch->iso_code == 'TW') { + // $validate_ch->iso_code = 'CN'; + // } + + + + $openID = Capsule::table('tblclients')->where('email', $data->email)->first()->id; + + if ($openID) { + + + go_oauth_login($openID); + // //更新实名状态 + // $realnameID = Capsule::table('tblclients_realname')->where('userid', $openID)->first()->id; + // if (!empty($realnameID)) { + // Capsule::table('tblclients_realname')->where('id', $realnameID)->update([ + // 'userid' => $openID, + // 'verified_at' => $data->verified_at, + // 'real_name' => $data->real_name, + // ]); + // } else { + // Capsule::table('tblclients_realname')->insert([ + // 'userid' => $openID, + // 'verified_at' => $data->verified_at, + // 'real_name' => $data->real_name, + // ]); + // } + } else { + //创建账户 + $user_IP = ($_SERVER["HTTP_VIA"]) ? $_SERVER["HTTP_X_FORWARDED_FOR"] : $_SERVER["REMOTE_ADDR"]; + $user_IP = ($user_IP) ? $user_IP : $_SERVER["REMOTE_ADDR"]; + $command = 'AddClient'; + $postData = [ + 'firstname' => 'LAE', + 'lastname' => $data->name, + 'email' => $data->email, + // 'address1' => $validate_ch->city . ' ' . $validate_ch->state_name, + // 'city' => $validate_ch->city, + // 'state' => $validate_ch->state_name, + // 'postcode' => $validate_ch->postal_code, + // 'country' => $validate_ch->iso_code, + 'phonenumber' => $phonenumbers, + 'password2' => oauth_random_str(10), + // 'clientip' => $validate_ch->ip, + 'clientip' => $user_IP, + 'noemail' => true, + 'skipvalidation' => true, + // 'currency' => $_SESSION['switched_currency'] ?? $validate_ch->currency, + 'currency' => $_SESSION['switched_currency'], + 'language' => $_SESSION['Language'] ?? 'chinese' + ]; + + // Client + + $results = localAPI($command, $postData); + if ($results['result'] != 'success') { + // print_r($results); + // Capsule::table('tblusers')->where('id', $realnameID)->update([ + // 'userid' => $openID, + // 'verified_at' => $data->verified_at, + // 'real_name' => $data->real_name, + // ]); + die("无法新增用户"); + } else { + // Capsule::table('tblusers')->where('email', $data->email)->update([ + // 'email_verified_at' => $data->verified_at, + // ]); + $user = Capsule::table('tblusers')->where('email', $data->email)->first(); + // dd($user->id); + + $hookParams = ["user_id" => $user->id, "client_id" => $results['clientid'], "userid" => $results['clientid']]; + // dd($hookParams); + run_hook("ClientAreaRegister", $hookParams); + + go_oauth_login($results['clientid']); + } + } + + if ($_SESSION['redirect_url']) { + $redirect_url = $_SESSION['redirect_url']; + unset($_SESSION['redirect_url']); + + header('Location: ' . $redirect_url); + } else { + header('Location: /clientarea.php'); + } +} + + +function go_oauth_login($uid) +{ + // 登陆 + + // 写入 SESSION UID + $_SESSION['uid'] = $uid; + + // 获取 UID + $userinfo = Capsule::table('tblclients')->where('id', $uid)->first(); + $username = $userinfo->firstname . ' ' . $userinfo->lastname; + + // 取出值 + $login_uid = $userinfo->id; + $login_pwd = $userinfo->password; + $language = $userinfo->language; + + // 更新登录时间登录IP + $fullhost = gethostbyaddr($remote_ip); + + if ($userinfo->firstname == '') { + $command = 'UpdateClient'; + $postData = array( + 'clientid' => $login_uid, + 'firstname' => 'LAE', + ); + + $results = localAPI($command, $postData); + } + + Capsule::table('tblclients')->where('id', $login_uid)->update([ + 'lastlogin' => time(), + 'ip' => $remote_ip, + 'host' => $fullhost, + ]); + + + + $_SESSION['uid'] = $login_uid; + if ($login_cid) { + $_SESSION['cid'] = $login_cid; + } + //仅支持8.1+ + oauth_finishLogin($login_uid); + $hookParams = array('userid' => $login_uid); + $hookParams['contactid'] = $login_cid ? $login_cid : 0; + run_hook('ClientLogin', $hookParams); + // $loginsuccess = true; + return 1; +} + + + + +function oauth_getWHMCSversion() +{ + //获取WHMCS当前版本 + global $CONFIG; + return substr($GLOBALS["CONFIG"]["Version"], 0, 5); +} +function oauth_finishLogin($clientid) +{ + //登录参数 + $user = \WHMCS\User\Client::find($clientid); + $userData["email"] = $user->email; + if (oauth_isWhmcsVersionHigherOrEqual("8.0.0")) { + $login = oauth_authUserV8($user); + } else { + require ROOTDIR . "/includes/clientfunctions.php"; + $login = oauth_authUserOther($userData); + } +} +function oauth_isWhmcsVersionHigherOrEqual($toCompare) +{ + if (isset($GLOBALS["CONFIG"]["Version"])) { + $version = explode("-", $GLOBALS["CONFIG"]["Version"]); + return version_compare($version[0], $toCompare, ">="); + } + global $whmcs; + return version_compare($whmcs->getVersion()->getRelease(), $toCompare, ">="); +} + +function oauth_authUserV8(\WHMCS\User\Client $client) +{ + try { + $class = new \WHMCS\Authentication\AuthManager(); + $result = $class->login($client->owner()); + return true; + } catch (\Error $e) { + return false; + } +} + +function oauth_authUserOther($userData) +{ + $user = json_encode($userData); + $password = hash("md5", rand()); + return validateClientLogin($user, $password); +} + + + +function oauth_random_str($length, $type = 1) +{ + if ($type == 1) { + + // 密码字符集,可任意添加你需要的字符 + $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + } else if ($type == 2) { + $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + } else if ($type == 3) { + $chars = '0123456789'; + } + $str = ''; + for ($i = 0; $i < $length; $i++) { + // 这里提供两种字符获取方式 + // 第一种是使用 substr 截取$chars中的任意一位字符; + // 第二种是取字符数组 $chars 的任意元素 + $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); + // $str .= $chars[mt_rand(0, strlen($chars) - 1)]; + } + return $str; +} diff --git a/oauth/redirect.php b/oauth/redirect.php new file mode 100644 index 0000000..3e41f3d --- /dev/null +++ b/oauth/redirect.php @@ -0,0 +1,28 @@ +where('module', 'LoliArtAccount')->get(); + +foreach ( $moduleconfig as $key => $value ) { + $config[$value->setting] = $value->value; +} + + +$state = Str::random(40); + +$_SESSION['oauth_state'] = $state; + +$query = http_build_query([ + 'client_id' => $config['client_id'], + 'redirect_uri' => $config['callback_uri'], + 'response_type' => 'code', + 'scope' => 'user realname', + 'state' => $state, +]); + +header("Location: ".$config['auth_url']. '?' . $query); + \ No newline at end of file