fix(auth): address code review feedback - accessibility, docstrings, portable test paths
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> Agent-Logs-Url: https://github.com/christianlouis/DocuElevate/sessions/51d9bb59-d4b5-4713-9a4a-8acfc599e2cc
This commit is contained in:
+10
-1
@@ -109,6 +109,15 @@ def _dropbox_userinfo_compliance_fix(client, user_cls, token, data):
|
|||||||
Dropbox's /2/users/get_current_account returns a non-standard response
|
Dropbox's /2/users/get_current_account returns a non-standard response
|
||||||
format. This compliance fix normalizes the response data — the HTTP
|
format. This compliance fix normalizes the response data — the HTTP
|
||||||
method (POST) is handled by authlib's compliance infrastructure.
|
method (POST) is handled by authlib's compliance infrastructure.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
client: The OAuth client instance (required by authlib compliance fix interface).
|
||||||
|
user_cls: The user class (required by authlib compliance fix interface).
|
||||||
|
token: The OAuth token dict.
|
||||||
|
data: The raw userinfo response dict from Dropbox.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The normalized userinfo dict with ``sub`` and ``name`` fields.
|
||||||
"""
|
"""
|
||||||
# Dropbox returns account_id instead of sub
|
# Dropbox returns account_id instead of sub
|
||||||
if "account_id" in data and "sub" not in data:
|
if "account_id" in data and "sub" not in data:
|
||||||
@@ -435,7 +444,7 @@ async def login(request: Request):
|
|||||||
show_oauth = OAUTH_CONFIGURED
|
show_oauth = OAUTH_CONFIGURED
|
||||||
|
|
||||||
# SSO Auto Login: redirect directly to SSO provider if configured
|
# SSO Auto Login: redirect directly to SSO provider if configured
|
||||||
if show_oauth and getattr(settings, "sso_auto_login", False) is True and not error and not message:
|
if show_oauth and settings.sso_auto_login is True and not error and not message:
|
||||||
return RedirectResponse(url="/oauth-login", status_code=status.HTTP_302_FOUND)
|
return RedirectResponse(url="/oauth-login", status_code=status.HTTP_302_FOUND)
|
||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
|
|||||||
@@ -104,10 +104,13 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Service Configuration Modal -->
|
<!-- Service Configuration Modal -->
|
||||||
<div id="service-modal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4 hidden" role="dialog" aria-modal="true" aria-labelledby="service-modal-title">
|
<div id="service-modal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4 hidden" role="dialog" aria-modal="true" aria-labelledby="service-modal-title" aria-describedby="service-modal-description">
|
||||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-lg overflow-y-auto max-h-[90vh]" onclick="event.stopPropagation()">
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-lg overflow-y-auto max-h-[90vh]" onclick="event.stopPropagation()">
|
||||||
<div class="px-6 pt-6 pb-2 flex items-center justify-between border-b border-gray-200 dark:border-gray-700">
|
<div class="px-6 pt-6 pb-2 flex items-center justify-between border-b border-gray-200 dark:border-gray-700">
|
||||||
|
<div>
|
||||||
<h2 id="service-modal-title" class="text-lg font-semibold text-gray-900 dark:text-white"></h2>
|
<h2 id="service-modal-title" class="text-lg font-semibold text-gray-900 dark:text-white"></h2>
|
||||||
|
<p id="service-modal-description" class="text-xs text-gray-500 dark:text-gray-400 mt-1">{{ _("connections.save_note") }}</p>
|
||||||
|
</div>
|
||||||
<button type="button" onclick="closeServiceModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 rounded-md p-1" style="min-height:44px; min-width:44px" aria-label="Close">
|
<button type="button" onclick="closeServiceModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 rounded-md p-1" style="min-height:44px; min-width:44px" aria-label="Close">
|
||||||
<i class="fas fa-times text-xl" aria-hidden="true"></i>
|
<i class="fas fa-times text-xl" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
@@ -129,6 +132,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Accessible notification banner -->
|
||||||
|
<div id="save-notification" class="fixed top-4 right-4 z-[60] hidden max-w-sm" role="alert" aria-live="assertive">
|
||||||
|
<div id="save-notification-inner" class="rounded-lg shadow-lg px-4 py-3 text-sm font-medium flex items-center gap-2">
|
||||||
|
<i id="save-notification-icon" class="fas" aria-hidden="true"></i>
|
||||||
|
<span id="save-notification-text"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const serviceSettings = {{ service_settings | tojson }};
|
const serviceSettings = {{ service_settings | tojson }};
|
||||||
const settingMetadata = {};
|
const settingMetadata = {};
|
||||||
@@ -269,12 +280,12 @@ function saveServiceSettings(event) {
|
|||||||
closeServiceModal();
|
closeServiceModal();
|
||||||
location.reload();
|
location.reload();
|
||||||
} else {
|
} else {
|
||||||
alert('Some settings failed to save. Please check the values and try again.');
|
showNotification('error', 'Some settings failed to save. Please check the values and try again.');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
console.error('Error saving settings:', err);
|
console.error('Error saving settings:', err);
|
||||||
alert('Failed to save settings. Please try again.');
|
showNotification('error', 'Failed to save settings. Please try again.');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,5 +312,23 @@ document.addEventListener('keydown', function(e) {
|
|||||||
document.getElementById('service-modal')?.addEventListener('click', function(e) {
|
document.getElementById('service-modal')?.addEventListener('click', function(e) {
|
||||||
if (e.target === this) closeServiceModal();
|
if (e.target === this) closeServiceModal();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function showNotification(type, message) {
|
||||||
|
var el = document.getElementById('save-notification');
|
||||||
|
var inner = document.getElementById('save-notification-inner');
|
||||||
|
var icon = document.getElementById('save-notification-icon');
|
||||||
|
var text = document.getElementById('save-notification-text');
|
||||||
|
if (!el) return;
|
||||||
|
text.textContent = message;
|
||||||
|
if (type === 'error') {
|
||||||
|
inner.className = 'rounded-lg shadow-lg px-4 py-3 text-sm font-medium flex items-center gap-2 bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200';
|
||||||
|
icon.className = 'fas fa-exclamation-circle';
|
||||||
|
} else {
|
||||||
|
inner.className = 'rounded-lg shadow-lg px-4 py-3 text-sm font-medium flex items-center gap-2 bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200';
|
||||||
|
icon.className = 'fas fa-check-circle';
|
||||||
|
}
|
||||||
|
el.classList.remove('hidden');
|
||||||
|
setTimeout(function() { el.classList.add('hidden'); }, 5000);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ class TestTranslationKeys:
|
|||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
en_path = Path("/home/runner/work/DocuElevate/DocuElevate/frontend/translations/en.json")
|
en_path = Path(__file__).parents[1] / "frontend" / "translations" / "en.json"
|
||||||
translations = json.loads(en_path.read_text())
|
translations = json.loads(en_path.read_text())
|
||||||
|
|
||||||
expected_keys = [
|
expected_keys = [
|
||||||
|
|||||||
Reference in New Issue
Block a user