only 2 buttons in asan login, and re-auth system
This commit is contained in:
parent
4d9cbc008a
commit
0a9ad34362
|
|
@ -467,6 +467,7 @@ def select_certificate(asan_login_name, certificate_data, certificate_name):
|
|||
}
|
||||
|
||||
except Exception as e:
|
||||
frappe.log_error(f"Error in select_certificate: {str(e)}\n{frappe.get_traceback()}", "Select Certificate Error")
|
||||
return {"success": False, "message": f"Error: {str(e)}"}
|
||||
|
||||
@frappe.whitelist()
|
||||
|
|
@ -501,6 +502,12 @@ def select_taxpayer(asan_login_name):
|
|||
if not owner_type or not tin:
|
||||
return {"success": False, "message": "Invalid certificate data. Cannot determine taxpayer type or ID."}
|
||||
|
||||
# Логируем попытку выбора налогоплательщика
|
||||
frappe.log_error(
|
||||
f"Attempting to choose taxpayer: type={owner_type}, tin={tin}, bearer_token={asan_login.bearer_token[:10]}...",
|
||||
"Choose Taxpayer"
|
||||
)
|
||||
|
||||
# Выбираем налогоплательщика
|
||||
taxpayer_result = choose_taxpayer(asan_login.bearer_token, owner_type, tin)
|
||||
|
||||
|
|
@ -520,14 +527,27 @@ def select_taxpayer(asan_login_name):
|
|||
asan_login.auth_status = "Fully Authenticated"
|
||||
asan_login.save()
|
||||
|
||||
# Логируем успешный выбор налогоплательщика
|
||||
frappe.log_error(
|
||||
f"Successfully chose taxpayer: type={owner_type}, tin={tin}, main_token={asan_login.main_token[:10]}...",
|
||||
"Choose Taxpayer Success"
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Taxpayer selected successfully."
|
||||
}
|
||||
else:
|
||||
# Логируем ошибку выбора налогоплательщика
|
||||
frappe.log_error(
|
||||
f"Failed to choose taxpayer: type={owner_type}, tin={tin}, response={taxpayer_result}",
|
||||
"Choose Taxpayer Error"
|
||||
)
|
||||
|
||||
return {"success": False, "message": "Failed to select taxpayer."}
|
||||
|
||||
except Exception as e:
|
||||
frappe.log_error(f"Error in select_taxpayer: {str(e)}\n{frappe.get_traceback()}", "Choose Taxpayer Exception")
|
||||
return {"success": False, "message": f"Error: {str(e)}"}
|
||||
|
||||
@frappe.whitelist()
|
||||
|
|
@ -2457,3 +2477,17 @@ def create_unmapped_parties(settings_name):
|
|||
"message": str(e)
|
||||
}
|
||||
|
||||
def handle_unauthorized_request(asan_login_name, operation_name="API request"):
|
||||
"""Общая функция для обработки неавторизованных запросов"""
|
||||
# Логирование события
|
||||
frappe.log_error(
|
||||
f"Unauthorized request for operation: {operation_name}, asan_login_name: {asan_login_name}",
|
||||
"Unauthorized API Request"
|
||||
)
|
||||
|
||||
return {
|
||||
"error": "unauthorized",
|
||||
"message": "Authentication required. Please login again.",
|
||||
"operation": operation_name
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,80 +48,80 @@ frappe.ui.form.on('Asan Login', {
|
|||
}, __('Login'));
|
||||
|
||||
// Кнопка для получения сертификатов (доступна только если авторизация успешна)
|
||||
if (frm.doc.auth_status === 'Authenticated' || frm.doc.auth_status === 'Fully Authenticated') {
|
||||
frm.add_custom_button(__('Get Certificates'), function() {
|
||||
frappe.call({
|
||||
method: 'invoice_az.api.get_auth_certificates',
|
||||
args: {
|
||||
'asan_login_name': frm.doc.name
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message && r.message.success) {
|
||||
// Обновляем форму после успешного получения сертификатов
|
||||
frm.reload_doc();
|
||||
// if (frm.doc.auth_status === 'Authenticated' || frm.doc.auth_status === 'Fully Authenticated') {
|
||||
// frm.add_custom_button(__('Get Certificates'), function() {
|
||||
// frappe.call({
|
||||
// method: 'invoice_az.api.get_auth_certificates',
|
||||
// args: {
|
||||
// 'asan_login_name': frm.doc.name
|
||||
// },
|
||||
// callback: function(r) {
|
||||
// if (r.message && r.message.success) {
|
||||
// // Обновляем форму после успешного получения сертификатов
|
||||
// frm.reload_doc();
|
||||
|
||||
// Показываем сообщение об успешном получении сертификатов
|
||||
frappe.msgprint({
|
||||
title: __('Success'),
|
||||
indicator: 'green',
|
||||
message: __('Certificates retrieved successfully')
|
||||
});
|
||||
// // Показываем сообщение об успешном получении сертификатов
|
||||
// frappe.msgprint({
|
||||
// title: __('Success'),
|
||||
// indicator: 'green',
|
||||
// message: __('Certificates retrieved successfully')
|
||||
// });
|
||||
|
||||
// Отображаем список сертификатов в диалоговом окне
|
||||
if (r.message.certificates) {
|
||||
showCertificatesDialog(r.message.certificates, frm);
|
||||
}
|
||||
} else if (r.message && r.message.unauthorized) {
|
||||
// Если ошибка авторизации, предлагаем авторизоваться заново
|
||||
showAuthDialog(frm);
|
||||
} else {
|
||||
// Другие ошибки
|
||||
frappe.msgprint({
|
||||
title: __('Error'),
|
||||
indicator: 'red',
|
||||
message: r.message ? r.message.message : __('Failed to get certificates')
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
// // Отображаем список сертификатов в диалоговом окне
|
||||
// if (r.message.certificates) {
|
||||
// showCertificatesDialog(r.message.certificates, frm);
|
||||
// }
|
||||
// } else if (r.message && r.message.unauthorized) {
|
||||
// // Если ошибка авторизации, предлагаем авторизоваться заново
|
||||
// showAuthDialog(frm);
|
||||
// } else {
|
||||
// // Другие ошибки
|
||||
// frappe.msgprint({
|
||||
// title: __('Error'),
|
||||
// indicator: 'red',
|
||||
// message: r.message ? r.message.message : __('Failed to get certificates')
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }, __('Actions'));
|
||||
// }
|
||||
|
||||
// Кнопка для выбора налогоплательщика (доступна если авторизация успешна и сертификат выбран)
|
||||
if ((frm.doc.auth_status === 'Authenticated' || frm.doc.auth_status === 'Fully Authenticated') &&
|
||||
frm.doc.selected_certificate) {
|
||||
frm.add_custom_button(__('Choose Taxpayer'), function() {
|
||||
frappe.call({
|
||||
method: 'invoice_az.api.select_taxpayer',
|
||||
args: {
|
||||
'asan_login_name': frm.doc.name
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message && r.message.success) {
|
||||
// Обновляем форму после успешного выбора налогоплательщика
|
||||
frm.reload_doc();
|
||||
// if ((frm.doc.auth_status === 'Authenticated' || frm.doc.auth_status === 'Fully Authenticated') &&
|
||||
// frm.doc.selected_certificate) {
|
||||
// frm.add_custom_button(__('Choose Taxpayer'), function() {
|
||||
// frappe.call({
|
||||
// method: 'invoice_az.api.select_taxpayer',
|
||||
// args: {
|
||||
// 'asan_login_name': frm.doc.name
|
||||
// },
|
||||
// callback: function(r) {
|
||||
// if (r.message && r.message.success) {
|
||||
// // Обновляем форму после успешного выбора налогоплательщика
|
||||
// frm.reload_doc();
|
||||
|
||||
// Показываем сообщение об успешном выборе
|
||||
frappe.msgprint({
|
||||
title: __('Success'),
|
||||
indicator: 'green',
|
||||
message: __('Taxpayer selected successfully')
|
||||
});
|
||||
} else if (r.message && r.message.unauthorized) {
|
||||
// Если ошибка авторизации, предлагаем авторизоваться заново
|
||||
showAuthDialog(frm);
|
||||
} else {
|
||||
// Другие ошибки
|
||||
frappe.msgprint({
|
||||
title: __('Error'),
|
||||
indicator: 'red',
|
||||
message: r.message ? r.message.message : __('Failed to select taxpayer')
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
}
|
||||
// // Показываем сообщение об успешном выборе
|
||||
// frappe.msgprint({
|
||||
// title: __('Success'),
|
||||
// indicator: 'green',
|
||||
// message: __('Taxpayer selected successfully')
|
||||
// });
|
||||
// } else if (r.message && r.message.unauthorized) {
|
||||
// // Если ошибка авторизации, предлагаем авторизоваться заново
|
||||
// showAuthDialog(frm);
|
||||
// } else {
|
||||
// // Другие ошибки
|
||||
// frappe.msgprint({
|
||||
// title: __('Error'),
|
||||
// indicator: 'red',
|
||||
// message: r.message ? r.message.message : __('Failed to select taxpayer')
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }, __('Actions'));
|
||||
// }
|
||||
|
||||
// Обработчик изменения выбранного сертификата
|
||||
if (frm.doc.certificates_json) {
|
||||
|
|
@ -194,7 +194,7 @@ frappe.ui.form.on('Asan Login', {
|
|||
});
|
||||
|
||||
// Функция для запуска опроса через setTimeout вместо setInterval
|
||||
function startPollingWithTimeout(frm) {
|
||||
function startPollingWithTimeout(frm, successCallback) {
|
||||
console.log('startPollingWithTimeout function has been called');
|
||||
|
||||
// Отображаем индикатор загрузки
|
||||
|
|
@ -257,15 +257,16 @@ function startPollingWithTimeout(frm) {
|
|||
`);
|
||||
$('.lds-dual-ring').css('display', 'none');
|
||||
|
||||
// Обновляем поле auth_status
|
||||
// Обновляем поле auth_status и сохраняем
|
||||
frm.set_value('auth_status', 'Failed');
|
||||
frm.save();
|
||||
|
||||
// Закрываем диалог через 3 секунды
|
||||
setTimeout(function() {
|
||||
// Меняем кнопку на "Close"
|
||||
status_dialog.set_primary_action(__('Close'), function() {
|
||||
status_dialog.hide();
|
||||
frm.reload_doc();
|
||||
}, 3000);
|
||||
|
||||
// Сохраняем документ и затем обновляем его с сервера
|
||||
frm.save().then(() => frm.reload_doc());
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -294,10 +295,28 @@ function startPollingWithTimeout(frm) {
|
|||
`);
|
||||
$('.lds-dual-ring').css('display', 'none');
|
||||
|
||||
// Закрываем диалоговое окно через 2 секунды
|
||||
// Обновляем кнопку
|
||||
status_dialog.set_primary_action(__('Continue'), function() {
|
||||
status_dialog.hide();
|
||||
|
||||
// Вызываем callback после успешной аутентификации, если он предоставлен
|
||||
if (typeof successCallback === 'function') {
|
||||
successCallback();
|
||||
} else {
|
||||
frm.reload_doc();
|
||||
}
|
||||
});
|
||||
|
||||
// Автоматически закрываем диалог через 2 секунды
|
||||
setTimeout(function() {
|
||||
status_dialog.hide();
|
||||
frm.reload_doc();
|
||||
|
||||
// Вызываем callback после успешной аутентификации, если он предоставлен
|
||||
if (typeof successCallback === 'function') {
|
||||
successCallback();
|
||||
} else {
|
||||
frm.reload_doc();
|
||||
}
|
||||
}, 2000);
|
||||
} else {
|
||||
// Продолжаем опрос
|
||||
|
|
@ -316,13 +335,14 @@ function startPollingWithTimeout(frm) {
|
|||
|
||||
// Обновляем поле auth_status
|
||||
frm.set_value('auth_status', 'Failed');
|
||||
frm.save();
|
||||
|
||||
// Закрываем диалог через 3 секунды
|
||||
setTimeout(function() {
|
||||
// Меняем кнопку на "Close"
|
||||
status_dialog.set_primary_action(__('Close'), function() {
|
||||
status_dialog.hide();
|
||||
frm.reload_doc();
|
||||
}, 3000);
|
||||
|
||||
// Сохраняем документ и затем обновляем его с сервера
|
||||
frm.save().then(() => frm.reload_doc());
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(err) {
|
||||
|
|
@ -496,22 +516,95 @@ function showAuthDialog(frm) {
|
|||
primary_action: function() {
|
||||
d.hide();
|
||||
|
||||
// Показываем сообщение о начале аутентификации
|
||||
frappe.show_alert({
|
||||
message: __('Starting authentication process...'),
|
||||
indicator: 'blue'
|
||||
}, 3);
|
||||
|
||||
// Вызываем процесс аутентификации
|
||||
frappe.call({
|
||||
method: 'invoice_az.api.handle_authentication',
|
||||
args: {
|
||||
'asan_login_name': frm.doc.name
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: __('Sending authentication request...'),
|
||||
callback: function(r) {
|
||||
if (r.message && r.message.success) {
|
||||
// Сохраняем токен в документе и запускаем опрос статуса
|
||||
if (r.message.bearer_token) {
|
||||
frm.set_value('bearer_token', r.message.bearer_token);
|
||||
frm.save();
|
||||
}
|
||||
// Получаем bearer_token из ответа
|
||||
const bearerToken = r.message.bearer_token;
|
||||
|
||||
// Запускаем опрос статуса
|
||||
startPollingWithTimeout(frm);
|
||||
// Обновляем значение в документе
|
||||
frm.set_value('bearer_token', bearerToken);
|
||||
|
||||
// Запускаем опрос с передачей сертификата и налогоплательщика как callback
|
||||
// для автоматического восстановления сессии
|
||||
pollAuthenticationStatus(frm, function() {
|
||||
// После успешной аутентификации проверяем, был ли ранее выбран сертификат
|
||||
if (frm.doc.selected_certificate_json) {
|
||||
try {
|
||||
var certData = JSON.parse(frm.doc.selected_certificate_json);
|
||||
var certName = frm.doc.selected_certificate;
|
||||
|
||||
frappe.show_alert({
|
||||
message: __('Automatically restoring your session...'),
|
||||
indicator: 'blue'
|
||||
}, 3);
|
||||
|
||||
// Сначала восстанавливаем сертификат
|
||||
frappe.call({
|
||||
method: 'invoice_az.api.select_certificate',
|
||||
args: {
|
||||
'asan_login_name': frm.doc.name,
|
||||
'certificate_data': certData,
|
||||
'certificate_name': certName
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message && r.message.success) {
|
||||
// Затем восстанавливаем налогоплательщика
|
||||
frappe.call({
|
||||
method: 'invoice_az.api.select_taxpayer',
|
||||
args: {
|
||||
'asan_login_name': frm.doc.name
|
||||
},
|
||||
callback: function(r2) {
|
||||
if (r2.message && r2.message.success) {
|
||||
frappe.show_alert({
|
||||
message: __('Session restored successfully'),
|
||||
indicator: 'green'
|
||||
}, 5);
|
||||
} else {
|
||||
frappe.show_alert({
|
||||
message: __('Partial session restore - please select certificate manually'),
|
||||
indicator: 'orange'
|
||||
}, 5);
|
||||
}
|
||||
|
||||
// Обновляем документ с сервера
|
||||
frm.reload_doc();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
frappe.show_alert({
|
||||
message: __('Please select your certificate manually'),
|
||||
indicator: 'orange'
|
||||
}, 5);
|
||||
|
||||
// Обновляем документ с сервера
|
||||
frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Error restoring certificate:', e);
|
||||
frm.reload_doc();
|
||||
}
|
||||
} else {
|
||||
// Если сертификат не выбран, просто обновляем документ
|
||||
frm.reload_doc();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Показываем сообщение об ошибке
|
||||
frappe.msgprint({
|
||||
|
|
@ -531,3 +624,147 @@ function showAuthDialog(frm) {
|
|||
|
||||
d.show();
|
||||
}
|
||||
|
||||
// Отдельная функция для опроса статуса аутентификации
|
||||
function pollAuthenticationStatus(frm, successCallback) {
|
||||
// Создаем всплывающее окно с информацией
|
||||
const status_dialog = new frappe.ui.Dialog({
|
||||
title: __('Authentication Status'),
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'status_html',
|
||||
fieldtype: 'HTML',
|
||||
options: `
|
||||
<div class="text-center">
|
||||
<div class="lds-dual-ring" style="display: inline-block; width: 64px; height: 64px;">
|
||||
<div style="width: 64px; height: 64px; border: 6px solid #4e73df; border-radius: 50%; border-color: #4e73df transparent #4e73df transparent; animation: lds-dual-ring 1.2s linear infinite;"></div>
|
||||
</div>
|
||||
<style>
|
||||
@keyframes lds-dual-ring {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
<div class="mt-3" id="poll_status_message">
|
||||
<h4>Waiting for confirmation on your phone</h4>
|
||||
<p>Please check your phone and confirm the authentication request.</p>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
],
|
||||
primary_action_label: __('Cancel'),
|
||||
primary_action: function() {
|
||||
// Останавливаем опрос и скрываем диалог
|
||||
stopPolling = true;
|
||||
status_dialog.hide();
|
||||
|
||||
// Обновляем документ с сервера
|
||||
frm.reload_doc();
|
||||
}
|
||||
});
|
||||
|
||||
status_dialog.show();
|
||||
|
||||
// Счетчик попыток и флаг для остановки опроса
|
||||
let attempts = 0;
|
||||
const maxAttempts = 20; // 20 попыток с интервалом 6 секунд
|
||||
let stopPolling = false;
|
||||
|
||||
// Функция опроса
|
||||
function pollStatus() {
|
||||
// Если достигнуто максимальное количество попыток или установлен флаг остановки
|
||||
if (attempts >= maxAttempts || stopPolling) {
|
||||
console.log('Polling stopped: ' + (attempts >= maxAttempts ? 'max attempts reached' : 'manually cancelled'));
|
||||
|
||||
if (attempts >= maxAttempts) {
|
||||
// Обновляем информацию в диалоговом окне по таймауту
|
||||
$('#poll_status_message').html(`
|
||||
<h4 style="color: red;">Authentication Timeout</h4>
|
||||
<p>The authentication request has timed out. Please try again.</p>
|
||||
`);
|
||||
$('.lds-dual-ring').css('display', 'none');
|
||||
|
||||
// Меняем кнопку на "Close"
|
||||
status_dialog.set_primary_action(__('Close'), function() {
|
||||
status_dialog.hide();
|
||||
|
||||
// Устанавливаем статус "Failed" и перезагружаем документ
|
||||
frm.set_value('auth_status', 'Failed');
|
||||
frm.save().then(() => frm.reload_doc());
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
attempts++;
|
||||
console.log(`Polling auth status, attempt ${attempts} of ${maxAttempts}`);
|
||||
|
||||
// Проверяем статус авторизации
|
||||
frappe.call({
|
||||
method: 'invoice_az.api.poll_auth_status',
|
||||
args: {
|
||||
'asan_login_name': frm.doc.name,
|
||||
'bearer_token': frm.doc.bearer_token
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message && r.message.success) {
|
||||
if (r.message.authenticated) {
|
||||
// Авторизация успешна
|
||||
stopPolling = true;
|
||||
|
||||
// Обновляем информацию в диалоговом окне
|
||||
$('#poll_status_message').html(`
|
||||
<h4 style="color: green;">Authentication Successful!</h4>
|
||||
<p>You are now authenticated.</p>
|
||||
`);
|
||||
$('.lds-dual-ring').css('display', 'none');
|
||||
|
||||
// Меняем кнопку на "Continue"
|
||||
status_dialog.set_primary_action(__('Continue'), function() {
|
||||
status_dialog.hide();
|
||||
|
||||
// Выполняем callback, если он предоставлен
|
||||
if (typeof successCallback === 'function') {
|
||||
successCallback();
|
||||
} else {
|
||||
frm.reload_doc();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Продолжаем опрос
|
||||
setTimeout(pollStatus, 6000);
|
||||
}
|
||||
} else {
|
||||
// Если ошибка, останавливаем опрос и показываем сообщение
|
||||
stopPolling = true;
|
||||
|
||||
// Обновляем информацию в диалоговом окне
|
||||
$('#poll_status_message').html(`
|
||||
<h4 style="color: red;">Authentication Error</h4>
|
||||
<p>${r.message ? r.message.message : 'An unknown error occurred.'}</p>
|
||||
`);
|
||||
$('.lds-dual-ring').css('display', 'none');
|
||||
|
||||
// Меняем кнопку на "Close"
|
||||
status_dialog.set_primary_action(__('Close'), function() {
|
||||
status_dialog.hide();
|
||||
|
||||
// Устанавливаем статус "Failed" и перезагружаем документ
|
||||
frm.set_value('auth_status', 'Failed');
|
||||
frm.save().then(() => frm.reload_doc());
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(err) {
|
||||
// В случае ошибки продолжаем опрос
|
||||
console.error('Error during status check:', err);
|
||||
setTimeout(pollStatus, 6000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Начинаем опрос
|
||||
pollStatus();
|
||||
}
|
||||
Loading…
Reference in New Issue