feature(auth): replace clerk.com with custom auth (#103)

* feature(auth): replace clerk.com with custom auth

* minor fixes

* remove notification preferences

* decrease live events interval

fix(api): cookies..

# Conflicts:
#	.gitignore
#	apps/api/src/index.ts
#	apps/dashboard/src/app/providers.tsx
#	packages/trpc/src/trpc.ts
This commit is contained in:
Carl-Gerhard Lindesvärd
2024-12-18 21:30:39 +01:00
committed by Carl-Gerhard Lindesvärd
parent f28802b1c2
commit d31d9924a5
151 changed files with 18484 additions and 12853 deletions

View File

@@ -1,91 +0,0 @@
'use client';
import {
InputOTP,
InputOTPGroup,
InputOTPSlot,
} from '@/components/ui/input-otp';
import { getClerkError } from '@/utils/clerk-error';
import { useSignUp } from '@clerk/nextjs';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { toast } from 'sonner';
import { popModal } from '.';
import { ModalContent, ModalHeader } from './Modal/Container';
type Props = {
email: string;
};
export default function VerifyEmail({ email }: Props) {
const { signUp, setActive, isLoaded } = useSignUp();
const router = useRouter();
const [code, setCode] = useState('');
return (
<ModalContent
onPointerDownOutside={(e) => e.preventDefault()}
onEscapeKeyDown={(e) => e.preventDefault()}
>
<ModalHeader
title="Verify your email"
text={
<p>
Please enter the verification code sent to your{' '}
<span className="font-semibold">{email}</span>.
</p>
}
/>
<InputOTP
maxLength={6}
value={code}
onChange={setCode}
onComplete={async () => {
if (!isLoaded) {
return toast.info('Sign up is not available at the moment');
}
try {
const completeSignUp = await signUp.attemptEmailAddressVerification(
{
code,
},
);
if (completeSignUp.status !== 'complete') {
// The status can also be `abandoned` or `missing_requirements`
// Please see https://clerk.com/docs/references/react/use-sign-up#result-status for more information
return toast.error('Invalid code');
}
// Check the status to see if it is complete
// If complete, the user has been created -- set the session active
if (completeSignUp.status === 'complete') {
await setActive({ session: completeSignUp.createdSessionId });
router.push('/onboarding');
popModal();
}
} catch (e) {
const error = getClerkError(e);
if (error) {
toast.error(error.longMessage);
} else {
toast.error('An error occurred, please try again later');
}
}
}}
>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
</ModalContent>
);
}

View File

@@ -14,6 +14,9 @@ const Loading = () => (
);
const modals = {
RequestPasswordReset: dynamic(() => import('./request-reset-password'), {
loading: Loading,
}),
EditEvent: dynamic(() => import('./edit-event'), {
loading: Loading,
}),
@@ -56,9 +59,6 @@ const modals = {
OnboardingTroubleshoot: dynamic(() => import('./OnboardingTroubleshoot'), {
loading: Loading,
}),
VerifyEmail: dynamic(() => import('./VerifyEmail'), {
loading: Loading,
}),
DateRangerPicker: dynamic(() => import('./DateRangerPicker'), {
loading: Loading,
}),

View File

@@ -0,0 +1,73 @@
'use client';
import { Button } from '@/components/ui/button';
import { DialogFooter } from '@/components/ui/dialog';
import { api, handleError } from '@/trpc/client';
import { zodResolver } from '@hookform/resolvers/zod';
import { SendIcon } from 'lucide-react';
import { useRouter } from 'next/navigation';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import type { z } from 'zod';
import { InputWithLabel } from '@/components/forms/input-with-label';
import { zRequestResetPassword } from '@openpanel/validation';
import { popModal } from '.';
import { ModalContent, ModalHeader } from './Modal/Container';
const validation = zRequestResetPassword;
type IForm = z.infer<typeof validation>;
type Props = {
email?: string;
};
export default function RequestPasswordReset({ email }: Props) {
const router = useRouter();
const form = useForm<IForm>({
resolver: zodResolver(validation),
defaultValues: {
email: email ?? '',
},
});
const mutation = api.auth.requestResetPassword.useMutation({
onError: handleError,
onSuccess() {
toast.success('You should receive an email shortly!');
popModal();
},
});
const onSubmit = form.handleSubmit((values) => {
mutation.mutate({
email: values.email,
});
});
return (
<ModalContent>
<ModalHeader title="Request password reset" />
<form className="flex flex-col gap-4" onSubmit={onSubmit}>
<InputWithLabel
label="Email"
placeholder="Your email address"
error={form.formState.errors.email?.message}
{...form.register('email')}
/>
<DialogFooter>
<Button
type="button"
variant={'secondary'}
onClick={() => popModal()}
>
Cancel
</Button>
<Button type="submit" icon={SendIcon} loading={mutation.isLoading}>
Continue
</Button>
</DialogFooter>
</form>
</ModalContent>
);
}