Vertical auth (#210)

* Vertically organized auth logic.

* Updated opensaas-sh app.

* Updated docs.
This commit is contained in:
Martin Šošić 2024-07-10 16:07:44 +02:00 committed by GitHub
parent 10b7596f1d
commit 138552d541
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 62 additions and 64 deletions

View File

@ -47,25 +47,25 @@
clientRoute: EmailVerificationRoute,
@@ -44,16 +44,14 @@
},
userSignupFields: import { getEmailUserFields } from "@src/server/auth/userSignupFields",
userSignupFields: import { getEmailUserFields } from "@src/auth/userSignupFields",
},
- // Uncomment to enable Google Auth (check https://wasp-lang.dev/docs/auth/social-auth/google for setup instructions):
- // google: { // Guide for setting up Auth via Google
- // userSignupFields: import { getGoogleUserFields } from "@src/server/auth/userSignupFields",
- // configFn: import { getGoogleAuthConfig } from "@src/server/auth/userSignupFields",
- // userSignupFields: import { getGoogleUserFields } from "@src/auth/userSignupFields",
- // configFn: import { getGoogleAuthConfig } from "@src/auth/userSignupFields",
- // },
- // Uncomment to enable GitHub Auth (check https://wasp-lang.dev/docs/auth/social-auth/github for setup instructions):
- // gitHub: {
- // userSignupFields: import { getGitHubUserFields } from "@src/server/auth/userSignupFields",
- // configFn: import { getGitHubAuthConfig } from "@src/server/auth/userSignupFields",
- // userSignupFields: import { getGitHubUserFields } from "@src/auth/userSignupFields",
- // configFn: import { getGitHubAuthConfig } from "@src/auth/userSignupFields",
- // },
+ google: {
+ userSignupFields: import { getGoogleUserFields } from "@src/server/auth/userSignupFields",
+ configFn: import { getGoogleAuthConfig } from "@src/server/auth/userSignupFields",
+ userSignupFields: import { getGoogleUserFields } from "@src/auth/userSignupFields",
+ configFn: import { getGoogleAuthConfig } from "@src/auth/userSignupFields",
+ },
+ gitHub: {
+ userSignupFields: import { getGitHubUserFields } from "@src/server/auth/userSignupFields",
+ configFn: import { getGitHubAuthConfig } from "@src/server/auth/userSignupFields",
+ userSignupFields: import { getGitHubUserFields } from "@src/auth/userSignupFields",
+ configFn: import { getGitHubAuthConfig } from "@src/auth/userSignupFields",
+ },
},
onAuthFailedRedirectTo: "/login",

View File

@ -1,14 +1,13 @@
--- template/app/src/client/auth/LoginPage.tsx
+++ opensaas-sh/app/src/client/auth/LoginPage.tsx
@@ -1,8 +1,15 @@
-import { LoginForm } from 'wasp/client/auth';
--- template/app/src/auth/LoginPage.tsx
+++ opensaas-sh/app/src/auth/LoginPage.tsx
@@ -1,8 +1,14 @@
-import { Link } from 'react-router-dom';
+import { LoginForm, useAuth } from 'wasp/client/auth';
-import { LoginForm } from 'wasp/client/auth';
+import { Redirect, Link } from 'react-router-dom';
import { AuthWrapper } from './authWrapper';
+import { LoginForm, useAuth } from 'wasp/client/auth';
import { AuthPageLayout } from './AuthPageLayout';
export default function Login() {
+
+ const { data: user } = useAuth();
+
+ if (user) {
@ -16,5 +15,5 @@
+ }
+
return (
<AuthWrapper>
<AuthPageLayout>
<LoginForm />

View File

@ -20,7 +20,7 @@ Setting up your app's authentication is easy with Wasp. In fact, it's already se
},
```
The great part is, by defining your auth config in the `main.wasp` file, Wasp manages most of the Auth process for you, including the auth-related database entities for user credentials and sessions, as well as auto-generated client components for your app on the fly (aka AuthUI -- you can see them in the `src/client/auth` folder).
The great part is, by defining your auth config in the `main.wasp` file, Wasp manages most of the Auth process for you, including the auth-related database entities for user credentials and sessions, as well as auto-generated client components for your app on the fly (aka AuthUI -- you can see them in use in the `src/auth` folder).
## Email Verified Auth

View File

@ -62,6 +62,7 @@ If you are using a version of the OpenSaaS template with Wasp `v0.11.x` or below
│   ├── client/ # Your client code (React) goes here.
│   ├── server/ # Your server code (NodeJS) goes here.
│   ├── shared/ # Your shared (runtime independent) code goes here.
│   ├── auth/ # All auth-related pages/components and logic.
│   ├── file-upload/ # Logic for uploading files to S3.
│   └── .waspignore
├── .env.server # Dev environment variables for your server code.
@ -109,7 +110,6 @@ The `src/client` folder contains the code that runs in the browser. It's a stand
└── client
   ├── admin # Admin dashboard pages and components
  ├── app # Your user-facing app that sits behind the paywall/login.
  ├── auth # All auth-related pages and components.
  ├── components # Your shared React components.
  ├── hooks # Your shared React hooks.
   ├── landing-page # Landing page related code
@ -127,7 +127,6 @@ All you have to do is define your server-side functions in the `main.wasp` file,
```sh
└── server
   ├── auth # Some small auth-related functions to customize the auth flow.
  ├── payments # Payments utility functions.
  ├── scripts # Scripts to run via Wasp, e.g. database seeding.
  ├── webhooks # The webhook handler for Stripe.

View File

@ -36,23 +36,23 @@ app OpenSaaS {
},
emailVerification: {
clientRoute: EmailVerificationRoute,
getEmailContentFn: import { getVerificationEmailContent } from "@src/server/auth/email",
getEmailContentFn: import { getVerificationEmailContent } from "@src/auth/email-and-pass/emails",
},
passwordReset: {
clientRoute: PasswordResetRoute,
getEmailContentFn: import { getPasswordResetEmailContent } from "@src/server/auth/email",
getEmailContentFn: import { getPasswordResetEmailContent } from "@src/auth/email-and-pass/emails",
},
userSignupFields: import { getEmailUserFields } from "@src/server/auth/userSignupFields",
userSignupFields: import { getEmailUserFields } from "@src/auth/userSignupFields",
},
// Uncomment to enable Google Auth (check https://wasp-lang.dev/docs/auth/social-auth/google for setup instructions):
// google: { // Guide for setting up Auth via Google
// userSignupFields: import { getGoogleUserFields } from "@src/server/auth/userSignupFields",
// configFn: import { getGoogleAuthConfig } from "@src/server/auth/userSignupFields",
// userSignupFields: import { getGoogleUserFields } from "@src/auth/userSignupFields",
// configFn: import { getGoogleAuthConfig } from "@src/auth/userSignupFields",
// },
// Uncomment to enable GitHub Auth (check https://wasp-lang.dev/docs/auth/social-auth/github for setup instructions):
// gitHub: {
// userSignupFields: import { getGitHubUserFields } from "@src/server/auth/userSignupFields",
// configFn: import { getGitHubAuthConfig } from "@src/server/auth/userSignupFields",
// userSignupFields: import { getGitHubUserFields } from "@src/auth/userSignupFields",
// configFn: import { getGitHubAuthConfig } from "@src/auth/userSignupFields",
// },
},
onAuthFailedRedirectTo: "/login",
@ -197,27 +197,27 @@ page LandingPage {
//#region Auth Pages
route LoginRoute { path: "/login", to: LoginPage }
page LoginPage {
component: import Login from "@src/client/auth/LoginPage"
component: import Login from "@src/auth/LoginPage"
}
route SignupRoute { path: "/signup", to: SignupPage }
page SignupPage {
component: import { Signup } from "@src/client/auth/SignupPage"
component: import { Signup } from "@src/auth/SignupPage"
}
route RequestPasswordResetRoute { path: "/request-password-reset", to: RequestPasswordResetPage }
page RequestPasswordResetPage {
component: import { RequestPasswordReset } from "@src/client/auth/RequestPasswordReset",
component: import { RequestPasswordResetPage } from "@src/auth/email-and-pass/RequestPasswordResetPage",
}
route PasswordResetRoute { path: "/password-reset", to: PasswordResetPage }
page PasswordResetPage {
component: import { PasswordReset } from "@src/client/auth/PasswordReset",
component: import { PasswordResetPage } from "@src/auth/email-and-pass/PasswordResetPage",
}
route EmailVerificationRoute { path: "/email-verification", to: EmailVerificationPage }
page EmailVerificationPage {
component: import { EmailVerification } from "@src/client/auth/EmailVerification",
component: import { EmailVerificationPage } from "@src/auth/email-and-pass/EmailVerificationPage",
}
//#endregion

View File

@ -1,6 +1,6 @@
import { ReactNode } from 'react';
export function AuthWrapper({children} : {children: ReactNode }) {
export function AuthPageLayout({children} : {children: ReactNode }) {
return (
<div className='flex min-h-full flex-col justify-center pt-10 sm:px-6 lg:px-8'>
<div className='sm:mx-auto sm:w-full sm:max-w-md'>

View File

@ -1,10 +1,10 @@
import { LoginForm } from 'wasp/client/auth';
import { Link } from 'react-router-dom';
import { AuthWrapper } from './authWrapper';
import { LoginForm } from 'wasp/client/auth';
import { AuthPageLayout } from './AuthPageLayout';
export default function Login() {
return (
<AuthWrapper>
<AuthPageLayout>
<LoginForm />
<br />
<span className='text-sm font-medium text-gray-900 dark:text-gray-900'>
@ -22,6 +22,6 @@ export default function Login() {
</Link>
.
</span>
</AuthWrapper>
</AuthPageLayout>
);
}

View File

@ -1,10 +1,10 @@
import { SignupForm } from 'wasp/client/auth';
import { Link } from 'react-router-dom';
import { AuthWrapper } from './authWrapper';
import { SignupForm } from 'wasp/client/auth';
import { AuthPageLayout } from './AuthPageLayout';
export function Signup() {
return (
<AuthWrapper>
<AuthPageLayout>
<SignupForm />
<br />
<span className='text-sm font-medium text-gray-900'>
@ -15,6 +15,6 @@ export function Signup() {
).
</span>
<br />
</AuthWrapper>
</AuthPageLayout>
);
}

View File

@ -1,15 +1,15 @@
import { VerifyEmailForm } from 'wasp/client/auth';
import { Link } from 'react-router-dom';
import { AuthWrapper } from './authWrapper';
import { VerifyEmailForm } from 'wasp/client/auth';
import { AuthPageLayout } from '../AuthPageLayout';
export function EmailVerification() {
export function EmailVerificationPage() {
return (
<AuthWrapper>
<AuthPageLayout>
<VerifyEmailForm />
<br />
<span className='text-sm font-medium text-gray-900'>
If everything is okay, <Link to='/login' className='underline'>go to login</Link>
</span>
</AuthWrapper>
</AuthPageLayout>
);
}

View File

@ -1,15 +1,15 @@
import { ResetPasswordForm } from 'wasp/client/auth';
import { Link } from 'react-router-dom';
import { AuthWrapper } from './authWrapper';
import { ResetPasswordForm } from 'wasp/client/auth';
import { AuthPageLayout } from '../AuthPageLayout';
export function PasswordReset() {
export function PasswordResetPage() {
return (
<AuthWrapper>
<AuthPageLayout>
<ResetPasswordForm />
<br />
<span className='text-sm font-medium text-gray-900'>
If everything is okay, <Link to='/login'>go to login</Link>
</span>
</AuthWrapper>
</AuthPageLayout>
);
}

View File

@ -0,0 +1,10 @@
import { ForgotPasswordForm } from 'wasp/client/auth';
import { AuthPageLayout } from '../AuthPageLayout';
export function RequestPasswordResetPage() {
return (
<AuthPageLayout>
<ForgotPasswordForm />
</AuthPageLayout>
);
}

View File

@ -1,4 +1,4 @@
import { type GetVerificationEmailContentFn, type GetPasswordResetEmailContentFn } from "wasp/server/auth";
import { type GetVerificationEmailContentFn, type GetPasswordResetEmailContentFn } from 'wasp/server/auth';
export const getVerificationEmailContent: GetVerificationEmailContentFn = ({ verificationLink }) => ({
subject: 'Verify your email',
@ -16,4 +16,4 @@ export const getPasswordResetEmailContent: GetPasswordResetEmailContentFn = ({ p
<p>Click the link below to reset your password</p>
<a href="${passwordResetLink}">Reset password</a>
`,
});
});

View File

@ -1,5 +1,5 @@
import { defineUserSignupFields } from 'wasp/auth/providers/types';
import { z } from 'zod';
import { defineUserSignupFields } from 'wasp/auth/providers/types';
const adminEmails = process.env.ADMIN_EMAILS?.split(',') || [];

View File

@ -1,10 +0,0 @@
import { ForgotPasswordForm } from 'wasp/client/auth';
import { AuthWrapper } from './authWrapper';
export function RequestPasswordReset() {
return (
<AuthWrapper>
<ForgotPasswordForm />
</AuthWrapper>
);
}