[admin] remove two-step authentication

This commit is contained in:
xiaomlove
2022-05-13 17:55:49 +08:00
parent 155d4ddcb6
commit a7d9a68db4
12 changed files with 70 additions and 38 deletions
+3 -1
View File
@@ -208,7 +208,9 @@ const api = {
pardonHrBulk: (params = {}) => { pardonHrBulk: (params = {}) => {
return axios.put('hr-pardon', params); return axios.put('hr-pardon', params);
}, },
removeTwoStepAuthentication: (params = {}) => {
return axios.put('user-remove-two-step', params);
},
} }
export default api export default api
+14 -20
View File
@@ -68,31 +68,24 @@
<td><el-button size="small" @click="handleViewInviteInfo">View</el-button></td> <td><el-button size="small" @click="handleViewInviteInfo">View</el-button></td>
</tr> </tr>
<tr> <tr>
<td>Seed points</td> <td>Two-step authentication</td>
<td>{{baseInfo.seed_points}}</td> <td>{{baseInfo.two_step_secret ? 'Enabled' : 'Disabled'}}</td>
</tr>
<tr>
<td>H&R inspecting</td>
<td>{{baseInfo.invites}}</td>
<td> <td>
<el-popconfirm <el-popconfirm
title="Confirm Remove ?" v-if="baseInfo.two_step_secret"
@confirm="handleRemoveHitAndRun" title="Confirm Disable Two-step authentication ?"
@confirm="handleRemoveTwoStepAuthentication"
> >
<template #reference> <template #reference>
<el-button size="small">Remove</el-button> <el-button type="default" size="small">Disable</el-button>
</template>
</el-popconfirm>
<el-popconfirm
title="Confirm Pardon ?"
@confirm="handlePardonHitAndRun"
>
<template #reference>
<el-button size="small">Pardon</el-button>
</template> </template>
</el-popconfirm> </el-popconfirm>
</td> </td>
</tr> </tr>
<tr>
<td>Seed points</td>
<td>{{baseInfo.seed_points}}</td>
</tr>
<tr> <tr>
<td>Invites</td> <td>Invites</td>
<td>{{baseInfo.invites}}</td> <td>{{baseInfo.invites}}</td>
@@ -356,12 +349,12 @@ export default {
ElMessage.success(res.msg) ElMessage.success(res.msg)
await fetchPageData() await fetchPageData()
} }
const handleRemoveTwoStepAuthentication = async () => {
const handleRemoveHitAndRun = async (id) => { let res = await api.removeTwoStepAuthentication({uid: id})
let res = await api.removeUserMedal(id)
ElMessage.success(res.msg) ElMessage.success(res.msg)
await fetchPageData() await fetchPageData()
} }
return { return {
...toRefs(state), ...toRefs(state),
handleRemoveExam, handleRemoveExam,
@@ -377,6 +370,7 @@ export default {
fetchPageData, fetchPageData,
handleRemoveUserMedal, handleRemoveUserMedal,
handleIncrementDecrement, handleIncrementDecrement,
handleRemoveTwoStepAuthentication,
assignExam, assignExam,
grantMedal, grantMedal,
viewInviteInfo, viewInviteInfo,
+3 -3
View File
@@ -7,13 +7,13 @@
:close-on-click-modal="false" :close-on-click-modal="false"
> >
<el-table :data="inviteInfo" v-loading="loading"> <el-table :data="inviteInfo" v-loading="loading">
<el-table-column prop="id" label="ID" width="55"></el-table-column> <el-table-column prop="id" label="ID" width="80"></el-table-column>
<el-table-column prop="inviter_user.username" label="Inviter" width="150"></el-table-column> <el-table-column prop="inviter_user.username" label="Inviter" width="150"></el-table-column>
<el-table-column prop="invitee" label="Receive email"></el-table-column> <el-table-column prop="invitee" label="Receive email"></el-table-column>
<el-table-column prop="hash" label="Hash"></el-table-column> <el-table-column prop="hash" label="Hash" width="300"></el-table-column>
<el-table-column prop="valid_text" label="Hash valid" width="100"></el-table-column> <el-table-column prop="valid_text" label="Hash valid" width="100"></el-table-column>
<el-table-column prop="invitee_register_email" label="Register email"></el-table-column> <el-table-column prop="invitee_register_email" label="Register email"></el-table-column>
<el-table-column prop="time_invited" label="Time invited" width="160"></el-table-column> <el-table-column prop="time_invited" label="Time invited" width="180"></el-table-column>
</el-table> </el-table>
</el-dialog> </el-dialog>
+10
View File
@@ -287,4 +287,14 @@ class UserController extends Controller
return $this->success(['success' => $result]); return $this->success(['success' => $result]);
} }
public function removeTwoStepAuthentication(Request $request): array
{
$user = Auth::user();
$request->validate([
'uid' => 'required',
]);
$result = $this->repository->removeTwoStepAuthentication($user, $request->uid, );
return $this->success(['success' => $result]);
}
} }
+5
View File
@@ -53,6 +53,11 @@ class UserResource extends JsonResource
$out['completed_torrents_count'] = $this->completed_torrents_count; $out['completed_torrents_count'] = $this->completed_torrents_count;
$out['incomplete_torrents_count'] = $this->incomplete_torrents_count; $out['incomplete_torrents_count'] = $this->incomplete_torrents_count;
} }
if (nexus()->isPlatformAdmin() && $request->routeIs('users.show')) {
$out['two_step_secret'] = $this->two_step_secret;
}
return $out; return $out;
} }
} }
+21 -7
View File
@@ -48,7 +48,7 @@ class UserRepository extends BaseRepository
'inviter' => function ($query) {return $query->select(User::$commonFields);}, 'inviter' => function ($query) {return $query->select(User::$commonFields);},
'valid_medals' 'valid_medals'
]; ];
$user = User::query()->with($with)->findOrFail($id, User::$commonFields); $user = User::query()->with($with)->findOrFail($id);
$userResource = new UserResource($user); $userResource = new UserResource($user);
$baseInfo = $userResource->response()->getData(true)['data']; $baseInfo = $userResource->response()->getData(true)['data'];
@@ -60,9 +60,6 @@ class UserRepository extends BaseRepository
} else { } else {
$examInfo = null; $examInfo = null;
} }
return [ return [
'base_info' => $baseInfo, 'base_info' => $baseInfo,
'exam_info' => $examInfo, 'exam_info' => $examInfo,
@@ -284,9 +281,7 @@ class UserRepository extends BaseRepository
public function removeLeechWarn($operator, $uid): bool public function removeLeechWarn($operator, $uid): bool
{ {
if (!$operator instanceof User) { $operator = $this->getOperator($operator);
$operator = User::query()->findOrFail(intval($operator), User::$commonFields);
}
$classRequire = Setting::get('authority.prfmanage'); $classRequire = Setting::get('authority.prfmanage');
if ($operator->class < $classRequire) { if ($operator->class < $classRequire) {
throw new \RuntimeException("No permission."); throw new \RuntimeException("No permission.");
@@ -298,6 +293,25 @@ class UserRepository extends BaseRepository
return $user->save(); return $user->save();
} }
public function removeTwoStepAuthentication($operator, $uid): bool
{
$operator = $this->getOperator($operator);
if (!$operator->canAccessAdmin()) {
throw new \RuntimeException("No permission.");
}
$user = User::query()->findOrFail($uid, User::$commonFields);
$user->two_step_secret = '';
return $user->save();
}
private function getOperator($operator)
{
if (!$operator instanceof User) {
$operator = User::query()->findOrFail(intval($operator), User::$commonFields);
}
return $operator;
}
} }
+3 -3
View File
@@ -1503,10 +1503,10 @@ function sent_mail($to,$fromname,$fromemail,$subject,$body,$type = "confirmation
@mail($to,"=?".$hdr_encoding."?B?".base64_encode($subject)."?=",$body,$headers) or stderr($lang_functions['std_error'], $lang_functions['text_unable_to_send_mail']); @mail($to,"=?".$hdr_encoding."?B?".base64_encode($subject)."?=",$body,$headers) or stderr($lang_functions['std_error'], $lang_functions['text_unable_to_send_mail']);
ini_restore(SMTP); ini_restore('SMTP');
ini_restore(smtp_port); ini_restore('smtp_port');
if ($windows) if ($windows)
ini_restore(sendmail_from); ini_restore('sendmail_from');
} }
elseif ($smtptype == 'external') { elseif ($smtptype == 'external') {
/* /*
+2
View File
@@ -6,6 +6,8 @@ $lang_takelogin = array
'std_login_fail' => "登錄失敗!", 'std_login_fail' => "登錄失敗!",
'std_account_disabled' => "該帳號已被禁用。", 'std_account_disabled' => "該帳號已被禁用。",
'std_user_account_unconfirmed' => "該賬戶還未通過驗證。如果你沒有收到驗證郵件,試試<a href='confirm_resend.php'><b>重新發送驗證郵件</b></a>。", 'std_user_account_unconfirmed' => "該賬戶還未通過驗證。如果你沒有收到驗證郵件,試試<a href='confirm_resend.php'><b>重新發送驗證郵件</b></a>。",
'std_require_two_step_code' => '需要兩步驗證 code',
'std_invalid_two_step_code' => '兩步驗證 code 無效',
); );
?> ?>
+1 -1
View File
@@ -69,7 +69,7 @@ $lang_index = array
'text_peers_active_now' => " users are seeding or leeching. ", 'text_peers_active_now' => " users are seeding or leeching. ",
'text_disclaimer' => "Disclaimer", 'text_disclaimer' => "Disclaimer",
'text_disclaimer_content' => "None of the files shown here are actually hosted on this server. The tracker only manages connections, it does not have any knowledge of the contents of the files being distributed. The links are provided solely by this site's users. The administrator of this site ".$SITENAME." cannot be held responsible for what its users post, or any other actions of its users. You may not use this site ".$SITENAME." to distribute or download any material when you do not have the legal rights to do so. It is your own responsibility to adhere to these terms.", 'text_disclaimer_content' => "None of the files shown here are actually hosted on this server. The tracker only manages connections, it does not have any knowledge of the contents of the files being distributed. The links are provided solely by this site's users. The administrator of this site ".$SITENAME." cannot be held responsible for what its users post, or any other actions of its users. You may not use this site ".$SITENAME." to distribute or download any material when you do not have the legal rights to do so. It is your own responsibility to adhere to these terms.",
'text_browser_note' => "This site is best viewed with <a href=\"https://www.google.com/chrome/\" target=\"_blank\"><img class=\"img-browser\" src=\"/pic/misc/chrome-logo.svg\" alt=\"Google Chrome\" title=\"Get Google Chrome\" /></a>or<a href=\"https://www.mozilla.org/en-US/firefox/new/\" target=\"_blank\"><img class=\"firefox\" src=\"/pic/misc/firefox-logo.svg\" alt=\"Firefox\" title=\"Get Firefox\" border=\"0\" /></a> and with resolution above 1024*768. Recommended BitTorrent clients: <a href=\"https://www.qbittorrent.org/download.php\" target=\"_blank\"><img class=\"img-browser\" src=\"/pic/misc/qBittorrent.ico\" alt=\"qBittorrent\" title=\"Get qBittorrent\" /></a>or<a href=\"https://transmissionbt.com/download/\" target=\"_blank\"><img class=\"utorrent\" src=\"/pic/misc/transmission.png\" alt=\"Transmission\" title=\"Get Transmission\" /></a>", 'text_browser_note' => "This site is best viewed with <a href=\"https://www.google.com/chrome/\" target=\"_blank\"><img class=\"img-browser\" src=\"/pic/misc/chrome-logo.svg\" alt=\"Google Chrome\" title=\"Get Google Chrome\" /></a>or<a href=\"https://www.mozilla.org/en-US/firefox/new/\" target=\"_blank\"><img class=\"img-browser\" src=\"/pic/misc/firefox-logo.svg\" alt=\"Firefox\" title=\"Get Firefox\" border=\"0\" /></a> and with resolution above 1024*768. Recommended BitTorrent clients: <a href=\"https://www.qbittorrent.org/download.php\" target=\"_blank\"><img class=\"img-browser\" src=\"/pic/misc/qBittorrent.ico\" alt=\"qBittorrent\" title=\"Get qBittorrent\" /></a>or<a href=\"https://transmissionbt.com/download/\" target=\"_blank\"><img class=\"img-browser\" src=\"/pic/misc/transmission.png\" alt=\"Transmission\" title=\"Get Transmission\" /></a>",
'title_show_or_hide' => "Show/Hide", 'title_show_or_hide' => "Show/Hide",
'text_links' => "Links", 'text_links' => "Links",
'text_manage_links' => "Manage Links", 'text_manage_links' => "Manage Links",
+2
View File
@@ -6,6 +6,8 @@ $lang_takelogin = array
'std_login_fail' => "Login failed!", 'std_login_fail' => "Login failed!",
'std_account_disabled' => "This account has been disabled.", 'std_account_disabled' => "This account has been disabled.",
'std_user_account_unconfirmed' => "The account has not been verified yet. If you didn't receive the confirmation email, try to <a href='confirm_resend.php'><b>reseed it</b></a>.", 'std_user_account_unconfirmed' => "The account has not been verified yet. If you didn't receive the confirmation email, try to <a href='confirm_resend.php'><b>reseed it</b></a>.",
'std_require_two_step_code' => 'Require two-step authentication code.',
'std_invalid_two_step_code' => 'Invalid two-step authentication code.',
); );
?> ?>
+5 -3
View File
@@ -47,8 +47,6 @@ $hash = md5(mt_rand(1,10000).$CURUSER['username'].TIMENOW.$CURUSER['passhash'])
$title = $SITENAME.$lang_takeinvite['mail_tilte']; $title = $SITENAME.$lang_takeinvite['mail_tilte'];
sql_query("INSERT INTO invites (inviter, invitee, hash, time_invited) VALUES ('".mysql_real_escape_string($id)."', '".mysql_real_escape_string($email)."', '".mysql_real_escape_string($hash)."', " . sqlesc(date("Y-m-d H:i:s")) . ")");
sql_query("UPDATE users SET invites = invites - 1 WHERE id = ".mysql_real_escape_string($id)) or sqlerr(__FILE__, __LINE__);
$signupUrl = getSchemeAndHttpHost() . "/signup.php?type=invite&invitenumber=$hash"; $signupUrl = getSchemeAndHttpHost() . "/signup.php?type=invite&invitenumber=$hash";
$message = <<<EOD $message = <<<EOD
{$lang_takeinvite['mail_one']}{$arr['username']}{$lang_takeinvite['mail_two']} {$lang_takeinvite['mail_one']}{$arr['username']}{$lang_takeinvite['mail_two']}
@@ -59,8 +57,12 @@ $body
<br /><br />{$lang_takeinvite['mail_six']} <br /><br />{$lang_takeinvite['mail_six']}
EOD; EOD;
sent_mail($email,$SITENAME,$SITEEMAIL,$title,$message,"invitesignup",false,false,''); $sendResult = sent_mail($email,$SITENAME,$SITEEMAIL,$title,$message,"invitesignup",false,false,'');
//this email is sent only when someone give out an invitation //this email is sent only when someone give out an invitation
if ($sendResult === true) {
sql_query("INSERT INTO invites (inviter, invitee, hash, time_invited) VALUES ('".mysql_real_escape_string($id)."', '".mysql_real_escape_string($email)."', '".mysql_real_escape_string($hash)."', " . sqlesc(date("Y-m-d H:i:s")) . ")");
sql_query("UPDATE users SET invites = invites - 1 WHERE id = ".mysql_real_escape_string($id)) or sqlerr(__FILE__, __LINE__);
}
header("Refresh: 0; url=invite.php?id=".htmlspecialchars($id)."&sent=1"); header("Refresh: 0; url=invite.php?id=".htmlspecialchars($id)."&sent=1");
?> ?>
+1
View File
@@ -62,6 +62,7 @@ Route::group(['middleware' => ['auth:sanctum', 'locale']], function () {
Route::post('user-enable', [\App\Http\Controllers\UserController::class, 'enable']); Route::post('user-enable', [\App\Http\Controllers\UserController::class, 'enable']);
Route::post('user-reset-password', [\App\Http\Controllers\UserController::class, 'resetPassword']); Route::post('user-reset-password', [\App\Http\Controllers\UserController::class, 'resetPassword']);
Route::put('user-increment-decrement', [\App\Http\Controllers\UserController::class, 'incrementDecrement']); Route::put('user-increment-decrement', [\App\Http\Controllers\UserController::class, 'incrementDecrement']);
Route::put('user-remove-two-step', [\App\Http\Controllers\UserController::class, 'removeTwoStepAuthentication']);
Route::resource('exams', \App\Http\Controllers\ExamController::class); Route::resource('exams', \App\Http\Controllers\ExamController::class);
Route::get('exams-all', [\App\Http\Controllers\ExamController::class, 'all']); Route::get('exams-all', [\App\Http\Controllers\ExamController::class, 'all']);