Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion src/nine_rtksync/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,33 @@
"type.oauth": "OAuth 2.0",
"type.synced_model": "Synced model",
"type.virtual_key": "Virtual key",
"auth.authentication": "Authentication"
"auth.authentication": "Authentication",
"auth.item_airplane": "Airplane",
"auth.item_award": "Award",
"auth.item_bicycle": "Bicycle",
"auth.item_camera": "Camera",
"auth.item_cloud": "Cloud",
"auth.item_compass": "Compass",
"auth.item_cpu": "CPU",
"auth.item_cup": "Cup",
"auth.item_droplet": "Droplet",
"auth.item_fire": "Fire",
"auth.item_flag": "Flag",
"auth.item_flower": "Flower",
"auth.item_gem": "Gem",
"auth.item_gift": "Gift",
"auth.item_globe": "Globe",
"auth.item_laptop": "Laptop",
"auth.item_moon": "Moon",
"auth.item_palette": "Palette",
"auth.item_phone": "Phone",
"auth.item_rocket": "Rocket",
"auth.item_sun": "Sun",
"auth.item_terminal": "Terminal",
"auth.item_tree": "Tree",
"auth.item_trophy": "Trophy",
"auth.item_truck": "Truck",
"auth.item_umbrella": "Umbrella",
"auth.item_watch": "Watch",
"auth.item_wifi": "Wi-Fi"
}
30 changes: 29 additions & 1 deletion src/nine_rtksync/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,33 @@
"type.oauth": "OAuth 2.0",
"type.synced_model": "Modelo sincronizado",
"type.virtual_key": "Clave virtual",
"auth.authentication": "Autenticación"
"auth.authentication": "Autenticación",
"auth.item_airplane": "Avión",
"auth.item_award": "Medalla",
"auth.item_bicycle": "Bicicleta",
"auth.item_camera": "Cámara",
"auth.item_cloud": "Nube",
"auth.item_compass": "Brújula",
"auth.item_cpu": "Procesador",
"auth.item_cup": "Taza",
"auth.item_droplet": "Gota",
"auth.item_fire": "Fuego",
"auth.item_flag": "Bandera",
"auth.item_flower": "Flor",
"auth.item_gem": "Diamante",
"auth.item_gift": "Regalo",
"auth.item_globe": "Globo",
"auth.item_laptop": "Portátil",
"auth.item_moon": "Luna",
"auth.item_palette": "Paleta",
"auth.item_phone": "Teléfono",
"auth.item_rocket": "Cohete",
"auth.item_sun": "Sol",
"auth.item_terminal": "Terminal",
"auth.item_tree": "Árbol",
"auth.item_trophy": "Trofeo",
"auth.item_truck": "Camión",
"auth.item_umbrella": "Paraguas",
"auth.item_watch": "Reloj",
"auth.item_wifi": "Wi-Fi"
}
30 changes: 29 additions & 1 deletion src/nine_rtksync/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,33 @@
"type.oauth": "OAuth 2.0",
"type.synced_model": "Modelo sincronizado",
"type.virtual_key": "Chave virtual",
"auth.authentication": "Autenticação"
"auth.authentication": "Autenticação",
"auth.item_airplane": "Avião",
"auth.item_award": "Medalha",
"auth.item_bicycle": "Bicicleta",
"auth.item_camera": "Câmera",
"auth.item_cloud": "Nuvem",
"auth.item_compass": "Bússola",
"auth.item_cpu": "Processador",
"auth.item_cup": "Xícara",
"auth.item_droplet": "Gota",
"auth.item_fire": "Fogo",
"auth.item_flag": "Bandeira",
"auth.item_flower": "Flor",
"auth.item_gem": "Diamante",
"auth.item_gift": "Presente",
"auth.item_globe": "Globo",
"auth.item_laptop": "Notebook",
"auth.item_moon": "Lua",
"auth.item_palette": "Paleta",
"auth.item_phone": "Celular",
"auth.item_rocket": "Foguete",
"auth.item_sun": "Sol",
"auth.item_terminal": "Terminal",
"auth.item_tree": "Árvore",
"auth.item_trophy": "Troféu",
"auth.item_truck": "Caminhão",
"auth.item_umbrella": "Guarda-chuva",
"auth.item_watch": "Relógio",
"auth.item_wifi": "Wi-Fi"
}
28 changes: 28 additions & 0 deletions src/nine_rtksync/protecao.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,34 @@
("bell", "bi-bell-fill"),
("lightning", "bi-lightning-fill"),
("gear", "bi-gear-fill"),
("sun", "bi-sun-fill"),
("moon", "bi-moon-stars-fill"),
("cloud", "bi-cloud-fill"),
("fire", "bi-fire"),
("droplet", "bi-droplet-fill"),
("tree", "bi-tree-fill"),
("flower", "bi-flower1"),
("gem", "bi-gem"),
("trophy", "bi-trophy-fill"),
("award", "bi-award-fill"),
("gift", "bi-gift-fill"),
("compass", "bi-compass-fill"),
("flag", "bi-flag-fill"),
("globe", "bi-globe"),
("camera", "bi-camera-fill"),
("cup", "bi-cup-hot-fill"),
("palette", "bi-palette-fill"),
("umbrella", "bi-umbrella-fill"),
("rocket", "bi-rocket-takeoff-fill"),
("airplane", "bi-airplane-fill"),
("bicycle", "bi-bicycle"),
("truck", "bi-truck"),
("cpu", "bi-cpu-fill"),
("terminal", "bi-terminal-fill"),
("laptop", "bi-laptop"),
("phone", "bi-phone-fill"),
("watch", "bi-watch"),
("wifi", "bi-wifi"),
)
MAPA_ICONES: Dict[str, str] = dict(ITENS_DESAFIO)

Expand Down
75 changes: 57 additions & 18 deletions src/nine_rtksync/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ def render_login_page(
)
grade_botoes = "".join(botoes)
desafio_html = f"""
<div class="mb-3 p-3 rounded" style="background:var(--bg);border:1px solid var(--line)">
<div id="box-desafio" class="mb-3 p-3 rounded" style="background:var(--bg);border:1px solid var(--line);transition:border-color .2s">
<label class="form-label small d-flex align-items-center gap-2 mb-2 text-warning fw-semibold">
<i class="bi bi-shield-check" aria-hidden="true"></i>
<span>{esc(instrucao)}</span>
Expand All @@ -440,19 +440,58 @@ def render_login_page(
<div class="d-flex gap-2 justify-content-between my-1" role="group" aria-label="{esc(translate("auth.challenge", lang))}">
{grade_botoes}
</div>
<div id="desafio-feedback" class="small mt-2 text-center text-info fw-semibold" style="display:none"></div>
<div id="desafio-erro" class="small mt-2 text-danger fw-semibold" style="display:none">
<i class="bi bi-exclamation-octagon-fill me-1" aria-hidden="true"></i>{esc(translate("auth.select_challenge", lang))}
</div>
</div>
<script>
document.querySelectorAll('.desafio-btn').forEach(btn => {{
btn.addEventListener('click', function() {{
document.querySelectorAll('.desafio-btn').forEach(b => {{
b.classList.remove('btn-primary', 'active');
b.classList.add('btn-outline-secondary');
(function() {{
const btns = document.querySelectorAll('.desafio-btn');
const inputResp = document.getElementById('resposta');
const feedback = document.getElementById('desafio-feedback');
const erroBox = document.getElementById('desafio-erro');
const boxDesafio = document.getElementById('box-desafio');

btns.forEach(btn => {{
btn.addEventListener('click', function() {{
btns.forEach(b => {{
b.classList.remove('btn-primary', 'active', 'border-primary', 'shadow-sm');
b.classList.add('btn-outline-secondary');
b.setAttribute('aria-pressed', 'false');
}});
this.classList.remove('btn-outline-secondary');
this.classList.add('btn-primary', 'active', 'border-primary', 'shadow-sm');
this.setAttribute('aria-pressed', 'true');
const val = this.getAttribute('data-val');
const title = this.getAttribute('title') || val;
if (inputResp) inputResp.value = val;
if (feedback) {{
feedback.innerHTML = '<i class="bi bi-check-circle-fill text-success me-1"></i> ' + title;
feedback.style.display = 'block';
}}
if (erroBox) erroBox.style.display = 'none';
if (boxDesafio) {{
boxDesafio.style.borderColor = 'var(--line)';
boxDesafio.classList.remove('border-danger');
}}
}});
this.classList.remove('btn-outline-secondary');
this.classList.add('btn-primary', 'active');
document.getElementById('resposta').value = this.getAttribute('data-val');
}});
}});

const form = document.querySelector('form[action="/login"]');
if (form) {{
form.addEventListener('submit', function(e) {{
if (inputResp && !inputResp.value) {{
e.preventDefault();
if (erroBox) erroBox.style.display = 'block';
if (boxDesafio) {{
boxDesafio.style.borderColor = 'var(--bs-danger)';
boxDesafio.classList.add('border-danger');
}}
}}
}});
}}
}})();
</script>"""
else:
desafio_html = (
Expand All @@ -463,23 +502,23 @@ def render_login_page(
botoes_sso = []
if oidc_nome and saml_nome and oidc_nome == saml_nome:
rotulo_oidc = f"{oidc_nome} (OIDC)"
rotulo_saml = f"{saml_nome} (SAML)"
rotulo_saml = f"{saml_nome} (SAML 2.0)"
else:
rotulo_oidc = oidc_nome
rotulo_saml = saml_nome
rotulo_oidc = f"{oidc_nome} (OIDC)" if oidc_nome and "oidc" not in oidc_nome.lower() else oidc_nome
rotulo_saml = f"{saml_nome} (SAML 2.0)" if saml_nome and "saml" not in saml_nome.lower() else saml_nome

if rotulo_oidc:
botoes_sso.append(
f'<a class="btn btn-outline-light w-100 d-inline-flex align-items-center '
f'justify-content-center gap-2 mb-2" href="/sso/oidc/iniciar" rel="nofollow">'
f'<i class="bi bi-shield-check" aria-hidden="true"></i>'
f'<i class="bi bi-shield-check text-info" aria-hidden="true"></i>'
f'{esc(translate("sso.sign_in_with", lang, provider=rotulo_oidc))}</a>'
)
if rotulo_saml:
botoes_sso.append(
f'<a class="btn btn-outline-light w-100 d-inline-flex align-items-center '
f'justify-content-center gap-2 mb-2" href="/sso/saml/iniciar" rel="nofollow">'
f'<i class="bi bi-shield-lock" aria-hidden="true"></i>'
f'<i class="bi bi-shield-lock text-warning" aria-hidden="true"></i>'
f'{esc(translate("sso.sign_in_with", lang, provider=rotulo_saml))}</a>'
)
elif sso_indisponivel and not botoes_sso:
Expand Down Expand Up @@ -1479,9 +1518,9 @@ def render_sso_modal(
if hasattr(sso_view, "base_url"):
sso_obj = sso_view
prov = sso_obj.provedor
senha_hab = sso_obj.senha_esta_ligada()
oidc_hab = sso_obj.oidc_esta_ligado()
saml_hab = sso_obj.saml_esta_ligado()
senha_hab = sso_obj.senha_habilitada
oidc_hab = sso_obj.oidc_habilitado
saml_hab = sso_obj.saml_habilitado
base_url = sso_obj.base_url or ""
issuer = sso_obj.issuer or ""
client_id = sso_obj.client_id or ""
Expand Down
Loading