mirror of
https://github.com/thomiceli/opengist.git
synced 2025-06-21 17:28:00 +02:00
Add TOTP MFA (#342)
This commit is contained in:
14
templates/base/base_header.html
vendored
14
templates/base/base_header.html
vendored
@ -302,6 +302,20 @@
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{range .flashWarnings}}
|
||||
<div class="mt-4 rounded-md bg-gray-50 dark:bg-gray-800 border-l-4 border-yellow-500 dark:border-yellow-400 p-4">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-yellow-600 dark:text-yellow-400" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm text-yellow-600 dark:text-yellow-400">{{.}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{ end }}
|
||||
|
25
templates/pages/mfa.html
vendored
25
templates/pages/mfa.html
vendored
@ -7,7 +7,8 @@
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<div class="mt-8 sm:w-full sm:max-w-md mx-auto">
|
||||
<div class="mt-8 sm:w-full sm:max-w-md mx-auto grid gap-y-4">
|
||||
{{ if .hasWebauthn }}
|
||||
<div class="bg-white dark:bg-gray-900 rounded-md border border-1 border-gray-200 dark:border-gray-700 py-8 px-4 shadow sm:rounded-lg sm:px-10 ">
|
||||
<div class="flex items-center justify-center">
|
||||
<p class="block text-md font-medium items-center text-slate-700 dark:text-slate-300">{{ .locale.Tr "auth.mfa.use-passkey-to-finish" }}</p>
|
||||
@ -27,6 +28,28 @@
|
||||
<p id="login-passkey-wait" class="hidden text-sm font-medium items-center text-slate-700 dark:text-slate-300">{{ .locale.Tr "auth.mfa.waiting-for-passkey-input" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .hasTotp }}
|
||||
<div class="bg-white dark:bg-gray-900 rounded-md border border-1 border-gray-200 dark:border-gray-700 py-8 px-4 shadow sm:rounded-lg sm:px-10 ">
|
||||
<div class="flex items-center justify-center">
|
||||
<p class="block text-md font-medium items-center text-slate-700 dark:text-slate-300">{{ .locale.Tr "auth.totp.enter-code" }}</p>
|
||||
</div>
|
||||
<div class="flex items-center justify-center">
|
||||
<p class="block text-sm font-medium items-center text-slate-600 dark:text-slate-400">{{ .locale.Tr "auth.totp.enter-recovery-key" }}</p>
|
||||
</div>
|
||||
<div class="flex items-center justify-center mt-4">
|
||||
<form method="post" action="{{ $.c.ExternalUrl }}/mfa/totp/assertion">
|
||||
{{ .csrfHtml }}
|
||||
<label for="code" class="block text-sm font-medium text-slate-700 dark:text-slate-300">{{ .locale.Tr "auth.totp.code" }}</label>
|
||||
<div class="mt-1">
|
||||
<input id="code" name="code" type="text" required autocomplete="off" class="dark:bg-gray-800 appearance-none block w-full px-3 py-2 border border-gray-200 dark:border-gray-700 rounded-md shadow-sm placeholder-gray-600 dark:placeholder-gray-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" />
|
||||
</div>
|
||||
<button type="submit" class="mt-2 inline-flex items-center px-4 py-2 border border-transparent border-gray-200 dark:border-gray-700 text-sm font-medium rounded-md shadow-sm text-white dark:text-white bg-primary-500 hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">{{ .locale.Tr "auth.totp.submit" }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
32
templates/pages/settings.html
vendored
32
templates/pages/settings.html
vendored
@ -149,6 +149,32 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="w-full">
|
||||
<div class="bg-white dark:bg-gray-900 rounded-md border border-1 border-gray-200 dark:border-gray-700 py-8 px-4 shadow sm:rounded-lg sm:px-10">
|
||||
<h2 class="text-md font-bold text-slate-700 dark:text-slate-300">
|
||||
{{ .locale.Tr "auth.totp" }}
|
||||
</h2>
|
||||
<h3 class="text-sm text-gray-600 dark:text-gray-400 italic mb-4">
|
||||
{{ .locale.Tr "auth.totp.help" }}
|
||||
</h3>
|
||||
{{ if .hasTotp }}
|
||||
<div class="flex">
|
||||
<form method="post" action="{{ $.c.ExternalUrl }}/settings/totp" onconfirm="" class="mr-2">
|
||||
<input type="hidden" name="_method" value="DELETE" />
|
||||
{{ .csrfHtml }}
|
||||
<button type="submit" class="inline-flex items-center px-4 py-2 border border-transparent border-gray-200 dark:border-gray-700 text-sm font-medium rounded-md shadow-sm text-white dark:text-white bg-rose-600 hover:bg-rose-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-rose-500">{{ .locale.Tr "auth.totp.disable" }}</button>
|
||||
</form>
|
||||
<form method="post" action="{{ $.c.ExternalUrl }}/settings/totp/regenerate" onconfirm="">
|
||||
{{ .csrfHtml }}
|
||||
<button type="submit" class="inline-flex items-center px-4 py-2 border border-transparent border-gray-200 dark:border-gray-700 text-sm font-medium rounded-md shadow-sm text-white dark:text-white bg-primary-500 hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">{{ .locale.Tr "auth.totp.regenerate-recovery-codes" }}</button>
|
||||
</form>
|
||||
</div>
|
||||
{{ else }}
|
||||
<a href="{{ $.c.ExternalUrl }}/settings/totp/generate" class="inline-flex items-center px-4 py-2 border border-transparent border-gray-200 dark:border-gray-700 text-sm font-medium rounded-md shadow-sm text-white dark:text-white bg-primary-500 hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">{{ .locale.Tr "auth.totp.use" }}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sm:grid grid-cols-2 gap-x-4 md:gap-x-8">
|
||||
<div class="w-full">
|
||||
<div class="bg-white dark:bg-gray-900 rounded-md border border-1 border-gray-200 dark:border-gray-700 py-8 px-4 shadow sm:rounded-lg sm:px-10">
|
||||
@ -162,7 +188,7 @@
|
||||
<div>
|
||||
<label for="passkeyname" class="block text-sm font-medium text-slate-700 dark:text-slate-300">{{ .locale.Tr "auth.mfa.passkey-name" }}</label>
|
||||
<div class="mt-1">
|
||||
<input id="passkeyname" name="passkeyname" type="text" required autocomplete="off" class="dark:bg-gray-800 appearance-none block w-full px-3 py-2 border border-gray-200 dark:border-gray-700 rounded-md shadow-sm placeholder-gray-600 dark:placeholder-gray-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm">
|
||||
<input id="passkeyname" name="passkeyname" type="text" required autocomplete="off" class="dark:bg-gray-800 appearance-none block w-full px-3 py-2 border border-gray-200 dark:border-gray-700 rounded-md shadow-sm placeholder-gray-600 dark:placeholder-gray-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" />
|
||||
</div>
|
||||
</div>
|
||||
{{ .csrfHtml }}
|
||||
@ -273,9 +299,9 @@
|
||||
<h2 class="text-md font-bold text-slate-700 dark:text-slate-300">
|
||||
{{ .locale.Tr "settings.delete-account" }}
|
||||
</h2>
|
||||
<form class="space-y-6" action="{{ $.c.ExternalUrl }}/settings/account" method="post" onsubmit="return confirm('{{ .locale.Tr "settings.delete-account-confirm" }}')">
|
||||
<form class="space-y-6" action="{{ $.c.ExternalUrl }}/settings/account" method="post">
|
||||
<input type="hidden" name="_method" value="DELETE">
|
||||
<button type="submit" class="inline-flex items-center px-4 py-2 border border-transparent border-gray-200 dark:border-gray-700 text-sm font-medium rounded-md shadow-sm text-white dark:text-white bg-rose-600 hover:bg-rose-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-rose-500 mt-2">{{ .locale.Tr "settings.delete-account" }}</button>
|
||||
<button type="submit" onclick="return confirm('{{ .locale.Tr "settings.delete-account-confirm" }}')" class="inline-flex items-center px-4 py-2 border border-transparent border-gray-200 dark:border-gray-700 text-sm font-medium rounded-md shadow-sm text-white dark:text-white bg-rose-600 hover:bg-rose-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-rose-500 mt-2">{{ .locale.Tr "settings.delete-account" }}</button>
|
||||
{{ .csrfHtml }}
|
||||
</form>
|
||||
</div>
|
||||
|
54
templates/pages/totp.html
vendored
Normal file
54
templates/pages/totp.html
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
{{ template "header" .}}
|
||||
|
||||
<div class="py-10">
|
||||
<header class="pb-4">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold leading-tight">{{ .locale.Tr "auth.totp" }}</h1>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
{{ if .recoveryCodes }}
|
||||
<p class="mb-4">{{ .locale.Tr "auth.totp.save-recovery-codes" }}</p>
|
||||
|
||||
<div class="mt-8 sm:w-full sm:max-w-md mx-auto flex">
|
||||
<div class="mx-auto bg-white dark:bg-gray-900 rounded-md border border-1 border-gray-200 dark:border-gray-700 py-8 px-4 shadow sm:rounded-lg sm:px-10">
|
||||
<ul class="list-none">
|
||||
<code>
|
||||
{{ range .recoveryCodes }}
|
||||
<li>{{ . }}</li>
|
||||
{{ end }}
|
||||
</code>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="mt-8 sm:w-full sm:max-w-md mx-auto flex flex-col items-center">
|
||||
<a href="{{ $.c.ExternalUrl }}/settings" class="px-4 py-2 border border-transparent border-gray-200 dark:border-gray-700 text-sm font-medium rounded-md shadow-sm text-white dark:text-white bg-primary-500 hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">{{ .locale.Tr "auth.totp.proceed" }}</a>
|
||||
</div>
|
||||
|
||||
{{ else }}
|
||||
<p class="mb-2">{{ .locale.Tr "auth.totp.scan-qr-code" }}</p>
|
||||
|
||||
<div class="sm:grid grid-cols-2 gap-x-4 md:gap-x-8">
|
||||
<div class="mt-4">
|
||||
<p class="mb-4"><code>{{.totpSecret}}</code></p>
|
||||
<img src="{{.totpQrcode}}" alt="{{.totpSecret}}">
|
||||
</div>
|
||||
<div>
|
||||
<form method="post" action="{{ $.c.ExternalUrl }}/settings/totp/generate">
|
||||
{{ .csrfHtml }}
|
||||
<label for="code" class="block text-sm font-medium text-slate-700 dark:text-slate-300">{{ .locale.Tr "auth.totp.code" }}</label>
|
||||
<div class="mt-1">
|
||||
<input id="code" name="code" type="text" required autocomplete="off" class="dark:bg-gray-800 appearance-none block w-full px-3 py-2 border border-gray-200 dark:border-gray-700 rounded-md shadow-sm placeholder-gray-600 dark:placeholder-gray-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" />
|
||||
</div>
|
||||
<button type="submit" class="mt-4 inline-flex items-center px-4 py-2 border border-transparent border-gray-200 dark:border-gray-700 text-sm font-medium rounded-md shadow-sm text-white dark:text-white bg-primary-500 hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">{{ .locale.Tr "auth.totp.submit" }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{{ template "footer" .}}
|
Reference in New Issue
Block a user