diff --git a/README.md b/README.md
index c2b8fa9..8630dcf 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/next.config.js b/next.config.js
index b4d1e03..306d735 100644
--- a/next.config.js
+++ b/next.config.js
@@ -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',
@@ -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.
*
diff --git a/package.json b/package.json
index 7b574bd..726eaf1 100644
--- a/package.json
+++ b/package.json
@@ -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",
@@ -106,4 +105,4 @@
"seed": "tsx prisma/seed.ts"
},
"packageManager": "pnpm@8.9.2"
-}
+}
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 24463f8..c615858 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -95,9 +95,6 @@ dependencies:
input-otp:
specifier: ^1.2.3
version: 1.2.3(react-dom@18.2.0)(react@18.2.0)
- jiti:
- specifier: ^1.21.6
- version: 1.21.6
lucide-react:
specifier: ^0.312.0
version: 0.312.0(react@18.2.0)
diff --git a/src/env.js b/src/env.js
index 3863229..52606ba 100644
--- a/src/env.js
+++ b/src/env.js
@@ -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(),
@@ -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,
diff --git a/src/instrumentation.ts b/src/instrumentation.ts
new file mode 100644
index 0000000..b463eaa
--- /dev/null
+++ b/src/instrumentation.ts
@@ -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();
+ }
+}
diff --git a/src/pages/auth/signin.tsx b/src/pages/auth/signin.tsx
index d6d3bc1..2592250 100644
--- a/src/pages/auth/signin.tsx
+++ b/src/pages/auth/signin.tsx
@@ -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';
@@ -39,15 +39,33 @@ const otpSchema = z.object({
otp: z.string({ required_error: 'OTP is required' }).length(5, { message: 'Invalid OTP' }),
});
+const providerSvgs = {
+ github: (
+
+
+
+ ),
+ google: (
+
+
+
+ ),
+};
-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>({
resolver: zodResolver(emailSchema),
});
@@ -85,30 +103,26 @@ const Home: NextPage<{ authProviders: string; feedbackEmail: string }> = ({
- {providers?.includes('GOOGLE') && (
- signIn('google')}
- >
-
- Continue with Google
-
- )}
+ {providers
+ .filter((provider) => provider.id !== 'email')
+ .map((provider) => (
+ signIn(provider.id)}
+ key={provider.id}
+ >
+ {providerSvgs[provider.id as keyof typeof providerSvgs]}
+ Continue with {provider.name}
+
+ ))}
{providers && providers.length === 2 && (
)}
- {providers?.includes('EMAIL') &&
- (emailStatus === 'success' ? (
+ {providers.find((provider) => provider.id === 'email') ? (
+ emailStatus === 'success' ? (
<>
We have sent an email with the OTP. Please check your inbox
@@ -181,10 +195,10 @@ const Home: NextPage<{ authProviders: string; feedbackEmail: string }> = ({
>
- ))}
+ )
+ ) : null}
Trouble logging in? contact
-
{feedbackEmail ?? ''}
@@ -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 {
@@ -213,8 +229,8 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
return {
props: {
- authProviders: env.AUTH_PROVIDERS,
feedbackEmail: env.FEEDBACK_EMAIL ?? '',
+ providers: Object.values(providers ?? {}),
},
};
};
diff --git a/src/server/auth.ts b/src/server/auth.ts
index 8e2def8..159a1ff 100644
--- a/src/server/auth.ts
+++ b/src/server/auth.ts
@@ -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,
@@ -122,7 +119,7 @@ function getProviders() {
);
}
- if (envProviders?.includes('EMAIL')) {
+ if (env.EMAIL_SERVER_HOST) {
providersList.push(
EmailProvider({
from: env.FROM_EMAIL,
@@ -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',
+ );
+ }
+ }
+}