feat(problem/remote): validate remote account status
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Baoshuo Ren 2023-02-03 19:35:04 +08:00
parent 9f67331e6d
commit 50e7fdf1cc
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
4 changed files with 173 additions and 4 deletions

View File

@ -0,0 +1,86 @@
<?php
Auth::check() || redirectToLogin();
$type = UOJRequest::get('type', 'is_string', null);
$curl = new Curl\Curl();
$curl->setUserAgent(UOJRemoteProblem::USER_AGENT);
$res = false;
function validateLuogu($response) {
$response = json_decode(json_encode($response), true);
return $response['currentTemplate'] !== 'AuthLogin';
}
if ($type == 'luogu') {
$curl->setFollowLocation();
$curl->setCookie('_uid', UOJRequest::post('_uid', 'is_string', ''));
$curl->setCookie('__client_id', UOJRequest::post('__client_id', 'is_string', ''));
retry_loop(function () use (&$curl, &$res) {
$curl->get(UOJRemoteProblem::$providers['luogu']['url'] . '/user/setting?_contentOnly=1');
if ($curl->error) {
return false;
}
if ($curl->responseHeaders['Content-Type'] == 'text/html') {
$sec = $curl->getResponseCookie('sec');
if ($sec) {
$curl->setCookie('sec', $sec);
$curl->get(UOJRemoteProblem::$providers['luogu']['url'] . '/user/setting?_contentOnly=1');
if ($curl->responseHeaders['Content-Type'] == 'application/json') {
$res = validateLuogu($curl->response);
return true;
}
return false;
}
return false;
} else if ($curl->responseHeaders['Content-Type'] == 'application/json') {
$res = validateLuogu($curl->response);
return true;
}
return false;
}, 3);
die(json_encode(['ok' => $res === true]));
} else if ($type == 'codeforces') {
$curl->setFollowLocation();
$curl->setCookie('JSESSIONID', UOJRequest::post('JSESSIONID', 'is_string', ''));
retry_loop(function () use (&$curl, &$res) {
$curl->get(UOJRemoteProblem::$providers['codeforces']['url'] . '/enter');
if ($curl->error) {
return false;
}
if (str_starts_with($curl->responseHeaders['Content-Type'], 'text/html')) {
if (str_contains($curl->response, 'Login into Codeforces')) {
return false;
}
if (strlen($curl->response) < 1000 && str_contains($curl->response, 'Redirecting...')) {
return false;
}
$res = true;
return true;
}
return false;
}, 3);
} else {
UOJResponse::page406();
}
die(json_encode(['ok' => $res === true]));

View File

@ -0,0 +1,12 @@
<?php
call_user_func(function () { // to prevent variable scope leak
Route::group(
[
'domain' => UOJConfig::$data['web']['main']['host'],
],
function () {
Route::post("/api/remote_judge/custom_account_validator", '/subdomain/api/remote_judge/custom_account_validator.php');
}
);
});

View File

@ -5,6 +5,7 @@ require $_SERVER['DOCUMENT_ROOT'] . '/app/libs/uoj-lib.php';
require UOJContext::documentRoot().'/app/route.php'; require UOJContext::documentRoot().'/app/route.php';
require UOJContext::documentRoot().'/app/controllers/subdomain/blog/route.php'; require UOJContext::documentRoot().'/app/controllers/subdomain/blog/route.php';
require UOJContext::documentRoot().'/app/controllers/subdomain/api/route.php';
include UOJContext::documentRoot().'/app/controllers'.call_user_func(function() { include UOJContext::documentRoot().'/app/controllers'.call_user_func(function() {
$route = Route::dispatch(); $route = Route::dispatch();

View File

@ -958,11 +958,48 @@ $.fn.remote_submit_type_group = function(oj, pid, url, submit_type) {
var input_submit_type_bot = $('<input class="form-check-input" type="radio" name="answer_remote_submit_type" id="' + input_submit_type_bot_id + '" value="bot" />'); var input_submit_type_bot = $('<input class="form-check-input" type="radio" name="answer_remote_submit_type" id="' + input_submit_type_bot_id + '" value="bot" />');
var input_submit_type_my = $('<input class="form-check-input" type="radio" name="answer_remote_submit_type" id="' + input_submit_type_my_id + '" value="my" />'); var input_submit_type_my = $('<input class="form-check-input" type="radio" name="answer_remote_submit_type" id="' + input_submit_type_my_id + '" value="my" />');
var input_my_account_data = $('<input type="hidden" name="answer_remote_account_data" value="" />'); var input_my_account_data = $('<input type="hidden" name="answer_remote_account_data" value="" />');
var my_account_validation_status = $('<span />').append('<span class="text-secondary">待验证</span>');
var my_account_validation_btn = $('<button type="button" class="btn btn-secondary btn-sm ms-2">验证</button>');
var validate_my_account = function(data) {
my_account_validation_btn.html('<span class="spinner-border spinner-border-sm" role="status"></span>');
my_account_validation_btn.addClass('disabled');
$.ajax({
type: 'POST',
url: '/api/remote_judge/custom_account_validator?type=' + oj,
data: data,
success: function(res) {
my_account_validation_btn.html('验证');
my_account_validation_btn.removeClass('disabled');
console.log('Validation status', res);
if (res.ok) {
my_account_validation_status.html('<span class="text-success">可用</span>');
} else {
my_account_validation_status.html('<span class="text-danger">不可用</span>');
}
},
error: function() {
my_account_validation_btn.html('验证');
my_account_validation_btn.removeClass('disabled');
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
},
dataType: 'json',
});
};
var div_submit_type_bot = $('<div id="' + div_submit_type_bot_id + '" />') var div_submit_type_bot = $('<div id="' + div_submit_type_bot_id + '" />')
.append('<div class="mt-3">将使用公用账号提交本题。</div>'); .append('<div class="mt-3">将使用公用账号提交本题。</div>');
var div_submit_type_my = $('<div id="' + div_submit_type_my_id + '" />') var div_submit_type_my = $('<div id="' + div_submit_type_my_id + '" />')
.append('<div class="mt-3">将使用您的账号提交本题。</div>'); .append($('<div class="mt-3" />')
.append('<span>将使用您的账号提交本题。</span>')
.append('<span>账号状态:</span>')
.append(my_account_validation_status)
.append(my_account_validation_btn)
);
if ('localStorage' in window) { if ('localStorage' in window) {
var prefer_submit_type = localStorage.getItem('uoj_remote_judge_save_prefer_submit_type__' + oj) || null; var prefer_submit_type = localStorage.getItem('uoj_remote_judge_save_prefer_submit_type__' + oj) || null;
@ -1035,28 +1072,46 @@ $.fn.remote_submit_type_group = function(oj, pid, url, submit_type) {
luogu_account_data._uid = $(this).val(); luogu_account_data._uid = $(this).val();
input_my_account_data.val(JSON.stringify(luogu_account_data)); input_my_account_data.val(JSON.stringify(luogu_account_data));
save_luogu_account_data(); save_luogu_account_data();
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
}); });
input_luogu_client_id.change(function() { input_luogu_client_id.change(function() {
luogu_account_data.__client_id = $(this).val(); luogu_account_data.__client_id = $(this).val();
input_my_account_data.val(JSON.stringify(luogu_account_data)); input_my_account_data.val(JSON.stringify(luogu_account_data));
save_luogu_account_data(); save_luogu_account_data();
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
});
my_account_validation_btn.click(function() {
validate_my_account({
type: 'luogu',
_uid: input_luogu_uid.val(),
__client_id: input_luogu_client_id.val(),
});
}); });
input_my_account_data.val(JSON.stringify(luogu_account_data)); input_my_account_data.val(JSON.stringify(luogu_account_data));
input_luogu_uid.val(luogu_account_data._uid); input_luogu_uid.val(luogu_account_data._uid);
input_luogu_client_id.val(luogu_account_data.__client_id); input_luogu_client_id.val(luogu_account_data.__client_id);
if (luogu_account_data._uid && luogu_account_data.__client_id){
validate_my_account({
type: 'luogu',
_uid: luogu_account_data._uid,
__client_id: luogu_account_data.__client_id,
});
}
div_submit_type_my.append( div_submit_type_my.append(
$('<div class="row mt-3 align-items-center" />') $('<div class="row mt-3 align-items-center" />')
.append($('<div class="col-sm-2" />').append('<label for="input-luogu_uid" class="col-form-label">_uid</label>')) .append($('<div class="col-sm-2" />').append('<label for="input-luogu_uid" class="col-form-label">_uid</label>'))
.append($('<div class="col-sm-4" />').append(input_luogu_uid)) .append($('<div class="col-sm-4" />').append(input_luogu_uid))
.append($('<div class="col-sm-6" />').append($('<div class="form-text" />').append('请填入 Cookie 中的 <code>_uid</code>。'))) .append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请填入 Cookie 中的 <code>_uid</code>。')))
).append( ).append(
$('<div class="row mt-3 align-items-center" />') $('<div class="row mt-3 align-items-center" />')
.append($('<div class="col-sm-2" />').append('<label for="input-luogu_client_id" class="col-form-label">__client_id</label>')) .append($('<div class="col-sm-2" />').append('<label for="input-luogu_client_id" class="col-form-label">__client_id</label>'))
.append($('<div class="col-sm-4" />').append(input_luogu_client_id)) .append($('<div class="col-sm-4" />').append(input_luogu_client_id))
.append($('<div class="col-sm-6" />').append($('<div class="form-text" />').append('请填入 Cookie 中的 <code>__client_id</code>。'))) .append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请填入 Cookie 中的 <code>__client_id</code>。')))
).append(input_my_account_data); ).append(input_my_account_data);
} else if (oj == 'codeforces') { } else if (oj == 'codeforces') {
var codeforces_account_data = {"JSESSIONID": ""}; var codeforces_account_data = {"JSESSIONID": ""};
@ -1079,16 +1134,31 @@ $.fn.remote_submit_type_group = function(oj, pid, url, submit_type) {
codeforces_account_data.JSESSIONID = $(this).val(); codeforces_account_data.JSESSIONID = $(this).val();
input_my_account_data.val(JSON.stringify(codeforces_account_data)); input_my_account_data.val(JSON.stringify(codeforces_account_data));
save_codeforces_account_data(); save_codeforces_account_data();
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
});
my_account_validation_btn.click(function() {
validate_my_account({
type: 'codeforces',
JSESSIONID: input_codeforces_jsessionid.val(),
});
}); });
input_my_account_data.val(JSON.stringify(codeforces_account_data)); input_my_account_data.val(JSON.stringify(codeforces_account_data));
input_codeforces_jsessionid.val(codeforces_account_data.JSESSIONID); input_codeforces_jsessionid.val(codeforces_account_data.JSESSIONID);
if (codeforces_account_data.JSESSIONID) {
validate_my_account({
type: 'codeforces',
JSESSIONID: codeforces_account_data.JSESSIONID,
});
}
div_submit_type_my.append( div_submit_type_my.append(
$('<div class="row mt-3 align-items-center" />') $('<div class="row mt-3 align-items-center" />')
.append($('<div class="col-sm-2" />').append('<label for="input-codeforces_jsessionid" class="col-form-label">JSESSIONID</label>')) .append($('<div class="col-sm-2" />').append('<label for="input-codeforces_jsessionid" class="col-form-label">JSESSIONID</label>'))
.append($('<div class="col-sm-4" />').append(input_codeforces_jsessionid)) .append($('<div class="col-sm-4" />').append(input_codeforces_jsessionid))
.append($('<div class="col-sm-6" />').append($('<div class="form-text" />').append('请填入 Cookie 中的 <code>JSESSIONID</code>。'))) .append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请填入 Cookie 中的 <code>JSESSIONID</code>。')))
).append(input_my_account_data); ).append(input_my_account_data);
} }