Files
Key-service-Server/Code/templates/login.html
T
Maximilian G. f1cdfba603 feat: Add iOS-specific enhancements and mobile compatibility utilities
- Implemented `remove_key` function in verify.py to allow key removal by user ID.
- Updated run.sh to include additional dependencies for QR code and TOTP support.
- Introduced ios_fixes.js for iOS-specific enhancements including file input handling, form submission fixes, and image handling optimizations.
- Added mobile_compatibility.js for mobile device detection and utility functions to improve compatibility, especially for iOS.
- Created base.html template for consistent layout and styling across the application.
- Developed login.html template with a password toggle feature for better user experience.
2026-03-22 17:28:28 +00:00

129 lines
5.0 KiB
HTML

<!--
Copyright 2025 Maximilian Gründinger
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-6">
<h2 class="text-center">Login</h2>
<form method="POST" action="{{ url_for('login') }}">
<div class="mb-3">
<label for="password" class="form-label">TOTP</label>
<div class="password-input-container">
<input type="password" class="form-control" id="password" name="password" required>
<button type="button" class="password-toggle-btn" id="togglePassword" aria-label="Show password">
<input type="checkbox" checked="checked">
<svg class="eye" xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 576 512"><path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z"></path></svg>
<svg class="eye-slash" xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 640 512"><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c8.4-19.3 10.6-41.4 4.8-63.3c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zM373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5L373 389.9z"></path></svg>
</button>
</div>
</div>
<button type="submit" class="btn btn-primary w-100">Login</button>
</form>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const togglePassword = document.getElementById('togglePassword');
const passwordInput = document.getElementById('password');
const passwordContainer = document.querySelector('.password-input-container');
togglePassword.addEventListener('click', function() {
// Toggle the password field type
const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password';
passwordInput.setAttribute('type', type);
// Toggle the visual state of the container
passwordContainer.classList.toggle('password-visible');
//Toggle visability of eye according to state
// Update aria-label for accessibility
const isVisible = type === 'text';
togglePassword.setAttribute('aria-label', isVisible ? 'Hide password' : 'Show password');
});
});
</script>
<style>
.password-input-container {
display: flex;
gap: 10px;
}
#togglePassword {
border-radius: 5px;
}
#togglePassword {
--color: #a5a5b0;
--size: 20px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
cursor: pointer;
font-size: var(--size);
user-select: none;
fill: var(--color);
width: 15%;
}
#togglePassword .eye-slash {
position: absolute;
animation: keyframes-fill .5s;
display: none;
}
#togglePassword .eye {
position: absolute;
animation: keyframes-fill .5s;
}
/* ------ On check event ------ */
#togglePassword input:checked ~ .eye-slash {
display: block;
}
#togglePassword input:checked ~ .eye {
display: none;
}
/* ------ Hide the default checkbox ------ */
#togglePassword input {
position: absolute;
z-index: 100;
opacity: 0;
cursor: pointer;
height: 100%;
width: 100%;
}
/* ------ Animation ------ */
@keyframes keyframes-fill {
0% {
transform: scale(0);
opacity: 0;
}
50% {
transform: scale(1.2);
}
}
</style>
{% endblock %}