forked from mirrors/keywind
test: add login theme tests
This commit is contained in:
parent
fb2abd7a36
commit
01df82a237
36 changed files with 2248 additions and 528 deletions
49
html/login/error.html
Normal file
49
html/login/error.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">We are sorry...</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
76
html/login/login-config-totp.html
Normal file
76
html/login/login-config-totp.html
Normal file
|
@ -0,0 +1,76 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Mobile Authenticator Setup</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<ol class="list-decimal pl-4 space-y-2">
|
||||
<li class="space-y-2">
|
||||
<p>Install one of the following applications on your mobile:</p>
|
||||
<ul class="list-disc pl-4">
|
||||
<li>FreeOTP</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
<p>Open the application and scan the barcode:</p><img alt="Figure: Barcode" class="mx-auto" src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABgAAAAYADwa0LPAAAF70lEQVR42u3d0W3DOBQAwfhwPcj9V2e4CV8D96EgBPVWnilAphRlwY8H6vH5fD4/AAH/XL0AgLMEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgIx/r17A/zmO4+f9fl+9jEt8Pp8l13k8HrnfOnOdM1bdl/dwHjssIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIGDk4esbr9fo5juPqZfzKqkHEaUOhO6+zagB11fP55vfwCnZYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQkR0cPWPVsOIZ005o3Hnvq+w8lXSnb34PV7PDAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CAjFsPjt7VtAHLaaeb3n148pvZYQEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIbB0aCdn2Ivrrn4fDjHDgvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjJuPTj6zcOBq4YnV13nm4dCp62nzA4LyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIysoOjz+fz6iWMtnMo9K7XOcN7uJcdFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZDw+jkPMOTMYeca0U0CLp4mylx0WkCFYQIZgARmCBWQIFpAhWECGYAEZggVkjDxxdOdg5M5hxbsOfBaf86o1r7JzPeXhWzssIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIGDk4esaq4bedQ4/ThhXPcAro3+992iB0mR0WkCFYQIZgARmCBWQIFpAhWECGYAEZggVkZD9Vbxhvj2mvh9NE//5bZXZYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQkR0cPXVzwWG84pqn3dddh0tXKZ8ia4cFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZ2U/VTxtE/GbThl13XmfnEKb30A4LCBEsIEOwgAzBAjIEC8gQLCBDsIAMwQIysoOjd/3896o1TxsynDagu3M9O4dLpz3n1eywgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgY+Tg6KpBu50nPU4b2CsOu057hjvXXHzHrmCHBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGY/PzgnDlQsfNmg3bUh1528Vn+FO0X+xkeywgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgI3vi6CrTPlm+8zqr7n3aqZvTTLuvaev5DTssIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIyJ44+s12DnMWBxrvel/YYQEhggVkCBaQIVhAhmABGYIFZAgWkCFYQMbIE0eP4/h5v99XL+MSd/1c+86h0Glr3vlbO0+jvYIdFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZIwcHD3j9Xr9HMdx9TJ+ZdVA7DeflvnNw5PThoGvYIcFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZ2cHRM3YO2hWHDIunZd71RNZvHoj9DTssIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIuPXg6F1N+6z5zjWvUhxALQ98rmKHBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGQZHg+46QLjzRM1pA5/T7n3qO2aHBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGbceHJ06/PZX04YMV5n29yquZ+ff6wp2WECGYAEZggVkCBaQIVhAhmABGYIFZAgWkJEdHH0+n1cvYbRpp1yeUT4J86/3xTl2WECGYAEZggVkCBaQIVhAhmABGYIFZAgWkPH4FCfxgK9khwVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVk/AeoXLE8BnySdAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMy0wOS0yNVQyMDoxMjo1OSswMDowMLyvm1kAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjMtMDktMjVUMjA6MTI6NTkrMDA6MDDN8iPlAAAAAElFTkSuQmCC"> <a class="text-primary-600 hover:text-primary-500 inline-flex" href="manualUrl"> Unable to scan? </a></li>
|
||||
<li>Enter the one-time code provided by the application and click Submit to finish the setup.</li>
|
||||
<li>Provide a Device Name to help you manage your OTP devices.</li>
|
||||
</ol>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction">
|
||||
<input name="totpSecret" type="hidden" value="totpSecret">
|
||||
<div>
|
||||
<label class="sr-only" for="totp"> One-time code * </label> <input autofocus aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="totp" name="totp" placeholder="One-time code *" autocomplete="off" type="text">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="sr-only" for="userLabel"> Device Name * </label> <input aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="userLabel" name="userLabel" placeholder="Device Name *" autocomplete="off" type="text">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Submit </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
52
html/login/login-idp-link-confirm.html
Normal file
52
html/login/login-idp-link-confirm.html
Normal file
|
@ -0,0 +1,52 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Account already exists</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" name="submitAction" type="submit" value="updateProfile"> Review profile </button> <button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" name="submitAction" type="submit" value="linkAccount"> Add to existing account </button>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
59
html/login/login-oauth-grant.html
Normal file
59
html/login/login-oauth-grant.html
Normal file
|
@ -0,0 +1,59 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">
|
||||
<p>Grant Access to null</p></h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<h3>Do you grant these access privileges?</h3>
|
||||
<ul class="list-disc pl-4">
|
||||
</ul>
|
||||
<form class="m-0 space-y-4" method="post" action="oauthAction">
|
||||
<input name="code" type="hidden" value="code">
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" name="accept" type="submit"> Yes </button> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" name="cancel" type="submit"> No </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
59
html/login/login-otp.html
Normal file
59
html/login/login-otp.html
Normal file
|
@ -0,0 +1,59 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Sign In</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction">
|
||||
<div>
|
||||
<label class="sr-only" for="otp"> One-time code * </label> <input autofocus required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="otp" name="otp" placeholder="One-time code *" autocomplete="off" type="text">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" name="submitAction" type="submit"> Sign In </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
52
html/login/login-page-expired.html
Normal file
52
html/login/login-page-expired.html
Normal file
|
@ -0,0 +1,52 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Page has expired</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<a class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" href="loginRestartFlowUrl"> Try again </a> <a class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" href="loginAction"> Continue </a>
|
||||
</div>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
62
html/login/login-password.html
Normal file
62
html/login/login-password.html
Normal file
|
@ -0,0 +1,62 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Sign In</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction" onsubmit="login.disabled = true; return true;">
|
||||
<div>
|
||||
<label class="sr-only" for="password"> Password </label> <input autofocus required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="password" name="password" placeholder="Password" type="password">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<a class="text-primary-600 hover:text-primary-500 text-sm inline-flex" href="loginResetCredentialsUrl"> Forgot Password? </a>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" name="login" type="submit"> Sign In </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
84
html/login/login-recovery-authn-code-config.html
Normal file
84
html/login/login-recovery-authn-code-config.html
Normal file
|
@ -0,0 +1,84 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/recoveryCodes.js" type="module"></script>
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Recovery Authentication Codes</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<div class="space-y-6" x-data="recoveryCodes">
|
||||
<div class="bg-orange-100 text-orange-600 p-4 rounded-lg text-sm" role="alert">
|
||||
<div class="space-y-2">
|
||||
<h4 class="font-medium">These recovery codes wont appear again after leaving this page</h4>
|
||||
<p>Make sure to print, download, or copy them to a password manager and keep them save. Canceling this setup will remove these recovery codes from your account.</p>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="columns-2 font-mono text-center" x-ref="codeList">
|
||||
<li>0000-0000-0000</li>
|
||||
<li>1111-1111-1111</li>
|
||||
</ul>
|
||||
<div class="flex items-stretch space-x-4 mb-4">
|
||||
<button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-2 py-1 text-xs flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" @click="print" type="button"> Print </button> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-2 py-1 text-xs flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" @click="download" type="button"> Download </button> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-2 py-1 text-xs flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" @click="copy" type="button"> Copy </button>
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction">
|
||||
<input name="generatedRecoveryAuthnCodes" type="hidden" value="generatedRecoveryAuthnCodesAsString"> <input name="generatedAt" type="hidden" value=""generatedAt""> <input name="userLabel" type="hidden" value="Recovery codes">
|
||||
<div class="flex items-center">
|
||||
<input class="border-secondary-200 h-4 rounded text-primary-600 w-4 focus:ring-primary-200 focus:ring-opacity-50" id="kcRecoveryCodesConfirmationCheck" name="kcRecoveryCodesConfirmationCheck" type="checkbox" required x-ref="confirmationCheck"> <label class="ml-2 text-secondary-600 text-sm" for="kcRecoveryCodesConfirmationCheck"> I have saved these codes somewhere safe </label>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Complete setup </button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.store('recoveryCodes', {
|
||||
downloadFileDate: 'These codes were generated on',
|
||||
downloadFileDescription: 'Recovery codes are single-use passcodes that allow you to sign in to your account if you do not have access to your authenticator.',
|
||||
downloadFileHeader: 'Keep these recovery codes somewhere safe.',
|
||||
downloadFileName: 'kc-download-recovery-codes',
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
59
html/login/login-recovery-authn-code-input.html
Normal file
59
html/login/login-recovery-authn-code-input.html
Normal file
|
@ -0,0 +1,59 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Login with a recovery authentication code</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction">
|
||||
<div>
|
||||
<label class="sr-only" for="recoveryCodeInput"> Recovery code #"codeNumber" </label> <input autofocus required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="recoveryCodeInput" name="recoveryCodeInput" placeholder="Recovery code #"codeNumber"" autocomplete="off" type="text">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" name="login" type="submit"> Sign In </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
63
html/login/login-reset-password.html
Normal file
63
html/login/login-reset-password.html
Normal file
|
@ -0,0 +1,63 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Forgot Your Password?</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction">
|
||||
<div>
|
||||
<label class="sr-only" for="username"> Email </label> <input autofocus required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="username" name="username" placeholder="Email" autocomplete="email" type="text" value="Attempted Username">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Submit </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
Enter your username or email address and we will send you instructions on how to create a new password.
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="loginUrl"> « Back to Login </a>
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
65
html/login/login-update-password.html
Normal file
65
html/login/login-update-password.html
Normal file
|
@ -0,0 +1,65 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Update password</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction">
|
||||
<input autocomplete="username" name="username" type="hidden" value="Username"> <input autocomplete="current-password" name="password" type="hidden">
|
||||
<div>
|
||||
<label class="sr-only" for="password-new"> New Password </label> <input autofocus required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="password-new" name="password-new" placeholder="New Password" autocomplete="new-password" type="password">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="sr-only" for="password-confirm"> Confirm password </label> <input required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="password-confirm" name="password-confirm" placeholder="Confirm password" autocomplete="new-password" type="password">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Submit </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
74
html/login/login-update-profile.html
Normal file
74
html/login/login-update-profile.html
Normal file
|
@ -0,0 +1,74 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Update Account Information</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction">
|
||||
<div>
|
||||
<label class="sr-only" for="username"> Username </label> <input autofocus required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="username" name="username" placeholder="Username" autocomplete="username" type="text" value="">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="sr-only" for="email"> Email </label> <input required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="email" name="email" placeholder="Email" autocomplete="email" type="email" value="">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="sr-only" for="firstName"> First name </label> <input required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="firstName" name="firstName" placeholder="First name" autocomplete="given-name" type="text" value="">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="sr-only" for="lastName"> Last name </label> <input required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="lastName" name="lastName" placeholder="Last name" autocomplete="family-name" type="text" value="">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Submit </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
90
html/login/login-username.html
Normal file
90
html/login/login-username.html
Normal file
|
@ -0,0 +1,90 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Sign in to your account</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction" onsubmit="login.disabled = true; return true;">
|
||||
<div>
|
||||
<label class="sr-only" for="username"> Email </label> <input autofocus required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="username" name="username" placeholder="Email" autocomplete="email" type="text" value="">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<input checked class="border-secondary-200 h-4 rounded text-primary-600 w-4 focus:ring-primary-200 focus:ring-opacity-50" id="rememberMe" name="rememberMe" type="checkbox"> <label class="ml-2 text-secondary-600 text-sm" for="rememberMe"> Remember me </label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" name="login" type="submit"> Sign In </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
<div class="pt-4 separate text-secondary-600 text-sm">
|
||||
Or sign in with
|
||||
</div>
|
||||
<div class="gap-4 grid grid-cols-3">
|
||||
<a class="hover:bg-provider-facebook/10 border border-secondary-200 flex justify-center py-2 rounded-lg hover:border-transparent" data-provider="facebook" href="loginUrl" type="button">
|
||||
<div class="h-6 w-6">
|
||||
<svg viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Facebook</title><path d="M24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 17.9895 4.38822 22.954 10.125 23.8542V15.4688H7.07813V12H10.125V9.35626C10.125 6.34875 11.9165 4.68751 14.6576 4.68751C15.9705 4.68751 17.3438 4.92188 17.3438 4.92188V7.875H15.8306C14.3399 7.875 13.875 8.80002 13.875 9.74901V12H17.2031L16.6711 15.4688H13.875V23.8542C19.6118 22.954 24 17.9895 24 12Z" fill="#1877F2" /> <path d="M16.6711 15.4688L17.2031 12H13.875V9.74901C13.875 8.80002 14.3399 7.875 15.8306 7.875H17.3438V4.92188C17.3438 4.92188 15.9705 4.68751 14.6576 4.68751C11.9165 4.68751 10.125 6.34875 10.125 9.35626V12H7.07813V15.4688H10.125V23.8542C10.7453 23.9514 11.3722 24.0002 12 24C12.6379 24 13.2641 23.9501 13.875 23.8542V15.4688H16.6711Z" fill="white" />
|
||||
</svg>
|
||||
</div></a> <a class="hover:bg-provider-github/10 border border-secondary-200 flex justify-center py-2 rounded-lg hover:border-transparent" data-provider="github" href="loginUrl" type="button">
|
||||
<div class="h-6 w-6">
|
||||
<svg viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>GitHub</title><path d="M11.8452 0C5.13387 0 0 5.09516 0 11.8065C0 17.1726 3.37742 21.7645 8.20161 23.3806C8.82097 23.4919 9.03871 23.1097 9.03871 22.7952C9.03871 22.4952 9.02419 20.8403 9.02419 19.8242C9.02419 19.8242 5.6371 20.55 4.92581 18.3823C4.92581 18.3823 4.37419 16.9742 3.58065 16.6113C3.58065 16.6113 2.47258 15.8516 3.65806 15.8661C3.65806 15.8661 4.8629 15.9629 5.52581 17.1145C6.58548 18.9823 8.36129 18.4452 9.05323 18.1258C9.16452 17.3516 9.47903 16.8145 9.82742 16.4952C7.12258 16.1952 4.39355 15.8032 4.39355 11.1484C4.39355 9.81774 4.76129 9.15 5.53548 8.29839C5.40968 7.98387 4.99839 6.6871 5.66129 5.0129C6.67258 4.69839 9 6.31936 9 6.31936C9.96774 6.04839 11.0081 5.90806 12.0387 5.90806C13.0694 5.90806 14.1097 6.04839 15.0774 6.31936C15.0774 6.31936 17.4048 4.69355 18.4161 5.0129C19.079 6.69194 18.6677 7.98387 18.5419 8.29839C19.3161 9.15484 19.7903 9.82258 19.7903 11.1484C19.7903 15.8177 16.9403 16.1903 14.2355 16.4952C14.6806 16.8774 15.0581 17.6032 15.0581 18.7403C15.0581 20.371 15.0435 22.3887 15.0435 22.7855C15.0435 23.1 15.2661 23.4823 15.8806 23.371C20.7194 21.7645 24 17.1726 24 11.8065C24 5.09516 18.5565 0 11.8452 0Z" fill="#181717" />
|
||||
</svg>
|
||||
</div></a> <a class="hover:bg-provider-google/10 border border-secondary-200 flex justify-center py-2 rounded-lg hover:border-transparent" data-provider="google" href="loginUrl" type="button">
|
||||
<div class="h-6 w-6">
|
||||
<svg viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Google</title><path d="M23.76 12.2727C23.76 11.4218 23.6836 10.6036 23.5418 9.81818H12.24V14.46H18.6982C18.42 15.96 17.5745 17.2309 16.3036 18.0818L18.2427 19.5873L20.1818 21.0927C22.4509 19.0036 23.76 15.9273 23.76 12.2727Z" fill="#4285F4" /> <path d="M12.24 24C15.48 24 18.1964 22.9255 20.1818 21.0927L16.3036 18.0818C15.2291 18.8018 13.8545 19.2273 12.24 19.2273C9.11455 19.2273 6.46909 17.1164 5.52545 14.28L3.52091 15.8345L1.51636 17.3891C3.49091 21.3109 7.54909 24 12.24 24Z" fill="#34A853" /> <path d="M5.52545 14.28C5.28545 13.56 5.14909 12.7909 5.14909 12C5.14909 11.2091 5.28545 10.44 5.52545 9.72L3.52091 8.16546L1.51636 6.61091C0.703637 8.23091 0.240001 10.0636 0.240001 12C0.240001 13.9364 0.703637 15.7691 1.51636 17.3891L5.52545 14.28Z" fill="#FBBC05" /> <path d="M12.24 4.77273C14.0018 4.77273 15.5836 5.37818 16.8273 6.56727L20.2691 3.12545C18.1909 1.18909 15.4745 0 12.24 0C7.54909 0 3.49091 2.68909 1.51636 6.61091L5.52545 9.72C6.46909 6.88364 9.11455 4.77273 12.24 4.77273Z" fill="#EA4335" />
|
||||
</svg>
|
||||
</div></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="text-center">
|
||||
New user? <a class="text-primary-600 hover:text-primary-500 inline-flex" href="registrationUrl"> Register </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
96
html/login/login.html
Normal file
96
html/login/login.html
Normal file
|
@ -0,0 +1,96 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Sign in to your account</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction" onsubmit="login.disabled = true; return true;">
|
||||
<input name="credentialId" type="hidden" value="">
|
||||
<div>
|
||||
<label class="sr-only" for="username"> Email </label> <input autofocus required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="username" name="username" placeholder="Email" autocomplete="email" type="text" value="">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="sr-only" for="password"> Password </label> <input required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="password" name="password" placeholder="Password" type="password">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<input checked class="border-secondary-200 h-4 rounded text-primary-600 w-4 focus:ring-primary-200 focus:ring-opacity-50" id="rememberMe" name="rememberMe" type="checkbox"> <label class="ml-2 text-secondary-600 text-sm" for="rememberMe"> Remember me </label>
|
||||
</div><a class="text-primary-600 hover:text-primary-500 text-sm inline-flex" href="loginResetCredentialsUrl"> Forgot Password? </a>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" name="login" type="submit"> Sign In </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
<div class="pt-4 separate text-secondary-600 text-sm">
|
||||
Or sign in with
|
||||
</div>
|
||||
<div class="gap-4 grid grid-cols-3">
|
||||
<a class="hover:bg-provider-facebook/10 border border-secondary-200 flex justify-center py-2 rounded-lg hover:border-transparent" data-provider="facebook" href="loginUrl" type="button">
|
||||
<div class="h-6 w-6">
|
||||
<svg viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Facebook</title><path d="M24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 17.9895 4.38822 22.954 10.125 23.8542V15.4688H7.07813V12H10.125V9.35626C10.125 6.34875 11.9165 4.68751 14.6576 4.68751C15.9705 4.68751 17.3438 4.92188 17.3438 4.92188V7.875H15.8306C14.3399 7.875 13.875 8.80002 13.875 9.74901V12H17.2031L16.6711 15.4688H13.875V23.8542C19.6118 22.954 24 17.9895 24 12Z" fill="#1877F2" /> <path d="M16.6711 15.4688L17.2031 12H13.875V9.74901C13.875 8.80002 14.3399 7.875 15.8306 7.875H17.3438V4.92188C17.3438 4.92188 15.9705 4.68751 14.6576 4.68751C11.9165 4.68751 10.125 6.34875 10.125 9.35626V12H7.07813V15.4688H10.125V23.8542C10.7453 23.9514 11.3722 24.0002 12 24C12.6379 24 13.2641 23.9501 13.875 23.8542V15.4688H16.6711Z" fill="white" />
|
||||
</svg>
|
||||
</div></a> <a class="hover:bg-provider-github/10 border border-secondary-200 flex justify-center py-2 rounded-lg hover:border-transparent" data-provider="github" href="loginUrl" type="button">
|
||||
<div class="h-6 w-6">
|
||||
<svg viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>GitHub</title><path d="M11.8452 0C5.13387 0 0 5.09516 0 11.8065C0 17.1726 3.37742 21.7645 8.20161 23.3806C8.82097 23.4919 9.03871 23.1097 9.03871 22.7952C9.03871 22.4952 9.02419 20.8403 9.02419 19.8242C9.02419 19.8242 5.6371 20.55 4.92581 18.3823C4.92581 18.3823 4.37419 16.9742 3.58065 16.6113C3.58065 16.6113 2.47258 15.8516 3.65806 15.8661C3.65806 15.8661 4.8629 15.9629 5.52581 17.1145C6.58548 18.9823 8.36129 18.4452 9.05323 18.1258C9.16452 17.3516 9.47903 16.8145 9.82742 16.4952C7.12258 16.1952 4.39355 15.8032 4.39355 11.1484C4.39355 9.81774 4.76129 9.15 5.53548 8.29839C5.40968 7.98387 4.99839 6.6871 5.66129 5.0129C6.67258 4.69839 9 6.31936 9 6.31936C9.96774 6.04839 11.0081 5.90806 12.0387 5.90806C13.0694 5.90806 14.1097 6.04839 15.0774 6.31936C15.0774 6.31936 17.4048 4.69355 18.4161 5.0129C19.079 6.69194 18.6677 7.98387 18.5419 8.29839C19.3161 9.15484 19.7903 9.82258 19.7903 11.1484C19.7903 15.8177 16.9403 16.1903 14.2355 16.4952C14.6806 16.8774 15.0581 17.6032 15.0581 18.7403C15.0581 20.371 15.0435 22.3887 15.0435 22.7855C15.0435 23.1 15.2661 23.4823 15.8806 23.371C20.7194 21.7645 24 17.1726 24 11.8065C24 5.09516 18.5565 0 11.8452 0Z" fill="#181717" />
|
||||
</svg>
|
||||
</div></a> <a class="hover:bg-provider-google/10 border border-secondary-200 flex justify-center py-2 rounded-lg hover:border-transparent" data-provider="google" href="loginUrl" type="button">
|
||||
<div class="h-6 w-6">
|
||||
<svg viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Google</title><path d="M23.76 12.2727C23.76 11.4218 23.6836 10.6036 23.5418 9.81818H12.24V14.46H18.6982C18.42 15.96 17.5745 17.2309 16.3036 18.0818L18.2427 19.5873L20.1818 21.0927C22.4509 19.0036 23.76 15.9273 23.76 12.2727Z" fill="#4285F4" /> <path d="M12.24 24C15.48 24 18.1964 22.9255 20.1818 21.0927L16.3036 18.0818C15.2291 18.8018 13.8545 19.2273 12.24 19.2273C9.11455 19.2273 6.46909 17.1164 5.52545 14.28L3.52091 15.8345L1.51636 17.3891C3.49091 21.3109 7.54909 24 12.24 24Z" fill="#34A853" /> <path d="M5.52545 14.28C5.28545 13.56 5.14909 12.7909 5.14909 12C5.14909 11.2091 5.28545 10.44 5.52545 9.72L3.52091 8.16546L1.51636 6.61091C0.703637 8.23091 0.240001 10.0636 0.240001 12C0.240001 13.9364 0.703637 15.7691 1.51636 17.3891L5.52545 14.28Z" fill="#FBBC05" /> <path d="M12.24 4.77273C14.0018 4.77273 15.5836 5.37818 16.8273 6.56727L20.2691 3.12545C18.1909 1.18909 15.4745 0 12.24 0C7.54909 0 3.49091 2.68909 1.51636 6.61091L5.52545 9.72C6.46909 6.88364 9.11455 4.77273 12.24 4.77273Z" fill="#EA4335" />
|
||||
</svg>
|
||||
</div></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="text-center">
|
||||
New user? <a class="text-primary-600 hover:text-primary-500 inline-flex" href="registrationUrl"> Register </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
53
html/login/logout-confirm.html
Normal file
53
html/login/logout-confirm.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Logging out</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<p>Do you want to log out?</p>
|
||||
<form class="m-0 space-y-4" method="post" action="logoutConfirmAction">
|
||||
<input name="session_code" type="hidden" value="code"> <button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" name="confirmLogout" type="submit" value="Logout"> Logout </button>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
70
html/login/register.html
Normal file
70
html/login/register.html
Normal file
|
@ -0,0 +1,70 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Register</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<form class="m-0 space-y-4" method="post" action="registrationAction">
|
||||
<div>
|
||||
<label class="sr-only" for="firstName"> First name </label> <input autofocus required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="firstName" name="firstName" placeholder="First name" autocomplete="given-name" type="text" value="">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="sr-only" for="lastName"> Last name </label> <input required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="lastName" name="lastName" placeholder="Last name" autocomplete="family-name" type="text" value="">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="sr-only" for="email"> Email </label> <input required aria-invalid="false" class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" id="email" name="email" placeholder="Email" autocomplete="email" type="email" value="">
|
||||
<div class="mt-2 text-red-600 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Register </button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="loginUrl"> « Back to Login </a>
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
60
html/login/select-authenticator.html
Normal file
60
html/login/select-authenticator.html
Normal file
|
@ -0,0 +1,60 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Select login method</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<div x-data>
|
||||
<form class="m-0 space-y-4" method="post" action="loginAction" x-ref="selectCredentialForm">
|
||||
<input name="authenticationExecution" type="hidden" x-ref="authExecInput">
|
||||
<div>
|
||||
<button class="text-primary-600 hover:text-primary-500 inline-flex" @click="$refs.authExecInput.value = 'authExecId'; $refs.selectCredentialForm.submit()" type="button"> Security Key </button>
|
||||
<div class="text-sm">
|
||||
Use your security key to sign in.
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
70
html/login/webauthn-authenticate.html
Normal file
70
html/login/webauthn-authenticate.html
Normal file
|
@ -0,0 +1,70 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/webAuthnAuthenticate.js" type="module"></script>
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Security Key login</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<div x-data="webAuthnAuthenticate">
|
||||
<form action="loginAction" method="post" x-ref="webAuthnForm">
|
||||
<input name="authenticatorData" type="hidden" x-ref="authenticatorDataInput"> <input name="clientDataJSON" type="hidden" x-ref="clientDataJSONInput"> <input name="credentialId" type="hidden" x-ref="credentialIdInput"> <input name="error" type="hidden" x-ref="errorInput"> <input name="signature" type="hidden" x-ref="signatureInput"> <input name="userHandle" type="hidden" x-ref="userHandleInput">
|
||||
</form>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" @click="webAuthnAuthenticate" type="button"> Sign in with Security Key </button>
|
||||
</div>
|
||||
</div>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.store('webAuthnAuthenticate', {
|
||||
challenge: 'challenge',
|
||||
createTimeout: '60000',
|
||||
isUserIdentified: 'true',
|
||||
rpId: 'https://webauthn.me',
|
||||
unsupportedBrowserText: 'WebAuthn is not supported by this browser. Try another one or contact your administrator.',
|
||||
userVerification: 'preferred',
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
57
html/login/webauthn-error.html
Normal file
57
html/login/webauthn-error.html
Normal file
|
@ -0,0 +1,57 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sign in to </title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../../theme/keywind/login/resources/dist/index.css" rel="stylesheet">
|
||||
<script defer src="../../theme/keywind/login/resources/dist/index.js" type="module"></script>
|
||||
</head>
|
||||
<body class="bg-secondary-100 flex flex-col items-center justify-center min-h-screen sm:py-16">
|
||||
<div class="max-w-md space-y-6 w-full">
|
||||
<div class="bg-white p-8 rounded-lg space-y-6">
|
||||
<div class="space-y-4">
|
||||
<div class="font-bold text-center text-2xl">
|
||||
Keywind
|
||||
</div>
|
||||
<h1 class="text-center text-xl">Security Key Error</h1>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-red-100 text-red-600 p-4 rounded-lg text-sm" role="alert">
|
||||
Example of an error message
|
||||
</div>
|
||||
<div x-data>
|
||||
<form action="loginAction" method="post" x-ref="errorCredentialForm">
|
||||
<input name="authenticationExecution" type="hidden" x-ref="executionValueInput"> <input name="isSetRetry" type="hidden" x-ref="isSetRetryInput">
|
||||
</form>
|
||||
<div class="flex flex-col pt-4 space-y-2">
|
||||
<button class="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" @click="$refs.executionValueInput.value = 'execution'; $refs.isSetRetryInput.value = 'retry'; $refs.errorCredentialForm.submit()" tabindex="4" name="try-again" type="button"> Try again </button>
|
||||
</div>
|
||||
</div>
|
||||
<form action="loginAction" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on"> <button class="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900 px-4 py-2 text-sm flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" type="submit"> Try Another Way </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-around">
|
||||
<div class="relative" x-data="{ open: false }">
|
||||
<button class="text-secondary-600 hover:text-secondary-900 inline-flex" @click="open = true" type="button">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-1 text-sm">English</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div></button>
|
||||
<div @click.away="open = false" class="absolute bg-white bottom-0 -left-4 max-h-80 mb-6 overflow-y-scroll rounded-lg shadow-lg" x-cloak x-show="open">
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Deutsch </a>
|
||||
</div>
|
||||
<div class="px-4 py-2">
|
||||
<a class="text-secondary-600 hover:text-secondary-900 text-sm inline-flex" href="url"> Français </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
26
package.json
26
package.json
|
@ -5,23 +5,23 @@
|
|||
"build": "tsc && vite build",
|
||||
"build:jar": "vite-node scripts/build",
|
||||
"dev": "vite build --watch",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"test": "mvn test"
|
||||
},
|
||||
"dependencies": {
|
||||
"alpinejs": "^3.12.0",
|
||||
"alpinejs": "^3.13.0",
|
||||
"rfc4648": "^1.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@types/alpinejs": "^3.7.1",
|
||||
"@types/archiver": "^5.3.1",
|
||||
"@types/node": "^18.15.0",
|
||||
"archiver": "^5.3.1",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"postcss": "^8.4.21",
|
||||
"tailwindcss": "^3.2.7",
|
||||
"typescript": "^4.9.5",
|
||||
"vite": "^4.1.4",
|
||||
"vite-node": "^0.29.2"
|
||||
"@tailwindcss/forms": "^0.5.6",
|
||||
"@types/alpinejs": "^3.13.2",
|
||||
"@types/archiver": "^5.3.3",
|
||||
"@types/node": "^20.6.5",
|
||||
"archiver": "^6.0.1",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"postcss": "^8.4.30",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^4.4.9",
|
||||
"vite-node": "^0.34.5"
|
||||
}
|
||||
}
|
||||
|
|
1007
pnpm-lock.yaml
1007
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
71
pom.xml
Normal file
71
pom.xml
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.keywind.theme</groupId>
|
||||
<artifactId>keywind</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<name>keywind</name>
|
||||
<url>https://keywind.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>20</maven.compiler.source>
|
||||
<maven.compiler.target>20</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>2.3.32</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.16.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-server-spi-private</artifactId>
|
||||
<version>22.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-services</artifactId>
|
||||
<version>22.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-themes</artifactId>
|
||||
<version>22.0.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>auto-clean</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>clean</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
13
src/test/java/org/keywind/theme/AuthenticationUtil.java
Normal file
13
src/test/java/org/keywind/theme/AuthenticationUtil.java
Normal file
|
@ -0,0 +1,13 @@
|
|||
package org.keywind.theme;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import freemarker.template.TemplateMethodModelEx;
|
||||
import freemarker.template.TemplateModelException;
|
||||
|
||||
public class AuthenticationUtil implements TemplateMethodModelEx {
|
||||
@Override
|
||||
public Object exec(List arguments) throws TemplateModelException {
|
||||
return true;
|
||||
}
|
||||
}
|
251
src/test/java/org/keywind/theme/LoginDataModel.java
Normal file
251
src/test/java/org/keywind/theme/LoginDataModel.java
Normal file
|
@ -0,0 +1,251 @@
|
|||
package org.keywind.theme;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class LoginDataModel {
|
||||
public static Map<String, Object> createDataModel() {
|
||||
Map<String, Object> dataModel = new HashMap<>();
|
||||
dataModel.put("auth", createAuthModel());
|
||||
dataModel.put("client", createClientModel());
|
||||
dataModel.put("locale", createLocaleModel());
|
||||
dataModel.put("login", createLoginModel());
|
||||
dataModel.put("logoutConfirm", createLogoutConfirmModel());
|
||||
dataModel.put("message", createMessageModel());
|
||||
dataModel.put("oauth", createOAuthModel());
|
||||
dataModel.put("otpLogin", createOtpLoginModel());
|
||||
dataModel.put("properties", createPropertiesModel());
|
||||
dataModel.put("realm", createRealmModel());
|
||||
dataModel.put("recoveryAuthnCodesConfigBean", createRecoveryAuthnCodesConfigBeanModel());
|
||||
dataModel.put("recoveryAuthnCodesInputBean", createRecoveryAuthnCodesInputBeanModel());
|
||||
dataModel.put("social", createSocialModel());
|
||||
dataModel.put("totp", createTotpModel());
|
||||
dataModel.put("url", createUrlModel());
|
||||
dataModel.put("user", createUserModel());
|
||||
dataModel.put("username", "Username");
|
||||
dataModel.putAll(createWebAuthnModel());
|
||||
|
||||
return dataModel;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createAuthModel() {
|
||||
Map<String, Object> securityKey = new HashMap<>();
|
||||
securityKey.put("authExecId", "authExecId");
|
||||
securityKey.put("displayName", "Security Key");
|
||||
securityKey.put("helpText", "Use your security key to sign in.");
|
||||
|
||||
List<Map<String, Object>> authenticationSelections = new ArrayList<>();
|
||||
authenticationSelections.add(securityKey);
|
||||
|
||||
Map<String, Object> auth = new HashMap<>();
|
||||
auth.put("attemptedUsername", "Attempted Username");
|
||||
auth.put("authenticationSelections", authenticationSelections);
|
||||
auth.put("showResetCredentials", new AuthenticationUtil());
|
||||
auth.put("showTryAnotherWayLink", new AuthenticationUtil());
|
||||
auth.put("showUsername", new AuthenticationUtil());
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createClientModel() {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
|
||||
Map<String, Object> client = new HashMap<>();
|
||||
client.put("attributes", attributes);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createLocaleModel() {
|
||||
Map<String, Object> de = new HashMap<>();
|
||||
de.put("label", "Deutsch");
|
||||
de.put("url", "url");
|
||||
|
||||
Map<String, Object> en = new HashMap<>();
|
||||
en.put("label", "English");
|
||||
en.put("url", "url");
|
||||
|
||||
Map<String, Object> fr = new HashMap<>();
|
||||
fr.put("label", "Français");
|
||||
fr.put("url", "url");
|
||||
|
||||
List<Map<String, Object>> supported = new ArrayList<>();
|
||||
supported.add(de);
|
||||
supported.add(en);
|
||||
supported.add(fr);
|
||||
|
||||
Map<String, Object> locale = new HashMap<>();
|
||||
locale.put("current", "English");
|
||||
locale.put("supported", supported);
|
||||
|
||||
return locale;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createLoginModel() {
|
||||
Map<String, Object> login = new HashMap<>();
|
||||
login.put("rememberMe", true);
|
||||
|
||||
return login;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createLogoutConfirmModel() {
|
||||
Map<String, Object> logoutConfirm = new HashMap<>();
|
||||
logoutConfirm.put("code", "code");
|
||||
logoutConfirm.put("skipLink", false);
|
||||
|
||||
return logoutConfirm;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createMessageModel() {
|
||||
Map<String, Object> message = new HashMap<>();
|
||||
message.put("summary", "Example of an error message");
|
||||
message.put("type", "error");
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createOAuthModel() {
|
||||
List<Map<String, Object>> clientScopesRequested = new ArrayList<>();
|
||||
|
||||
Map<String, Object> oauth = new HashMap<>();
|
||||
oauth.put("clientScopesRequested", clientScopesRequested);
|
||||
oauth.put("code", "code");
|
||||
|
||||
return oauth;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createOtpLoginModel() {
|
||||
List<Map<String, Object>> userOtpCredentials = new ArrayList<>();
|
||||
|
||||
Map<String, Object> otpLogin = new HashMap<>();
|
||||
otpLogin.put("selectedCredentialId", 1);
|
||||
otpLogin.put("userOtpCredentials", userOtpCredentials);
|
||||
|
||||
return otpLogin;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createPropertiesModel() {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("scripts", "dist/index.js");
|
||||
properties.put("styles", "dist/index.css");
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createRealmModel() {
|
||||
Map<String, Object> realm = new HashMap<>();
|
||||
realm.put("displayNameHtml", "Keywind");
|
||||
realm.put("internationalizationEnabled", true);
|
||||
realm.put("loginWithEmailAllowed", true);
|
||||
realm.put("password", true);
|
||||
realm.put("registrationAllowed", true);
|
||||
realm.put("registrationEmailAsUsername", true);
|
||||
realm.put("rememberMe", true);
|
||||
realm.put("resetPasswordAllowed", true);
|
||||
|
||||
return realm;
|
||||
}
|
||||
|
||||
public static Map<String, Object> createRecoveryAuthnCodesConfigBeanModel() {
|
||||
List<String> generatedRecoveryAuthnCodesList = new ArrayList<>();
|
||||
generatedRecoveryAuthnCodesList.add("000000000000");
|
||||
generatedRecoveryAuthnCodesList.add("111111111111");
|
||||
|
||||
Map<String, Object> recoveryAuthnCodesConfigBean = new HashMap<>();
|
||||
recoveryAuthnCodesConfigBean.put("generatedAt", "generatedAt");
|
||||
recoveryAuthnCodesConfigBean.put("generatedRecoveryAuthnCodesAsString", "generatedRecoveryAuthnCodesAsString");
|
||||
recoveryAuthnCodesConfigBean.put("generatedRecoveryAuthnCodesList", generatedRecoveryAuthnCodesList);
|
||||
|
||||
return recoveryAuthnCodesConfigBean;
|
||||
}
|
||||
|
||||
public static Map<String, Object> createRecoveryAuthnCodesInputBeanModel() {
|
||||
Map<String, Object> recoveryAuthnCodesInputBean = new HashMap<>();
|
||||
recoveryAuthnCodesInputBean.put("codeNumber", "codeNumber");
|
||||
|
||||
return recoveryAuthnCodesInputBean;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createSocialModel() {
|
||||
Map<String, Object> facebook = new HashMap<>();
|
||||
facebook.put("alias", "facebook");
|
||||
facebook.put("displayName", "Facebook");
|
||||
facebook.put("loginUrl", "loginUrl");
|
||||
|
||||
Map<String, Object> github = new HashMap<>();
|
||||
github.put("alias", "github");
|
||||
github.put("displayName", "GitHub");
|
||||
github.put("loginUrl", "loginUrl");
|
||||
|
||||
Map<String, Object> google = new HashMap<>();
|
||||
google.put("alias", "google");
|
||||
google.put("displayName", "Google");
|
||||
google.put("loginUrl", "loginUrl");
|
||||
|
||||
List<Map<String, Object>> providers = new ArrayList<>();
|
||||
providers.add(facebook);
|
||||
providers.add(github);
|
||||
providers.add(google);
|
||||
|
||||
Map<String, Object> social = new HashMap<>();
|
||||
social.put("providers", providers);
|
||||
|
||||
return social;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createTotpModel() {
|
||||
Map<String, Object> otpCredential = new HashMap<>();
|
||||
|
||||
List<Map<String, Object>> otpCredentials = new ArrayList<>();
|
||||
otpCredentials.add(otpCredential);
|
||||
|
||||
List<String> supportedApplications = new ArrayList<>();
|
||||
supportedApplications.add("totpAppFreeOTPName");
|
||||
|
||||
Map<String, Object> totp = new HashMap<>();
|
||||
totp.put("manualUrl", "manualUrl");
|
||||
totp.put("otpCredentials", otpCredentials);
|
||||
totp.put("supportedApplications", supportedApplications);
|
||||
totp.put("totpSecret", "totpSecret");
|
||||
totp.put("totpSecretQrCode",
|
||||
"iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABgAAAAYADwa0LPAAAF70lEQVR42u3d0W3DOBQAwfhwPcj9V2e4CV8D96EgBPVWnilAphRlwY8H6vH5fD4/AAH/XL0AgLMEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgIx/r17A/zmO4+f9fl+9jEt8Pp8l13k8HrnfOnOdM1bdl/dwHjssIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIGDk4esbr9fo5juPqZfzKqkHEaUOhO6+zagB11fP55vfwCnZYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQkR0cPWPVsOIZ005o3Hnvq+w8lXSnb34PV7PDAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CAjFsPjt7VtAHLaaeb3n148pvZYQEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIbB0aCdn2Ivrrn4fDjHDgvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjJuPTj6zcOBq4YnV13nm4dCp62nzA4LyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIysoOjz+fz6iWMtnMo9K7XOcN7uJcdFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZDw+jkPMOTMYeca0U0CLp4mylx0WkCFYQIZgARmCBWQIFpAhWECGYAEZggVkjDxxdOdg5M5hxbsOfBaf86o1r7JzPeXhWzssIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIGDk4esaq4bedQ4/ThhXPcAro3+992iB0mR0WkCFYQIZgARmCBWQIFpAhWECGYAEZggVkZD9Vbxhvj2mvh9NE//5bZXZYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQkR0cPXVzwWG84pqn3dddh0tXKZ8ia4cFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZ2U/VTxtE/GbThl13XmfnEKb30A4LCBEsIEOwgAzBAjIEC8gQLCBDsIAMwQIysoOjd/3896o1TxsynDagu3M9O4dLpz3n1eywgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgY+Tg6KpBu50nPU4b2CsOu057hjvXXHzHrmCHBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGY/PzgnDlQsfNmg3bUh1528Vn+FO0X+xkeywgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgI3vi6CrTPlm+8zqr7n3aqZvTTLuvaev5DTssIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIyJ44+s12DnMWBxrvel/YYQEhggVkCBaQIVhAhmABGYIFZAgWkCFYQMbIE0eP4/h5v99XL+MSd/1c+86h0Glr3vlbO0+jvYIdFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZIwcHD3j9Xr9HMdx9TJ+ZdVA7DeflvnNw5PThoGvYIcFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZ2cHRM3YO2hWHDIunZd71RNZvHoj9DTssIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIuPXg6F1N+6z5zjWvUhxALQ98rmKHBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGQZHg+46QLjzRM1pA5/T7n3qO2aHBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGbceHJ06/PZX04YMV5n29yquZ+ff6wp2WECGYAEZggVkCBaQIVhAhmABGYIFZAgWkJEdHH0+n1cvYbRpp1yeUT4J86/3xTl2WECGYAEZggVkCBaQIVhAhmABGYIFZAgWkPH4FCfxgK9khwVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVk/AeoXLE8BnySdAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMy0wOS0yNVQyMDoxMjo1OSswMDowMLyvm1kAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjMtMDktMjVUMjA6MTI6NTkrMDA6MDDN8iPlAAAAAElFTkSuQmCC");
|
||||
|
||||
return totp;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createUrlModel() {
|
||||
Map<String, Object> url = new HashMap<>();
|
||||
url.put("loginAction", "loginAction");
|
||||
url.put("loginResetCredentialsUrl", "loginResetCredentialsUrl");
|
||||
url.put("loginRestartFlowUrl", "loginRestartFlowUrl");
|
||||
url.put("loginUrl", "loginUrl");
|
||||
url.put("logoutConfirmAction", "logoutConfirmAction");
|
||||
url.put("oauthAction", "oauthAction");
|
||||
url.put("registrationAction", "registrationAction");
|
||||
url.put("registrationUrl", "registrationUrl");
|
||||
url.put("resourcesPath", "../../theme/keywind/login/resources");
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createUserModel() {
|
||||
Map<String, Object> user = new HashMap<>();
|
||||
user.put("editUsernameAllowed", true);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
private static Map<String, Object> createWebAuthnModel() {
|
||||
Map<String, Object> webAuthn = new HashMap<>();
|
||||
webAuthn.put("challenge", "challenge");
|
||||
webAuthn.put("execution", "execution");
|
||||
webAuthn.put("createTimeout", "60000");
|
||||
webAuthn.put("isUserIdentified", "true");
|
||||
webAuthn.put("rpId", "https://webauthn.me");
|
||||
webAuthn.put("userVerification", "preferred");
|
||||
|
||||
return webAuthn;
|
||||
}
|
||||
}
|
113
src/test/java/org/keywind/theme/LoginThemeTest.java
Normal file
113
src/test/java/org/keywind/theme/LoginThemeTest.java
Normal file
|
@ -0,0 +1,113 @@
|
|||
package org.keywind.theme;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import freemarker.core.HTMLOutputFormat;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModelException;
|
||||
import freemarker.template.TemplateNotFoundException;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.forms.login.LoginFormsPages;
|
||||
import org.keycloak.forms.login.freemarker.Templates;
|
||||
import org.keycloak.theme.KeycloakSanitizerMethod;
|
||||
import org.keycloak.theme.beans.MessageFormatterMethod;
|
||||
import org.keycloak.theme.beans.MessagesPerFieldBean;
|
||||
|
||||
public class LoginThemeTest {
|
||||
private static final String LANGUAGE = "English";
|
||||
private static final String MESSAGE_PATH = "theme/base/login/messages/messages";
|
||||
private static final String OUTPUT_PATH = "html/login";
|
||||
private static final String THEME_PATH = "theme/keywind/login";
|
||||
|
||||
@Test
|
||||
public void shouldTestTemplates() throws IOException, TemplateException {
|
||||
Configuration configuration = createFreeMarkerConfiguration();
|
||||
|
||||
for (String templateName : getTemplateNames()) {
|
||||
try {
|
||||
Template template = configuration.getTemplate(templateName);
|
||||
String renderedTemplate = renderTemplate(template);
|
||||
Document document = formatHtml(renderedTemplate);
|
||||
|
||||
saveHtmlToFile(templateName, document);
|
||||
} catch (TemplateNotFoundException e) {
|
||||
System.out.println("Template not found: " + templateName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Configuration createFreeMarkerConfiguration() throws IOException, TemplateModelException {
|
||||
Configuration configuration = new Configuration(Configuration.VERSION_2_3_32);
|
||||
configuration.setDirectoryForTemplateLoading(new File(THEME_PATH));
|
||||
configuration.setOutputFormat(HTMLOutputFormat.INSTANCE);
|
||||
|
||||
Locale locale = Locale.of(LANGUAGE);
|
||||
Properties messages = loadMessages(locale);
|
||||
|
||||
configuration.setSharedVariable("kcSanitize", new KeycloakSanitizerMethod());
|
||||
configuration.setSharedVariable("messagesPerField", new MessagesPerFieldBean());
|
||||
configuration.setSharedVariable("msg", new MessageFormatterMethod(locale, messages));
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
private Properties loadMessages(Locale locale) {
|
||||
ResourceBundle resourceBundle = ResourceBundle.getBundle(MESSAGE_PATH, locale);
|
||||
Properties properties = new Properties();
|
||||
|
||||
Enumeration<String> keys = resourceBundle.getKeys();
|
||||
while (keys.hasMoreElements()) {
|
||||
String key = keys.nextElement();
|
||||
String value = resourceBundle.getString(key);
|
||||
|
||||
properties.setProperty(key, value);
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private String[] getTemplateNames() {
|
||||
return Arrays.stream(LoginFormsPages.values())
|
||||
.map(Templates::getTemplate)
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
private String renderTemplate(Template template) throws IOException, TemplateException {
|
||||
Map<String, Object> dataModel = LoginDataModel.createDataModel();
|
||||
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
template.process(dataModel, writer);
|
||||
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private Document formatHtml(String html) {
|
||||
Document document = Jsoup.parse(html);
|
||||
document.outputSettings().indentAmount(2);
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
private void saveHtmlToFile(String templateName, Document document) throws IOException {
|
||||
File outputFile = new File(OUTPUT_PATH, templateName.replace(".ftl", ".html"));
|
||||
|
||||
try (FileWriter fileWriter = new FileWriter(outputFile)) {
|
||||
fileWriter.write(document.outerHtml());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
const colors = require('tailwindcss/colors');
|
||||
import type { Config } from 'tailwindcss';
|
||||
import colors from 'tailwindcss/colors';
|
||||
|
||||
/**
|
||||
* @type { import('tailwindcss').Config }
|
||||
*/
|
||||
module.exports = {
|
||||
export default {
|
||||
content: ['./theme/**/*.ftl'],
|
||||
experimental: {
|
||||
optimizeUniversalDefaults: true,
|
||||
|
@ -36,4 +34,4 @@ module.exports = {
|
|||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
} satisfies Config;
|
File diff suppressed because one or more lines are too long
5
theme/keywind/login/resources/dist/assets/module.esm-9a996e1c.js
vendored
Normal file
5
theme/keywind/login/resources/dist/assets/module.esm-9a996e1c.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
theme/keywind/login/resources/dist/index.css
vendored
2
theme/keywind/login/resources/dist/index.css
vendored
File diff suppressed because one or more lines are too long
2
theme/keywind/login/resources/dist/index.js
vendored
2
theme/keywind/login/resources/dist/index.js
vendored
|
@ -1 +1 @@
|
|||
import{m as o}from"./assets/module.esm-62c37d0d.js";window.Alpine=o;o.start();
|
||||
import{m as o}from"./assets/module.esm-9a996e1c.js";window.Alpine=o;o.start();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import{m as p}from"./assets/module.esm-62c37d0d.js";document.addEventListener("alpine:init",()=>{p.data("recoveryCodes",function(){const{codeList:o}=this.$refs,{downloadFileDate:n,downloadFileDescription:i,downloadFileHeader:d,downloadFileName:s}=this.$store.recoveryCodes,a=new Date().toLocaleString(navigator.language),r=o.getElementsByTagName("li"),l=Array.from(r).map(t=>t.innerText).join(`
|
||||
import{m as p}from"./assets/module.esm-9a996e1c.js";document.addEventListener("alpine:init",()=>{p.data("recoveryCodes",function(){const{codeList:o}=this.$refs,{downloadFileDate:n,downloadFileDescription:i,downloadFileHeader:d,downloadFileName:s}=this.$store.recoveryCodes,a=new Date().toLocaleString(navigator.language),r=o.getElementsByTagName("li"),l=Array.from(r).map(t=>t.innerText).join(`
|
||||
`);return{copy:()=>navigator.clipboard.writeText(l),download:()=>{const t=document.createElement("a"),c=`${d}
|
||||
|
||||
${l}
|
||||
|
|
|
@ -1 +1 @@
|
|||
import{m as g}from"./assets/module.esm-62c37d0d.js";import{b as n}from"./assets/index-a7b84447.js";document.addEventListener("alpine:init",()=>{g.data("webAuthnAuthenticate",function(){const{authenticatorDataInput:l,authnSelectForm:r,clientDataJSONInput:p,credentialIdInput:f,errorInput:s,signatureInput:d,userHandleInput:h,webAuthnForm:a}=this.$refs,{challenge:m,createTimeout:o,isUserIdentified:A,rpId:w,unsupportedBrowserText:y,userVerification:u}=this.$store.webAuthnAuthenticate,c=i=>{if(!window.PublicKeyCredential){s.value=y,a.submit();return}const t={challenge:n.parse(m,{loose:!0}),rpId:w};i.length&&(t.allowCredentials=i),parseInt(o)!==0&&(t.timeout=parseInt(o)*1e3),u!=="not specified"&&(t.userVerification=u),navigator.credentials.get({publicKey:t}).then(e=>{e instanceof PublicKeyCredential&&e.response instanceof AuthenticatorAssertionResponse&&(window.result=e,l.value=n.stringify(new Uint8Array(e.response.authenticatorData),{pad:!1}),p.value=n.stringify(new Uint8Array(e.response.clientDataJSON),{pad:!1}),d.value=n.stringify(new Uint8Array(e.response.signature),{pad:!1}),f.value=e.id,e.response.userHandle&&(h.value=n.stringify(new Uint8Array(e.response.userHandle),{pad:!1})),a.submit())}).catch(e=>{s.value=e,a.submit()})},b=()=>{const i=[];if(r){const t=Array.from(r.elements);t.length&&t.forEach(e=>{e instanceof HTMLInputElement&&i.push({id:n.parse(e.value,{loose:!0}),type:"public-key"})})}c(i)};return{webAuthnAuthenticate:()=>{if(!A){c([]);return}b()}}})});
|
||||
import{m as g}from"./assets/module.esm-9a996e1c.js";import{b as n}from"./assets/index-a7b84447.js";document.addEventListener("alpine:init",()=>{g.data("webAuthnAuthenticate",function(){const{authenticatorDataInput:l,authnSelectForm:r,clientDataJSONInput:p,credentialIdInput:f,errorInput:s,signatureInput:d,userHandleInput:h,webAuthnForm:a}=this.$refs,{challenge:m,createTimeout:o,isUserIdentified:A,rpId:w,unsupportedBrowserText:y,userVerification:u}=this.$store.webAuthnAuthenticate,c=i=>{if(!window.PublicKeyCredential){s.value=y,a.submit();return}const t={challenge:n.parse(m,{loose:!0}),rpId:w};i.length&&(t.allowCredentials=i),parseInt(o)!==0&&(t.timeout=parseInt(o)*1e3),u!=="not specified"&&(t.userVerification=u),navigator.credentials.get({publicKey:t}).then(e=>{e instanceof PublicKeyCredential&&e.response instanceof AuthenticatorAssertionResponse&&(window.result=e,l.value=n.stringify(new Uint8Array(e.response.authenticatorData),{pad:!1}),p.value=n.stringify(new Uint8Array(e.response.clientDataJSON),{pad:!1}),d.value=n.stringify(new Uint8Array(e.response.signature),{pad:!1}),f.value=e.id,e.response.userHandle&&(h.value=n.stringify(new Uint8Array(e.response.userHandle),{pad:!1})),a.submit())}).catch(e=>{s.value=e,a.submit()})},b=()=>{const i=[];if(r){const t=Array.from(r.elements);t.length&&t.forEach(e=>{e instanceof HTMLInputElement&&i.push({id:n.parse(e.value,{loose:!0}),type:"public-key"})})}c(i)};return{webAuthnAuthenticate:()=>{if(!A){c([]);return}b()}}})});
|
||||
|
|
|
@ -1 +1 @@
|
|||
import{m as T}from"./assets/module.esm-62c37d0d.js";import{b as a}from"./assets/index-a7b84447.js";document.addEventListener("alpine:init",()=>{T.data("webAuthnRegister",function(){const{attestationObjectInput:m,authenticatorLabelInput:g,clientDataJSONInput:A,errorInput:I,publicKeyCredentialIdInput:w,registerForm:s,transportsInput:C}=this.$refs,{attestationConveyancePreference:u,authenticatorAttachment:c,challenge:K,createTimeout:l,excludeCredentialIds:v,requireResidentKey:p,rpEntityName:S,rpId:P,signatureAlgorithms:R,unsupportedBrowserText:x,userId:E,userVerificationRequirement:d,username:f}=this.$store.webAuthnRegister,L=t=>{const e=[];return t===""?(e.push({alg:-7,type:"public-key"}),e):(t.split(",").forEach(r=>{e.push({alg:parseInt(r),type:"public-key"})}),e)},q=t=>{const e=[];return t===""||t.split(",").forEach(r=>{e.push({id:a.parse(r,{loose:!0}),type:"public-key"})}),e},N=t=>{if(t===""||t.constructor!==Array)return"";let e="";return t.forEach(i=>{e+=i+","}),e.slice(0,-1)};return{registerSecurityKey:()=>{if(!window.PublicKeyCredential){I.value=x,s.submit();return}const t={challenge:a.parse(K,{loose:!0}),pubKeyCredParams:L(R),rp:{id:P,name:S},user:{displayName:f,id:a.parse(E,{loose:!0}),name:f}};u!=="not specified"&&(t.attestation=u);const e={};let i=!1;c!=="not specified"&&(e.authenticatorAttachment=c,i=!0),p!=="not specified"&&(p==="Yes"?e.requireResidentKey=!0:e.requireResidentKey=!1,i=!0),d!=="not specified"&&(e.userVerification=d,i=!0),i&&(t.authenticatorSelection=e);const r=q(v);r.length>0&&(t.excludeCredentials=r),parseInt(l)!==0&&(t.timeout=parseInt(l)*1e3),navigator.credentials.create({publicKey:t}).then(n=>{if(n instanceof PublicKeyCredential&&n.response instanceof AuthenticatorAttestationResponse){const{getTransports:h}=n.response;window.result=n;const O=n.rawId;if(m.value=a.stringify(new Uint8Array(n.response.attestationObject),{pad:!1}),A.value=a.stringify(new Uint8Array(n.response.clientDataJSON),{pad:!1}),w.value=a.stringify(new Uint8Array(O),{pad:!1}),typeof h=="function"){const b=h();b&&(C.value=N(b))}else console.log("Your browser is not able to recognize supported transport media for the authenticator.");const y="WebAuthn Authenticator (Default Label)";let o=window.prompt("Please input your registered authenticator's label",y);o===null&&(o=y),g.value=o,s.submit()}}).catch(function(n){n.value=n,s.submit()})}}})});
|
||||
import{m as T}from"./assets/module.esm-9a996e1c.js";import{b as a}from"./assets/index-a7b84447.js";document.addEventListener("alpine:init",()=>{T.data("webAuthnRegister",function(){const{attestationObjectInput:m,authenticatorLabelInput:g,clientDataJSONInput:A,errorInput:I,publicKeyCredentialIdInput:w,registerForm:s,transportsInput:C}=this.$refs,{attestationConveyancePreference:u,authenticatorAttachment:c,challenge:K,createTimeout:l,excludeCredentialIds:v,requireResidentKey:p,rpEntityName:S,rpId:P,signatureAlgorithms:R,unsupportedBrowserText:x,userId:E,userVerificationRequirement:d,username:f}=this.$store.webAuthnRegister,L=t=>{const e=[];return t===""?(e.push({alg:-7,type:"public-key"}),e):(t.split(",").forEach(r=>{e.push({alg:parseInt(r),type:"public-key"})}),e)},q=t=>{const e=[];return t===""||t.split(",").forEach(r=>{e.push({id:a.parse(r,{loose:!0}),type:"public-key"})}),e},N=t=>{if(t===""||t.constructor!==Array)return"";let e="";return t.forEach(i=>{e+=i+","}),e.slice(0,-1)};return{registerSecurityKey:()=>{if(!window.PublicKeyCredential){I.value=x,s.submit();return}const t={challenge:a.parse(K,{loose:!0}),pubKeyCredParams:L(R),rp:{id:P,name:S},user:{displayName:f,id:a.parse(E,{loose:!0}),name:f}};u!=="not specified"&&(t.attestation=u);const e={};let i=!1;c!=="not specified"&&(e.authenticatorAttachment=c,i=!0),p!=="not specified"&&(p==="Yes"?e.requireResidentKey=!0:e.requireResidentKey=!1,i=!0),d!=="not specified"&&(e.userVerification=d,i=!0),i&&(t.authenticatorSelection=e);const r=q(v);r.length>0&&(t.excludeCredentials=r),parseInt(l)!==0&&(t.timeout=parseInt(l)*1e3),navigator.credentials.create({publicKey:t}).then(n=>{if(n instanceof PublicKeyCredential&&n.response instanceof AuthenticatorAttestationResponse){const{getTransports:h}=n.response;window.result=n;const O=n.rawId;if(m.value=a.stringify(new Uint8Array(n.response.attestationObject),{pad:!1}),A.value=a.stringify(new Uint8Array(n.response.clientDataJSON),{pad:!1}),w.value=a.stringify(new Uint8Array(O),{pad:!1}),typeof h=="function"){const b=h();b&&(C.value=N(b))}else console.log("Your browser is not able to recognize supported transport media for the authenticator.");const y="WebAuthn Authenticator (Default Label)";let o=window.prompt("Please input your registered authenticator's label",y);o===null&&(o=y),g.value=o,s.submit()}}).catch(function(n){n.value=n,s.submit()})}}})});
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
<#if auth?has_content && auth.showTryAnotherWayLink() && showAnotherWayIfPresent>
|
||||
<form action="${url.loginAction}" method="post">
|
||||
<input name="tryAnotherWay" type="hidden" value="on" />
|
||||
<@button.kw color="primary" type="submit">
|
||||
<@button.kw color="secondary" type="submit">
|
||||
${msg("doTryAnotherWay")}
|
||||
</@button.kw>
|
||||
</form>
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"moduleResolution": "bundler",
|
||||
"noEmit": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true
|
||||
},
|
||||
"include": ["src"]
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
"allowSyntheticDefaultImports": true,
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node"
|
||||
"moduleResolution": "bundler",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue