Skip to content

Commit

Permalink
remove the need for auth provider env (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
KMKoushik authored Oct 16, 2024
1 parent 3a19b2b commit aba9f22
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 46 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pnpm i
### Setting up the environment

- Copy the env.example file into .env
- Setup google oauth required for auth https://next-auth.js.org/providers/google
- Setup google oauth required for auth https://next-auth.js.org/providers/google or Email provider by setting SMTP details
- Login to minio console using `splitpro` user and password `password` and [create access keys](http://localhost:9001/access-keys/new-account) and the R2 related env variables

### Run the app
Expand Down
9 changes: 3 additions & 6 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,6 @@ import pwa from 'next-pwa';
// @ts-ignore
import nextra from 'nextra';

import { fileURLToPath } from 'node:url';
import createJiti from 'jiti';
const jiti = createJiti(fileURLToPath(import.meta.url));

jiti('./src/env.js');

// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const withPwa = pwa({
dest: 'public',
Expand All @@ -28,6 +22,9 @@ const withPwa = pwa({
const config = {
reactStrictMode: true,
output: process.env.DOCKER_OUTPUT ? 'standalone' : undefined,
experimental: {
instrumentationHook: true,
},
/**
* If you are using `appDir` then you must comment the below `i18n` config out.
*
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
"framer-motion": "^11.0.3",
"geist": "^1.2.1",
"input-otp": "^1.2.3",
"jiti": "^1.21.6",
"lucide-react": "^0.312.0",
"nanoid": "^5.0.6",
"next": "^14.0.4",
Expand Down Expand Up @@ -106,4 +105,4 @@
"seed": "tsx prisma/seed.ts"
},
"packageManager": "pnpm@8.9.2"
}
}
3 changes: 0 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions src/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export const env = createEnv({
// VERCEL_URL doesn't include `https` so it cant be validated as a URL
process.env.VERCEL ? z.string() : z.string().url(),
),
AUTH_PROVIDERS: z.string(),
ENABLE_SENDING_INVITES: z.boolean(),
FROM_EMAIL: z.string().optional(),
EMAIL_SERVER_HOST: z.string().optional(),
Expand Down Expand Up @@ -62,7 +61,6 @@ export const env = createEnv({
NODE_ENV: process.env.NODE_ENV,
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
AUTH_PROVIDERS: process.env.AUTH_PROVIDERS,
ENABLE_SENDING_INVITES: process.env.ENABLE_SENDING_INVITES === 'true',
FROM_EMAIL: process.env.FROM_EMAIL,
EMAIL_SERVER_HOST: process.env.EMAIL_SERVER_HOST,
Expand Down
12 changes: 12 additions & 0 deletions src/instrumentation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Add things here to be executed during server startup.
*
* more details here: https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation
*/
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
console.log('Registering instrumentation');
const { validateAuthEnv } = await import('./server/auth');
validateAuthEnv();
}
}
70 changes: 43 additions & 27 deletions src/pages/auth/signin.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client';
import { signIn } from 'next-auth/react';
import { type ClientSafeProvider, getProviders, signIn } from 'next-auth/react';
import Head from 'next/head';
import { Button } from '~/components/ui/button';
import Image from 'next/image';
Expand Down Expand Up @@ -39,15 +39,33 @@ const otpSchema = z.object({
otp: z.string({ required_error: 'OTP is required' }).length(5, { message: 'Invalid OTP' }),
});

const providerSvgs = {
github: (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 496 512"
className="h-4 w-4 fill-primary-foreground "
>
<path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z" />
</svg>
),
google: (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 488 512"
className="h-4 w-4 fill-primary-foreground"
>
<path d="M488 261.8C488 403.3 391.1 504 248 504 110.8 504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z" />
</svg>
),
};

const Home: NextPage<{ authProviders: string; feedbackEmail: string }> = ({
authProviders,
const Home: NextPage<{ feedbackEmail: string; providers: ClientSafeProvider[] }> = ({
providers,
feedbackEmail,
}) => {
const [emailStatus, setEmailStatus] = useState<'idle' | 'sending' | 'success'>('idle');

const providers = authProviders.split(',').map((provider) => provider.trim().toUpperCase());

const emailForm = useForm<z.infer<typeof emailSchema>>({
resolver: zodResolver(emailSchema),
});
Expand Down Expand Up @@ -85,30 +103,26 @@ const Home: NextPage<{ authProviders: string; feedbackEmail: string }> = ({
<div className="mb-10 flex items-center gap-4">
<p className="text-3xl text-primary">SplitPro</p>
</div>
{providers?.includes('GOOGLE') && (
<Button
className="mx-auto flex w-[300px] items-center gap-2 bg-white hover:bg-gray-100 focus:bg-gray-100"
onClick={() => signIn('google')}
>
<Image
alt="Google logo"
loading="lazy"
height="15"
width="15"
id="provider-logo-dark"
src="https://authjs.dev/img/providers/google.svg"
/>
Continue with Google
</Button>
)}
{providers
.filter((provider) => provider.id !== 'email')
.map((provider) => (
<Button
className="mx-auto flex w-[300px] items-center gap-3 bg-white hover:bg-gray-100 focus:bg-gray-100"
onClick={() => signIn(provider.id)}
key={provider.id}
>
{providerSvgs[provider.id as keyof typeof providerSvgs]}
Continue with {provider.name}
</Button>
))}
{providers && providers.length === 2 && (
<div className="mt-6 flex w-[300px] items-center justify-between gap-2">
<p className=" z-10 ml-[150px] -translate-x-1/2 bg-background px-4 text-sm">or</p>
<div className="absolute h-[1px] w-[300px] bg-gradient-to-r from-zinc-800 via-zinc-300 to-zinc-800"></div>
</div>
)}
{providers?.includes('EMAIL') &&
(emailStatus === 'success' ? (
{providers.find((provider) => provider.id === 'email') ? (
emailStatus === 'success' ? (
<>
<p className="mt-6 w-[300px] text-center text-sm">
We have sent an email with the OTP. Please check your inbox
Expand Down Expand Up @@ -181,10 +195,10 @@ const Home: NextPage<{ authProviders: string; feedbackEmail: string }> = ({
</form>
</Form>
</>
))}
)
) : null}
<p className="mt-6 w-[300px] text-center text-sm text-muted-foreground">
Trouble logging in? contact

<br />
<a className="underline" href={'mailto:' + feedbackEmail}>
{feedbackEmail ?? ''}
Expand All @@ -200,7 +214,9 @@ export default Home;

export const getServerSideProps: GetServerSideProps = async (context) => {
const session = await getServerAuthSession(context);
const feedbackEmail = process.env.FEEDBACK_EMAIL;
const providers = await getProviders();

console.log('providers', providers);

if (session) {
return {
Expand All @@ -213,8 +229,8 @@ export const getServerSideProps: GetServerSideProps = async (context) => {

return {
props: {
authProviders: env.AUTH_PROVIDERS,
feedbackEmail: env.FEEDBACK_EMAIL ?? '',
providers: Object.values(providers ?? {}),
},
};
};
25 changes: 20 additions & 5 deletions src/server/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,8 @@ export const getServerAuthSessionForSSG = async (context: GetServerSidePropsCont
*/
function getProviders() {
const providersList = [];
const envProviders = env.AUTH_PROVIDERS?.split(',').map((provider) =>
provider.trim().toUpperCase(),
);

if (envProviders?.includes('GOOGLE') && env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET) {
if (env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET) {
providersList.push(
GoogleProvider({
clientId: env.GOOGLE_CLIENT_ID,
Expand All @@ -122,7 +119,7 @@ function getProviders() {
);
}

if (envProviders?.includes('EMAIL')) {
if (env.EMAIL_SERVER_HOST) {
providersList.push(
EmailProvider({
from: env.FROM_EMAIL,
Expand All @@ -149,3 +146,21 @@ function getProviders() {

return providersList;
}

/**
* Validates the environment variables that are related to authentication.
* this will check if atleat one provider is set properly.
*
* this function should be updated if new providers are added.
*/
export function validateAuthEnv() {
console.log('Validating auth env');
if (!process.env.SKIP_ENV_VALIDATION) {
const providers = getProviders();
if (providers.length === 0) {
throw new Error(
'No authentication providers are configured, at least one is required. Learn more here: https://github.com/oss-apps/split-pro?tab=readme-ov-file#setting-up-the-environment',
);
}
}
}

0 comments on commit aba9f22

Please sign in to comment.