diff --git a/.env.example b/.env.example index 6f53284..e509a47 100644 --- a/.env.example +++ b/.env.example @@ -7,3 +7,5 @@ AUTH_AUTHENTIK_SECRET= AUTH_AUTHENTIK_ISSUER= NEXT_PUBLIC_APP_URL= + +MEETUP_SKIP_LOGIN= \ No newline at end of file diff --git a/README.md b/README.md index 1fbb7bf..8a71828 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,10 @@ This project is built with a modern tech stack: # Base URL of your application NEXT_PUBLIC_APP_URL="http://localhost:3000" + + # Development: Skip login flow (set to "true" to bypass authentication) + # Ensure this is NOT set to "true" in production. + MEETUP_SKIP_LOGIN="false" ``` 4. **Apply database migrations (Prisma):** @@ -107,20 +111,11 @@ This project is built with a modern tech stack: - (Optional: If you need to generate Prisma Client without running migrations, use `npx prisma generate`) 5. **Run the development server:** - ```bash yarn dev ``` - Open [http://localhost:3000](http://localhost:3000) in your browser to see the application. - The test user for the application is: - - ```bash - email: test@example.com - password: password - ``` - **Self-Hosting with Docker (Planned):** - A Docker image and `docker-compose.yml` file will be provided in the future to allow for easy self-hosting of the MeetUP application. This setup will also include database services. Instructions will be updated here once available. diff --git a/package.json b/package.json index 2cdd489..8286dc4 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,8 @@ "@eslint/eslintrc": "3.3.1", "@tailwindcss/postcss": "4.1.6", "@types/node": "22.15.17", - "@types/react": "19.1.4", - "@types/react-dom": "19.1.5", + "@types/react": "19.1.3", + "@types/react-dom": "19.1.4", "cypress": "14.3.3", "dotenv-cli": "^8.0.0", "eslint": "9.26.0", diff --git a/src/app/home/page.tsx b/src/app/home/page.tsx index 4e6773b..c61abdd 100644 --- a/src/app/home/page.tsx +++ b/src/app/home/page.tsx @@ -1,3 +1,4 @@ +import { Logout } from '@/components/user/sso-logout-button'; import { RedirectButton } from '@/components/user/redirect-button'; import { ThemePicker } from '@/components/user/theme-picker'; @@ -7,7 +8,7 @@ export default function Home() {
{}

Home

- +
diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 34d1b07..6b74310 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -1,4 +1,4 @@ -import { auth, providerMap } from '@/auth'; +import { auth } from '@/auth'; import SSOLogin from '@/components/user/sso-login-button'; import LoginForm from '@/components/user/login-form'; import { redirect } from 'next/navigation'; @@ -37,16 +37,15 @@ export default async function LoginPage() { - {providerMap.length > 0 &&
} +
- {providerMap.map((provider) => ( + {process.env.AUTH_AUTHENTIK_ISSUER && ( - ))} + )}
diff --git a/src/app/logout/page.tsx b/src/app/logout/page.tsx deleted file mode 100644 index 15f29aa..0000000 --- a/src/app/logout/page.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { signOut } from '@/auth'; -import { Button } from '@/components/ui/button'; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from '@/components/ui/card'; - -export default function SignOutPage() { - return ( -
-
{ - 'use server'; - await signOut({ redirectTo: '/login' }); - }} - > - - - Logout - - Are you sure you want to log out? - - - - - - -
-
- ); -} diff --git a/src/app/page.tsx b/src/app/page.tsx index a86e576..7bcd29e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,9 +1,3 @@ -import { auth } from '@/auth'; -import { redirect } from 'next/navigation'; - -export default async function Home() { - const session = await auth(); - - if (!session?.user) redirect('/login'); - else redirect('/home'); +export default function Home() { + return
; } diff --git a/src/auth.ts b/src/auth.ts index 09a5065..50b654c 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,49 +1,13 @@ import NextAuth from 'next-auth'; - -import type { Provider } from 'next-auth/providers'; -import Credentials from 'next-auth/providers/credentials'; - import Authentik from 'next-auth/providers/authentik'; -const providers: Provider[] = [ - !process.env.DISABLE_PASSWORD_LOGIN && - Credentials({ - credentials: { password: { label: 'Password', type: 'password' } }, - authorize(c) { - if (c.password !== 'password') return null; - return { - id: 'test', - name: 'Test User', - email: 'test@example.com', - }; - }, - }), - process.env.AUTH_AUTHENTIK_ID && Authentik, -].filter(Boolean) as Provider[]; - -export const providerMap = providers - .map((provider) => { - if (typeof provider === 'function') { - const providerData = provider(); - return { id: providerData.id, name: providerData.name }; - } else { - return { id: provider.id, name: provider.name }; - } - }) - .filter((provider) => provider.id !== 'credentials'); - export const { handlers, signIn, signOut, auth } = NextAuth({ - providers, - session: { - strategy: 'jwt', - }, - pages: { - signIn: '/login', - signOut: '/logout', - }, + providers: [process.env.AUTH_AUTHENTIK_ISSUER ? Authentik : null].filter( + (x) => x !== null, + ), callbacks: { - authorized({ auth }) { - return !!auth?.user; + authorized: async ({ auth }) => { + return !!auth; }, }, }); diff --git a/src/components/labeled-input.tsx b/src/components/labeled-input.tsx index 840d599..1f715a1 100644 --- a/src/components/labeled-input.tsx +++ b/src/components/labeled-input.tsx @@ -17,7 +17,7 @@ export default function LabeledInput({ return (
- + { - 'use server'; - try { - await signIn('credentials', formData); - } catch (error) { - if (error instanceof AuthError) { - return redirect(`${SIGNIN_ERROR_URL}?error=${error.type}`); - } - throw error; - } - }} - > +