From 3bb15d6a41cb57cf1a2046e87400beb0f7f3efe4 Mon Sep 17 00:00:00 2001
From: xiaomlove <353856593@qq.com>
Date: Thu, 10 Jun 2021 21:07:20 +0800
Subject: [PATCH] Google Authenticator
---
app/Console/Commands/AttendanceCleanup.php | 71 +++++++++++++++++++
app/Console/Commands/Test.php | 4 +-
app/Models/Attendance.php | 12 ++++
classes/class_attendance.php | 33 +++++++--
composer.json | 1 +
composer.lock | 60 +++++++++++++++-
...s_and_total_points_to_attendance_table.php | 36 ++++++++++
...005_add_two_step_secret_to_users_table.php | 35 +++++++++
include/functions.php | 2 +-
include/globalfunctions.php | 31 ++++++--
lang/chs/lang_login.php | 2 +
lang/chs/lang_takelogin.php | 2 +
lang/chs/lang_usercp.php | 7 +-
lang/en/lang_usercp.php | 5 +-
public/login.php | 1 +
public/takelogin.php | 14 +++-
public/usercp.php | 46 ++++++++++++
17 files changed, 339 insertions(+), 23 deletions(-)
create mode 100644 app/Console/Commands/AttendanceCleanup.php
create mode 100644 app/Models/Attendance.php
create mode 100644 database/migrations/2021_06_10_150523_add_total_days_and_total_points_to_attendance_table.php
create mode 100644 database/migrations/2021_06_10_181005_add_two_step_secret_to_users_table.php
diff --git a/app/Console/Commands/AttendanceCleanup.php b/app/Console/Commands/AttendanceCleanup.php
new file mode 100644
index 00000000..c11a9f7b
--- /dev/null
+++ b/app/Console/Commands/AttendanceCleanup.php
@@ -0,0 +1,71 @@
+groupBy('uid')->selectRaw('uid, max(id) as max_id');
+ $page = 1;
+ $size = 1000;
+ while (true) {
+ $rows = $query->forPage($page, $size)->get();
+ $log = "sql: " . last_query() . ", count: " . $rows->count();
+ do_log($log);
+ $this->info($log);
+ if ($rows->isEmpty()) {
+ $log = "no more data....";
+ do_log($log);
+ $this->info($log);
+ break;
+ }
+ foreach ($rows as $row) {
+ do {
+ $deleted = Attendance::query()
+ ->where('uid', $row->uid)
+ ->where('id', '<', $row->max_id)
+ ->limit(10000)
+ ->delete();
+ $log = "delete: $deleted by sql: " . last_query();
+ do_log($log);
+ $this->info($log);
+ } while ($deleted > 0);
+ }
+ $page++;
+ }
+ return 0;
+ }
+}
diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php
index 75659466..415434a2 100644
--- a/app/Console/Commands/Test.php
+++ b/app/Console/Commands/Test.php
@@ -2,6 +2,7 @@
namespace App\Console\Commands;
+use App\Models\Attendance;
use App\Models\Exam;
use App\Models\ExamProgress;
use App\Models\ExamUser;
@@ -52,8 +53,7 @@ class Test extends Command
*/
public function handle()
{
- $r = 'https://hdtime.org/download.php?downhash=' . urlencode('1|Roqd');
- dd($r);
+
}
}
diff --git a/app/Models/Attendance.php b/app/Models/Attendance.php
new file mode 100644
index 00000000..95d09349
--- /dev/null
+++ b/app/Models/Attendance.php
@@ -0,0 +1,12 @@
+ 'datetime',
+ ];
+}
diff --git a/classes/class_attendance.php b/classes/class_attendance.php
index 1a724fba..84aa83ba 100644
--- a/classes/class_attendance.php
+++ b/classes/class_attendance.php
@@ -23,10 +23,16 @@ class Attendance
public function attend($initial = 10, $step = 5, $maximum = 2000, $continous = array())
{
if($this->check(true)) return false;
- $count = get_row_count('attendance', sprintf('WHERE `uid` = %u', $this->userid));
- $points = min($initial + $step * $count, $maximum);
- $res = sql_query(sprintf('SELECT DATEDIFF(%s, `added`) AS diff, `days` FROM `attendance` WHERE `uid` = %u ORDER BY `id` DESC LIMIT 1', sqlesc($this->curdate), $this->userid)) or sqlerr(__FILE__,__LINE__);
- list($datediff, $days) = mysql_num_rows($res) ? mysql_fetch_row($res) : array('diff' => 0, 'days' => 0);
+ $res = sql_query(sprintf('SELECT DATEDIFF(%s, `added`) AS diff, `days`, `total_days`, `total_points` FROM `attendance` WHERE `uid` = %u ORDER BY `id` DESC LIMIT 1', sqlesc($this->curdate), $this->userid)) or sqlerr(__FILE__,__LINE__);
+ $doUpdate = mysql_num_rows($res);
+ if ($doUpdate) {
+ $row = mysql_fetch_row($res);
+ do_log("uid: {$this->userid}, row: " . json_encode($row));
+ } else {
+ $row = [0, 0, 0, 0];
+ }
+ $points = min($initial + $step * $row['total_attend_times'], $maximum);
+ list($datediff, $days, $totalDays, $totalPoints) = $row;
$cdays = $datediff == 1 ? ++$days : 1;
if($cdays > 1){
krsort($continous);
@@ -37,10 +43,23 @@ class Attendance
}
}
}
- sql_query(sprintf('INSERT INTO `attendance` (`uid`,`added`,`points`,`days`) VALUES (%u, %s, %u, %u)', $this->userid, sqlesc(date('Y-m-d H:i:s')), $points, $cdays)) or sqlerr(__FILE__, __LINE__);
+// sql_query(sprintf('INSERT INTO `attendance` (`uid`,`added`,`points`,`days`) VALUES (%u, %s, %u, %u)', $this->userid, sqlesc(date('Y-m-d H:i:s')), $points, $cdays)) or sqlerr(__FILE__, __LINE__);
+ if ($doUpdate) {
+ $sql = sprintf(
+ 'UPDATE `attendance` set added = %s, points = %s, days = %s, total_days= %s, total_points = %s where uid = %s order by id desc limit 1',
+ sqlesc(date('Y-m-d H:i:s')), $points, $cdays, $totalDays + 1, $totalPoints + $points, $this->userid
+ );
+ } else {
+ $sql = sprintf(
+ 'INSERT INTO `attendance` (`uid`, `added`, `points`, `days`, `total_days`, `total_points`) VALUES (%u, %s, %u, %u, %u, %u)',
+ $this->userid, sqlesc(date('Y-m-d H:i:s')), $points, $cdays, $totalDays + 1, $totalPoints + $points
+ );
+ }
+ do_log(sprintf('uid: %s, date: %s, doUpdate: %s, sql: %s', $this->userid, $this->curdate, $doUpdate, $sql), 'notice');
+ sql_query($sql) or sqlerr(__FILE__, __LINE__);
KPS('+', $points, $this->userid);
global $Cache;
$Cache->delete_value($this->cachename);
- return array(++$count, $cdays, $points);
+ return array(++$totalDays, $cdays, $points);
}
-}
\ No newline at end of file
+}
diff --git a/composer.json b/composer.json
index 4a60c3a9..a7a418d6 100644
--- a/composer.json
+++ b/composer.json
@@ -41,6 +41,7 @@
"laravel/tinker": "^2.5",
"nao-pon/flysystem-google-drive": "^1.1",
"orangehill/iseed": "^3.0",
+ "phpgangsta/googleauthenticator": "dev-master",
"rhilip/bencode": "^1.1",
"swiftmailer/swiftmailer": "^6.2"
},
diff --git a/composer.lock b/composer.lock
index 823ee73d..1cfcab00 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": "a4f805b49bd52cf34ee5f763976ed030",
+ "content-hash": "fcf04cef5848b9eb1d15b0c297de364f",
"packages": [
{
"name": "asm89/stack-cors",
@@ -3282,6 +3282,60 @@
},
"time": "2020-10-15T08:29:30+00:00"
},
+ {
+ "name": "phpgangsta/googleauthenticator",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPGangsta/GoogleAuthenticator.git",
+ "reference": "505c2af8337b559b33557f37cda38e5f843f3768"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPGangsta/GoogleAuthenticator/zipball/505c2af8337b559b33557f37cda38e5f843f3768",
+ "reference": "505c2af8337b559b33557f37cda38e5f843f3768",
+ "shasum": "",
+ "mirrors": [
+ {
+ "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+ "preferred": true
+ }
+ ]
+ },
+ "require": {
+ "php": ">=5.3"
+ },
+ "default-branch": true,
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "PHPGangsta/GoogleAuthenticator.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-4-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Michael Kliewe",
+ "email": "info@phpgangsta.de",
+ "homepage": "http://www.phpgangsta.de/",
+ "role": "Developer"
+ }
+ ],
+ "description": "Google Authenticator 2-factor authentication",
+ "keywords": [
+ "googleauthenticator",
+ "rfc6238",
+ "totp"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPGangsta/GoogleAuthenticator/issues",
+ "source": "https://github.com/PHPGangsta/GoogleAuthenticator"
+ },
+ "time": "2019-03-20T00:55:58+00:00"
+ },
{
"name": "phpoption/phpoption",
"version": "1.7.5",
@@ -9400,7 +9454,9 @@
],
"aliases": [],
"minimum-stability": "dev",
- "stability-flags": [],
+ "stability-flags": {
+ "phpgangsta/googleauthenticator": 20
+ },
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
diff --git a/database/migrations/2021_06_10_150523_add_total_days_and_total_points_to_attendance_table.php b/database/migrations/2021_06_10_150523_add_total_days_and_total_points_to_attendance_table.php
new file mode 100644
index 00000000..eef06b57
--- /dev/null
+++ b/database/migrations/2021_06_10_150523_add_total_days_and_total_points_to_attendance_table.php
@@ -0,0 +1,36 @@
+integer('total_days')->default(0);
+ $table->integer('total_points')->default(0);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('attendance', function (Blueprint $table) {
+ $table->dropColumn(['total_days', 'total_points']);
+ });
+ }
+}
diff --git a/database/migrations/2021_06_10_181005_add_two_step_secret_to_users_table.php b/database/migrations/2021_06_10_181005_add_two_step_secret_to_users_table.php
new file mode 100644
index 00000000..ccf3d8cb
--- /dev/null
+++ b/database/migrations/2021_06_10_181005_add_two_step_secret_to_users_table.php
@@ -0,0 +1,35 @@
+string('two_step_secret')->default('');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('users', function (Blueprint $table) {
+ $table->dropColumn('two_step_secret');
+ });
+ }
+}
diff --git a/include/functions.php b/include/functions.php
index aad8b560..db249aba 100644
--- a/include/functions.php
+++ b/include/functions.php
@@ -2476,7 +2476,7 @@ else {
= UC_SYSOP) { ?> []
[]
[]:
- %s', $lang_functions['text_attendance']);}?>
+ %s', $lang_functions['text_attendance']);}?>
[]:
diff --git a/include/globalfunctions.php b/include/globalfunctions.php
index 9ab5e189..8efb2e22 100644
--- a/include/globalfunctions.php
+++ b/include/globalfunctions.php
@@ -544,16 +544,33 @@ function fail(...$args)
function last_query($all = false)
{
- if (IN_NEXUS) {
- $queries = \Illuminate\Database\Capsule\Manager::connection(\Nexus\Database\NexusDB::ELOQUENT_CONNECTION_NAME)->getQueryLog();
- } else {
- $queries = \Illuminate\Support\Facades\DB::connection(config('database.default'))->getQueryLog();
+ static $connection, $pdo;
+ if (is_null($connection)) {
+ if (IN_NEXUS) {
+ $connection = \Illuminate\Database\Capsule\Manager::connection(\Nexus\Database\NexusDB::ELOQUENT_CONNECTION_NAME);
+ } else {
+ $connection = \Illuminate\Support\Facades\DB::connection(config('database.default'));
+ }
+ $pdo = $connection->getPdo();
+ }
+ $queries = $connection->getQueryLog();
+ if (!$all) {
+ $queries = [last($queries)];
+ }
+ $queryFormatted = [];
+ foreach ($queries as $query) {
+ $sqlWithPlaceholders = str_replace(['%', '?'], ['%%', '%s'], $query['query']);
+ $bindings = $query['bindings'];
+ $realSql = $sqlWithPlaceholders;
+ if (count($bindings) > 0) {
+ $realSql = vsprintf($sqlWithPlaceholders, array_map([$pdo, 'quote'], $bindings));
+ }
+ $queryFormatted[] = $realSql;
}
if ($all) {
- return nexus_json_encode($queries);
+ return nexus_json_encode($queryFormatted);
}
- $query = last($queries);
- return nexus_json_encode($query);
+ return $queryFormatted[0];
}
function format_datetime($datetime, $format = 'Y-m-d H:i')
diff --git a/lang/chs/lang_login.php b/lang/chs/lang_login.php
index 4ff579ce..45c5a941 100644
--- a/lang/chs/lang_login.php
+++ b/lang/chs/lang_login.php
@@ -32,5 +32,7 @@ $lang_login = array
'submit_clear' => "清空",
'text_select_lang' => "Select Site Language: ",
'head_login' => "登录",
+ 'rowhead_two_step_code' => '两步验证',
+ 'two_step_code_tooltip' => '如有设置必须填写',
);
?>
diff --git a/lang/chs/lang_takelogin.php b/lang/chs/lang_takelogin.php
index b6d45f95..862826fe 100644
--- a/lang/chs/lang_takelogin.php
+++ b/lang/chs/lang_takelogin.php
@@ -6,6 +6,8 @@ $lang_takelogin = array
'std_login_fail' => "登录失败!",
'std_account_disabled' => "该账号已被禁用。",
'std_user_account_unconfirmed' => "该账户还未通过验证。如果你没有收到验证邮件,试试重新发送验证邮件。",
+ 'std_require_two_step_code' => '需要两步验证 code',
+ 'std_invalid_two_step_code' => '两步验证 code 无效',
);
?>
diff --git a/lang/chs/lang_usercp.php b/lang/chs/lang_usercp.php
index 8fa27dff..b7883f75 100644
--- a/lang/chs/lang_usercp.php
+++ b/lang/chs/lang_usercp.php
@@ -245,7 +245,12 @@ $lang_usercp = array
'text_show_advertisement_note' => "我想看到广告",
'row_promotion_link' => "宣传链接",
'text_update_promotion_link' => "更新宣传链接",
- 'text_read_more' => "了解更多"
+ 'text_read_more' => "了解更多",
+ 'row_two_step_secret' => '两步验证',
+ 'text_two_step_secret_bind_by_qrdoe_note' => '你可以使用 Google Authenticator 或 Authy 扫描左侧二维码
如果左侧二维码没有加载成功,可以尝试打开此链接进行加载:',
+ 'text_two_step_secret_bind_manually_note' => '或者在 APP 中手动输入以下 Key:',
+ 'text_two_step_secret_bind_complete_note' => '输入 code 完成两步验证',
+ 'text_two_step_secret_unbind_note' => '输入 code 取消两步验证',
);
?>
diff --git a/lang/en/lang_usercp.php b/lang/en/lang_usercp.php
index e69d75d5..abc25b87 100644
--- a/lang/en/lang_usercp.php
+++ b/lang/en/lang_usercp.php
@@ -245,7 +245,10 @@ $lang_usercp = array
'text_show_advertisement_note' => "I'd like to see the advertisements",
'row_promotion_link' => "Promotion Link",
'text_update_promotion_link' => "Update Promotion Link",
- 'text_read_more' => "Read More"
+ 'text_read_more' => "Read More",
+ 'row_two_step_secret' => 'Two step authentication',
+ 'text_two_step_secret_bind_note' => '',
+ 'text_two_step_secret_remove_note' => '',
);
?>
diff --git a/public/login.php b/public/login.php
index c202262d..e1620f69 100644
--- a/public/login.php
+++ b/public/login.php
@@ -53,6 +53,7 @@ if (!empty($_GET["returnto"])) {
| ".$lang_usercp['row_security_check']." | ".$lang_usercp['text_security_check_note']." |