Files
bewcloud/components/auth/MultiFactorAuthVerifyForm.tsx
Bruno Bernardino 7fac7febcf Public File Sharing (#72)
* Public File Sharing

This implements public file sharing (read-only) with and without passwords (#57).

It also fixes a problem with filenames including special characters like `#` not working properly (#71).

You can share a directory or a single file, by using the new share icon on the right of the directories/files, and click on it to manage an existing file share (setting a new password, or deleting the file share).

There is some other minor cleanup and other copy updates in the README.

Closes #57
Fixes #71

* Hide UI elements when sharing isn't allowed
2025-06-20 12:04:16 +01:00

138 lines
3.8 KiB
TypeScript

import { MultiFactorAuthMethodType } from '/lib/types.ts';
import PasswordlessPasskeyLogin from '/islands/auth/PasswordlessPasskeyLogin.tsx';
interface MultiFactorAuthVerifyFormProps {
email: string;
redirectUrl: string;
availableMethods: MultiFactorAuthMethodType[];
error?: { title: string; message: string };
}
export default function MultiFactorAuthVerifyForm(
{ email, redirectUrl, availableMethods, error }: MultiFactorAuthVerifyFormProps,
) {
const hasPasskey = availableMethods.includes('passkey');
const hasTotp = availableMethods.includes('totp');
const hasEmail = availableMethods.includes('email');
return (
<section class='max-w-md w-full mb-12'>
<section class='mb-6'>
<h2 class='mt-6 text-center text-3xl font-extrabold text-white'>
Multi-Factor Authentication
</h2>
<p class='mt-2 text-center text-sm text-gray-300'>
You are required to authenticate with an additional method
</p>
</section>
{error
? (
<section class='notification-error'>
<h3>{error.title}</h3>
<p>{error.message}</p>
</section>
)
: null}
{hasEmail
? (
<form
class='mb-6'
method='POST'
action={`/mfa-verify?redirect=${encodeURIComponent(redirectUrl)}`}
>
<fieldset class='block mb-4'>
<label class='text-slate-300 block pb-1' for='token'>
Email Verification Code
</label>
<input
type='text'
id='code'
name='code'
placeholder='123456'
class='mt-1 input-field'
autocomplete='off'
required
/>
</fieldset>
<section class='flex justify-center mt-8 mb-4'>
<button
type='submit'
class='button'
>
Verify Code
</button>
</section>
</form>
)
: null}
{hasEmail && hasTotp
? (
<section class='text-center -mt-10 mb-6 block'>
<p class='text-gray-400 text-sm'>or</p>
</section>
)
: null}
{hasTotp
? (
<form
class='mb-6'
method='POST'
action={`/mfa-verify?redirect=${encodeURIComponent(redirectUrl)}`}
>
<fieldset class='block mb-4'>
<label class='text-slate-300 block pb-1' for='token'>
Authentication Token or Backup Code
</label>
<input
type='text'
id='token'
name='token'
placeholder='123456 or backup code'
class='mt-1 input-field'
autocomplete='one-time-code'
required
/>
</fieldset>
<section class='flex justify-center mt-8 mb-4'>
<button
type='submit'
class='button'
>
Verify Code
</button>
</section>
</form>
)
: null}
{(hasEmail || hasTotp) && hasPasskey
? (
<section class='text-center -mt-10 mb-6 block'>
<p class='text-gray-400 text-sm'>or</p>
</section>
)
: null}
{hasPasskey && email
? (
<section class='mb-8'>
<PasswordlessPasskeyLogin email={email} redirectUrl={redirectUrl} />
</section>
)
: null}
<section class='text-center mt-6'>
<a href='/login' class='text-blue-400 hover:text-blue-300 text-sm'>
Back to Login
</a>
</section>
</section>
);
}