{% extends "base_settings_page.html" %} {% block content %} <form method="post" action="/admin/users" id="edit_user_form"> <!-- User ID --> <div class="form-group"> <label class="form-label mt-4" for="userID">User ID</label> <input class="form-control" id="userID" type="text" readonly="" name="uid" value="{{ u.uid.0 }}"/> </div> <!-- User name --> <div class="form-group"> <label class="form-label mt-4" for="username">Username</label> <input class="form-control" id="username" type="text" autocomplete="nope" name="username" value="{{ u.username }}" required/> <div class="valid-feedback">This username is valid</div> <div class="invalid-feedback">This username is already taken.</div> </div> <!-- First name --> <div class="form-group"> <label class="form-label mt-4" for="first_name">First name</label> <input class="form-control" id="first_name" type="text" name="first_name" value="{{ u.first_name }}"/> </div> <!-- Last name --> <div class="form-group"> <label class="form-label mt-4" for="last_name">Last name</label> <input class="form-control" id="last_name" type="text" name="last_name" value="{{ u.last_name }}"/> </div> <!-- Email --> <div class="form-group"> <label class="form-label mt-4" for="email">Email address</label> <input class="form-control" id="email" type="email" name="email" value="{{ u.email }}"/> </div> <div class="form-group mt-4"> <!-- Generate new password --> <div class="form-check"> <input class="form-check-input" type="checkbox" name="gen_new_password" id="gen_new_password" {% if u.password.is_empty() %} checked="" {% endif %}> <label class="form-check-label" for="gen_new_password"> Generate a new temporary password </label> </div> <!-- Enabled --> <div class="form-check"> <input class="form-check-input" type="checkbox" name="enabled" id="enabled" {% if u.enabled %} checked="" {% endif %}> <label class="form-check-label" for="enabled"> Enabled </label> </div> <!-- 2FA exemption after successful login --> <div class="form-check"> <input class="form-check-input" type="checkbox" name="two_factor_exemption_after_successful_login" id="two_factor_exemption_after_successful_login" {% if u.two_factor_exemption_after_successful_login %} checked="" {% endif %}> <label class="form-check-label" for="two_factor_exemption_after_successful_login"> Exempt user from 2FA authentication for an IP address after a successful login for a limited time </label> </div> <!-- Admin --> <div class="form-check"> <input class="form-check-input" type="checkbox" name="admin" id="admin" {% if u.admin %} checked="" {% endif %}> <label class="form-check-label" for="admin"> Grant admin privileges </label> </div> </div> <!-- Two-Factor authentication --> <input type="hidden" name="two_factor" value=""/> {% if u.has_two_factor() %} <fieldset class="form-group"> <legend class="mt-4">Two factor authentication</legend> <strong>If you uncheck a factor, it will be DELETED</strong> {% for f in u.two_factor %} <div class="form-check"> <label class="form-check-label"> <input type="checkbox" class="form-check-input two-fact-checkbox" value="{{ f.id.0 }}" checked=""/> {{ f.name }} (<img src="{{ f.type_image() }}" alt="Factor icon" style="height:1em;"/> {{ f.type_str() }}) </label> </div> {% endfor %} </fieldset> {% endif %} <!-- Two factor authentication history --> {% if !u.last_successful_2fa.is_empty() %} <fieldset class="form-group"> <legend class="mt-4">Last successful 2FA authentications</legend> <!-- Clear 2FA history --> <div class="form-check"> <input class="form-check-input" type="checkbox" name="clear_2fa_history" id="clear_2fa_history"> <label class="form-check-label" for="clear_2fa_history"> Clear 2FA authentication history </label> </div> <ul> {% for e in u.get_formatted_2fa_successful_logins() %} {% if e.can_bypass_2fa %} <li style="font-weight: bold;">{{ e.ip }} - {{ e.fmt_time() }} - BYPASS 2FA</li> {% else %} <li>{{ e.ip }} - {{ e.fmt_time() }}</li> {% endif %} {% endfor %} </ul> </fieldset> {% endif %} <!-- Authorized authentication sources --> <fieldset class="form-group"> <legend class="mt-4">Authorized authentication sources</legend> <!-- Local login --> <div class="form-check"> <input class="form-check-input" type="checkbox" name="allow_local_login" id="allow_local_login" {% if u.allow_local_login %} checked="" {% endif %}> <label class="form-check-label" for="allow_local_login"> Allow local login </label> </div> <!-- Upstream providers --> <input type="hidden" name="authorized_sources" id="authorized_sources"/> {% for prov in providers %} <div class="form-check"> <input class="form-check-input authorized_provider" type="checkbox" name="prov-{{ prov.id.0 }}" id="prov-{{ prov.id.0 }}" data-id="{{ prov.id.0 }}" {% if u.can_login_from_provider(prov) %} checked="" {% endif %}> <label class="form-check-label" for="prov-{{ prov.id.0 }}"> Allow login from {{ prov.name }} </label> </div> {% endfor %} </fieldset> <!-- Granted clients --> <fieldset class="form-group"> <legend class="mt-4">Granted clients</legend> <div class="form-check"> <label class="form-check-label"> <input type="radio" class="form-check-input" name="grant_type" value="all_clients" {% if u.granted_clients()== GrantedClients::AllClients %} checked="" {% endif %}> Grant all clients </label> </div> <div class="form-check"> <label class="form-check-label"> <input type="radio" class="form-check-input" name="grant_type" value="custom_clients" {% if matches!(self.u.granted_clients(), GrantedClients::SomeClients(_)) %} checked="checked" {% endif %}> Manually specify allowed clients </label> </div> <div id="clients_target"> <input type="hidden" name="granted_clients" value=""/> {% for c in clients %} <div class="form-check"> <input id="client-{{ c.id.0 }}" class="form-check-input authorize_client_checkbox" type="checkbox" data-id="{{ c.id.0 }}" {% if u.can_access_app(c) %} checked="" {% endif %}> <label class="form-check-label" for="client-{{ c.id.0 }}"> {{ c.name }} </label> </div> {% endfor %} </div> <div class="form-check"> <label class="form-check-label"> <input type="radio" class="form-check-input" name="grant_type" value="no_client" {% if u.granted_clients()== GrantedClients::NoClient %} checked="checked" {% endif %}> Do not grant any client </label> </div> </fieldset> <input type="submit" class="btn btn-primary mt-4" value="{{ _p.page_title }}"> </form> <script> // Check Username async function find_username(username) { let data = new URLSearchParams(); data.append("username", username); return (await(await fetch("/admin/api/find_username", { body: data, method: "POST", })).json()).user_id } const usernameEl = document.getElementById("username") async function check_username() { try { usernameEl.classList.remove("is-invalid"); usernameEl.classList.remove("is-valid"); if (usernameEl.value === "") return; const userID = await find_username(usernameEl.value); usernameEl.classList.add((userID === null || userID === "{{ u.uid.0 }}") ? "is-valid" : "is-invalid"); } catch(e) { console.error(e); } } check_username(); usernameEl.addEventListener("change", check_username); usernameEl.addEventListener("keyup", check_username); // Clients granted function refreshDisplayAuthorizedClients() { const clientsSelectorEl = document.getElementById("clients_target"); const radioBtn = document.querySelector("input[name=grant_type][value=custom_clients]"); clientsSelectorEl.style.display = radioBtn.checked ? "block" : "none"; } refreshDisplayAuthorizedClients(); document.querySelectorAll("input[name=grant_type]").forEach(el=> { el.addEventListener("change", refreshDisplayAuthorizedClients) }) // Handle submitted form const form = document.getElementById("edit_user_form"); form.addEventListener("submit", (ev) => { ev.preventDefault(); const authorized_sources = [...document.querySelectorAll(".authorized_provider")] .filter(e => e.checked) .map(e => e.getAttribute("data-id")).join(",") document.querySelector("input[name=authorized_sources]").value = authorized_sources; const authorized_clients = [...document.querySelectorAll(".authorize_client_checkbox")] .filter(e => e.checked) .map(e => e.getAttribute("data-id")).join(",") document.querySelector("input[name=granted_clients]").value = authorized_clients; const factors_to_keep = [...document.querySelectorAll(".two-fact-checkbox")] .filter(e => e.checked) .map(e => e.value) .join(";") document.querySelector("input[name=two_factor]").value = factors_to_keep; form.submit(); }); </script> {% endblock content %}