Migrate wasp/client/auth API

This commit is contained in:
Mihovil Ilakovac 2024-01-29 16:14:05 +01:00 committed by Filip Sodić
parent d650276586
commit 615b373fd6
44 changed files with 220 additions and 59 deletions

View File

@ -2,7 +2,7 @@
import React from 'react'
import { Redirect } from 'react-router-dom'
import useAuth from 'wasp/auth/useAuth'
import { useAuth } from 'wasp/client/auth'
const createAuthRequiredPage = (Page) => {

View File

@ -2,6 +2,7 @@
import { api, handleApiError } from 'wasp/client/api';
import { initSession } from '../../helpers/user';
// PUBLIC API
export async function login(data: { email: string; password: string }): Promise<void> {
try {
const response = await api.post('{= loginPath =}', data);

View File

@ -1,6 +1,7 @@
{{={= =}=}}
import { api, handleApiError } from 'wasp/client/api';
// PUBLIC API
export async function requestPasswordReset(data: { email: string; }): Promise<{ success: boolean }> {
try {
const response = await api.post('{= requestPasswordResetPath =}', data);
@ -10,6 +11,7 @@ export async function requestPasswordReset(data: { email: string; }): Promise<{
}
}
// PUBLIC API
export async function resetPassword(data: { token: string; password: string; }): Promise<{ success: boolean }> {
try {
const response = await api.post('{= resetPasswordPath =}', data);

View File

@ -1,6 +1,7 @@
{{={= =}=}}
import { api, handleApiError } from 'wasp/client/api';
// PUBLIC API
export async function signup(data: { email: string; password: string }): Promise<{ success: boolean }> {
try {
const response = await api.post('{= signupPath =}', data);

View File

@ -1,6 +1,7 @@
{{={= =}=}}
import { api, handleApiError } from 'wasp/client/api'
// PUBLIC API
export async function verifyEmail(data: {
token: string
}): Promise<{ success: boolean; reason?: string }> {

View File

@ -33,6 +33,7 @@ const HeaderText = styled('h2', {
})
// PRIVATE API
export const AuthContext = createContext({
isLoading: false,
setIsLoading: (isLoading: boolean) => {},
@ -98,4 +99,5 @@ function Auth ({ state, appearance, logo, socialLayout = 'horizontal', additiona
)
}
// PRIVATE API
export default Auth;

View File

@ -1,6 +1,7 @@
import Auth from './Auth'
import { type CustomizationOptions, State } from './types'
// PUBLIC API
export function ForgotPasswordForm({
appearance,
logo,

View File

@ -1,6 +1,7 @@
import Auth from './Auth'
import { type CustomizationOptions, State } from './types'
// PUBLIC API
export function LoginForm({
appearance,
logo,

View File

@ -1,6 +1,7 @@
import Auth from './Auth'
import { type CustomizationOptions, State } from './types'
// PUBLIC API
export function ResetPasswordForm({
appearance,
logo,

View File

@ -5,6 +5,7 @@ import {
State,
} from './types'
// PUBLIC API
export function SignupForm({
appearance,
logo,

View File

@ -1,6 +1,7 @@
import Auth from './Auth'
import { type CustomizationOptions, State } from './types'
// PUBLIC API
export function VerifyEmailForm({
appearance,
logo,

View File

@ -1,15 +1,18 @@
import { styled } from 'wasp/core/stitches.config'
// PRIVATE API
export const Form = styled('form', {
marginTop: '1.5rem',
})
// PUBLIC API
export const FormItemGroup = styled('div', {
'& + div': {
marginTop: '1.5rem',
},
})
// PUBLIC API
export const FormLabel = styled('label', {
display: 'block',
fontSize: '$sm',
@ -48,10 +51,13 @@ const commonInputStyles = {
margin: 0,
}
// PUBLIC API
export const FormInput = styled('input', commonInputStyles)
// PUBLIC API
export const FormTextarea = styled('textarea', commonInputStyles)
// PUBLIC API
export const FormError = styled('div', {
display: 'block',
fontSize: '$sm',
@ -60,6 +66,7 @@ export const FormError = styled('div', {
marginTop: '0.5rem',
})
// PRIVATE API
export const SubmitButton = styled('button', {
display: 'flex',
justifyContent: 'center',

View File

@ -1,5 +1,6 @@
import { styled } from 'wasp/core/stitches.config'
// PRIVATE API
export const Message = styled('div', {
padding: '0.5rem 0.75rem',
borderRadius: '0.375rem',
@ -7,11 +8,13 @@ export const Message = styled('div', {
background: '$gray400',
})
// PRIVATE API
export const MessageError = styled(Message, {
background: '$errorBackground',
color: '$errorText',
})
// PRIVATE API
export const MessageSuccess = styled(Message, {
background: '$successBackground',
color: '$successText',

View File

@ -117,10 +117,12 @@ const gitHubSignInUrl = `${config.apiUrl}{= gitHubSignInPath =}`
// know the exact shape of the form values. We are assuming that the form values
// will be a flat object with string values.
=}
// PRIVATE API
export type LoginSignupFormFields = {
[key: string]: string;
}
// PRIVATE API
export const LoginSignupForm = ({
state,
socialButtonsDirection = 'horizontal',

View File

@ -4,6 +4,7 @@ import { requestPasswordReset } from '../../../email/actions/passwordReset.js'
import { Form, FormItemGroup, FormLabel, FormInput, SubmitButton, FormError } from '../Form'
import { AuthContext } from '../../Auth'
// PRIVATE API
export const ForgotPasswordForm = () => {
const { register, handleSubmit, reset, formState: { errors } } = useForm<{ email: string }>()
const { isLoading, setErrorMessage, setSuccessMessage, setIsLoading } = useContext(AuthContext)

View File

@ -5,6 +5,7 @@ import { useLocation } from 'react-router-dom'
import { Form, FormItemGroup, FormLabel, FormInput, SubmitButton, FormError } from '../Form'
import { AuthContext } from '../../Auth'
// PRIVATE API
export const ResetPasswordForm = () => {
const { register, handleSubmit, reset, formState: { errors } } = useForm<{ password: string; passwordConfirmation: string }>()
const { isLoading, setErrorMessage, setSuccessMessage, setIsLoading } = useContext(AuthContext)

View File

@ -4,6 +4,7 @@ import { verifyEmail } from '../../../email/actions/verifyEmail.js'
import { Message } from '../Message'
import { AuthContext } from '../../Auth'
// PRIVATE API
export const VerifyEmailForm = () => {
const { isLoading, setErrorMessage, setSuccessMessage, setIsLoading } = useContext(AuthContext)
const location = useLocation()

View File

@ -1,6 +1,7 @@
import { signup } from '../../../email/actions/signup'
import { login } from '../../../email/actions/login'
// PRIVATE API
export function useEmail({
onError,
showEmailVerificationPending,

View File

@ -1,5 +1,6 @@
import { styled } from 'wasp/core/stitches.config'
// PRIVATE API
export const SocialButton = styled('a', {
display: 'flex',
justifyContent: 'center',

View File

@ -5,6 +5,7 @@ const defaultStyles = css({
height: '1.25rem',
})
// PRIVATE API
export const Google = () => (
<svg
className={defaultStyles()}
@ -23,6 +24,7 @@ export const Google = () => (
</svg>
)
// PRIVATE API
export const GitHub = () => (
<svg
className={defaultStyles()}

View File

@ -1,6 +1,7 @@
import signup from '../../../signup'
import login from '../../../login'
// PRIVATE API
export function useUsernameAndPassword({
onError,
onSuccess,

View File

@ -3,6 +3,7 @@ import { createTheme } from '@stitches/react'
import { UseFormReturn, RegisterOptions } from 'react-hook-form'
import type { LoginSignupFormFields } from './internal/common/LoginSignupForm'
// PRIVATE API
export enum State {
Login = 'login',
Signup = 'signup',
@ -13,26 +14,31 @@ export enum State {
{=/ isEmailAuthEnabled =}
}
// PUBLIC API
export type CustomizationOptions = {
logo?: string
socialLayout?: 'horizontal' | 'vertical'
appearance?: Parameters<typeof createTheme>[0]
}
// PRIVATE API
export type ErrorMessage = {
title: string
description?: string
}
// PRIVATE API
export type FormState = {
isLoading: boolean
}
// PRIVATE API
export type AdditionalSignupFieldRenderFn = (
hookForm: UseFormReturn<LoginSignupFormFields>,
formState: FormState
) => React.ReactNode
// PRIVATE API
export type AdditionalSignupField = {
name: string
label: string
@ -40,6 +46,7 @@ export type AdditionalSignupField = {
validations?: RegisterOptions<LoginSignupFormFields>
}
// PRIVATE API
export type AdditionalSignupFields =
| (AdditionalSignupField | AdditionalSignupFieldRenderFn)[]
| AdditionalSignupFieldRenderFn

View File

@ -4,8 +4,10 @@ import config from 'wasp/core/config'
import { SocialButton } from '../forms/internal/social/SocialButton'
import * as SocialIcons from '../forms/internal/social/SocialIcons'
// PUBLIC API
export const signInUrl = `${config.apiUrl}{= signInPath =}`
// PUBLIC API
export function SignInButton() {
return (
<SocialButton href={signInUrl}>

View File

@ -1,6 +1,7 @@
import { setSessionId } from 'wasp/client/api'
import { invalidateAndRemoveQueries } from 'wasp/operations/resources'
// PRIVATE API
export async function initSession(sessionId: string): Promise<void> {
setSessionId(sessionId)
// We need to invalidate queries after login in order to get the correct user

View File

@ -1,7 +1,5 @@
export { defineUserSignupFields } from './providers/types.js';
// PUBLIC
export type { AuthUser } from '../server/_types'
// PUBLIC
export { getEmail, getUsername, getFirstProviderUserId, findUserIdentity } from './user.js'

View File

@ -8,5 +8,7 @@ const jwtVerify = util.promisify(jwt.verify)
const JWT_SECRET = config.auth.jwtSecret
// PRIVATE API
export const signData = (data, options) => jwtSign(data, JWT_SECRET, options)
// PRIVATE API
export const verify = (token) => jwtVerify(token, JWT_SECRET)

View File

@ -1,6 +1,7 @@
import { api, removeLocalUserData } from 'wasp/client/api'
import { invalidateAndRemoveQueries } from 'wasp/operations/resources'
// PUBLIC API
export default async function logout(): Promise<void> {
try {
await api.post('/auth/logout')

View File

@ -12,6 +12,7 @@ const prismaAdapter = new PrismaAdapter(
prisma.{= authEntityLower =} as any
);
// PRIVATE API
/**
* We are using Lucia for session management.
*

View File

@ -6,8 +6,10 @@ import { HttpMethod } from 'wasp/types'
import type { AuthUser } from './types'
import { addMetadataToQuery } from 'wasp/rpc/queries'
// PUBLIC API
export const getMe = createUserGetter()
// PUBLIC API
export default function useAuth(queryFnArgs?: unknown, config?: any) {
return useQuery(getMe, queryFnArgs, config)
}

View File

@ -1,13 +1,16 @@
import type { AuthUser, ProviderName, DeserializedAuthIdentity } from './types'
// PUBLIC API
export function getEmail(user: AuthUser): string | null {
return findUserIdentity(user, "email")?.providerUserId ?? null;
}
// PUBLIC API
export function getUsername(user: AuthUser): string | null {
return findUserIdentity(user, "username")?.providerUserId ?? null;
}
// PUBLIC API
export function getFirstProviderUserId(user?: AuthUser): string | null {
if (!user || !user.auth || !user.auth.identities || user.auth.identities.length === 0) {
return null;
@ -16,6 +19,7 @@ export function getFirstProviderUserId(user?: AuthUser): string | null {
return user.auth.identities[0].providerUserId ?? null;
}
// PUBLIC API
export function findUserIdentity(user: AuthUser, providerName: ProviderName): DeserializedAuthIdentity | undefined {
return user.auth.identities.find(
(identity) => identity.providerName === providerName

View File

@ -0,0 +1,5 @@
// PUBLIC API
export { login } from '../../auth/email/actions/login'
export { signup } from '../../auth/email/actions/signup'
export { requestPasswordReset, resetPassword } from '../../auth/email/actions/passwordReset'
export { verifyEmail } from '../../auth/email/actions/verifyEmail'

View File

@ -0,0 +1,2 @@
// PUBLIC API
export { signInUrl as githubSignInUrl } from '../../auth/helpers/Github'

View File

@ -0,0 +1,2 @@
// PUBLIC API
export { signInUrl as googleSignInUrl } from '../../auth/helpers/Google'

View File

@ -0,0 +1,20 @@
{{={= =}=}}
export * from './ui'
{=# isEmailAuthEnabled =}
export * from './email'
{=/ isEmailAuthEnabled =}
{=# isUsernameAndPasswordAuthEnabled =}
export * from './username'
{=/ isUsernameAndPasswordAuthEnabled =}
{=# isGoogleAuthEnabled =}
export * from './google'
{=/ isGoogleAuthEnabled =}
{=# isGithubAuthEnabled =}
export * from './github'
{=/ isGithubAuthEnabled =}
export {
default as useAuth,
getMe,
} from '../../auth/useAuth'
export { default as logout } from '../../auth/logout'

View File

@ -0,0 +1,23 @@
{{={= =}=}}
// PUBLIC API
export { LoginForm } from '../../auth/forms/Login'
export { SignupForm } from '../../auth/forms/Signup'
{=# isEmailAuthEnabled =}
export { ForgotPasswordForm } from '../../auth/forms/ForgotPassword'
export { VerifyEmailForm } from '../../auth/forms/VerifyEmail'
export { ResetPasswordForm } from '../../auth/forms/ResetPassword'
{=/ isEmailAuthEnabled =}
export type { CustomizationOptions } from '../../auth/forms/types'
{=# isGoogleAuthEnabled =}
export { SignInButton as GoogleSignInButton } from '../../auth/helpers/Google'
{=/ isGoogleAuthEnabled =}
{=# isGithubAuthEnabled =}
export { SignInButton as GithubSignInButton } from '../../auth/helpers/Github'
{=/ isGithubAuthEnabled =}
export {
FormError,
FormInput,
FormTextarea,
FormItemGroup,
FormLabel,
} from '../../auth/forms/internal/Form'

View File

@ -0,0 +1,2 @@
export { default as login } from '../../auth/login'
export { default as signup } from '../../auth/signup'

View File

@ -37,16 +37,6 @@
"./rpc/queryClient": "./dist/rpc/queryClient.js",
{=! Used by users, documented. =}
"./types": "./dist/types/index.js",
{=! Used by users, documented. =}
"./auth/login": "./dist/auth/login.js",
{=! Used by users, documented. =}
"./auth/logout": "./dist/auth/logout.js",
{=! Used by users, documented. =}
"./auth/signup": "./dist/auth/signup.js",
{=! Used by users, documented. =}
"./auth/useAuth": "./dist/auth/useAuth.js",
{=! Used by users, documented. =}
"./auth/email": "./dist/auth/email/index.js",
{=! Used by our code, uncodumented (but accessible) for users. =}
"./auth/helpers/user": "./dist/auth/helpers/user.js",
{=! Used by our code, uncodumented (but accessible) for users. =}
@ -61,20 +51,6 @@
"./auth/jwt": "./dist/auth/jwt.js",
{=! Used by user, documented. =}
"./auth/validation": "./dist/auth/validation.js",
{=! Used by users, documented. =}
"./auth/forms/Login": "./dist/auth/forms/Login.jsx",
{=! Used by users, documented. =}
"./auth/forms/Signup": "./dist/auth/forms/Signup.jsx",
{=! Used by users, documented. =}
"./auth/forms/VerifyEmail": "./dist/auth/forms/VerifyEmail.jsx",
{=! Used by users, documented. =}
"./auth/forms/ForgotPassword": "./dist/auth/forms/ForgotPassword.jsx",
{=! Used by users, documented. =}
"./auth/forms/ResetPassword": "./dist/auth/forms/ResetPassword.jsx",
{=! Used by users, documented. =}
"./auth/forms/internal/Form": "./dist/auth/forms/internal/Form.jsx",
{=! Used by users, documented. =}
"./auth/helpers/*": "./dist/auth/helpers/*.jsx",
{=! Used by our code, uncodumented (but accessible) for users. =}
"./auth/pages/createAuthRequiredPage": "./dist/auth/pages/createAuthRequiredPage.jsx",
{=! Used by our framework code (Websockets), undocumented (but accessible) for users. =}
@ -145,7 +121,8 @@
{=! Public: { api } =}
{=! Private: [sdk] =}
"./client/api": "./dist/api/index.js",
"./auth": "./dist/auth/index.js"
"./auth": "./dist/auth/index.js",
"./client/auth": "./dist/client/auth/index.js"
},
{=!
TypeScript doesn't care about the redirects we define above in "exports" field; those

View File

@ -21,11 +21,6 @@
"./rpc/actions/core": "./dist/rpc/actions/core.js",
"./rpc/queryClient": "./dist/rpc/queryClient.js",
"./types": "./dist/types/index.js",
"./auth/login": "./dist/auth/login.js",
"./auth/logout": "./dist/auth/logout.js",
"./auth/signup": "./dist/auth/signup.js",
"./auth/useAuth": "./dist/auth/useAuth.js",
"./auth/email": "./dist/auth/email/index.js",
"./auth/helpers/user": "./dist/auth/helpers/user.js",
"./auth/session": "./dist/auth/session.js",
"./auth/providers/types": "./dist/auth/providers/types.js",
@ -33,13 +28,6 @@
"./auth/password": "./dist/auth/password.js",
"./auth/jwt": "./dist/auth/jwt.js",
"./auth/validation": "./dist/auth/validation.js",
"./auth/forms/Login": "./dist/auth/forms/Login.jsx",
"./auth/forms/Signup": "./dist/auth/forms/Signup.jsx",
"./auth/forms/VerifyEmail": "./dist/auth/forms/VerifyEmail.jsx",
"./auth/forms/ForgotPassword": "./dist/auth/forms/ForgotPassword.jsx",
"./auth/forms/ResetPassword": "./dist/auth/forms/ResetPassword.jsx",
"./auth/forms/internal/Form": "./dist/auth/forms/internal/Form.jsx",
"./auth/helpers/*": "./dist/auth/helpers/*.jsx",
"./auth/pages/createAuthRequiredPage": "./dist/auth/pages/createAuthRequiredPage.jsx",
"./api/events": "./dist/api/events.js",
"./operations": "./dist/operations/index.js",
@ -73,7 +61,8 @@
"./server": "./dist/server/index.js",
"./server/api": "./dist/server/api/index.js",
"./client/api": "./dist/api/index.js",
"./auth": "./dist/auth/index.js"
"./auth": "./dist/auth/index.js",
"./client/auth": "./dist/client/auth/index.js"
},
"typesVersions": {
"*": {

View File

@ -1,6 +1,5 @@
import './Main.css'
import React, { useEffect, FormEventHandler, FormEvent } from 'react'
import logout from 'wasp/auth/logout'
import { useQuery, useAction } from 'wasp/rpc' // Wasp uses a thin wrapper around react-query
import { getTasks } from 'wasp/rpc/queries'
import {
@ -16,8 +15,8 @@ import { Link } from 'react-router-dom'
import { Tasks } from 'wasp/crud/Tasks'
// import login from 'wasp/auth/login'
// import signup from 'wasp/auth/signup'
import useAuth from 'wasp/auth/useAuth'
import { Todo } from './Todo'
import { logout, useAuth } from 'wasp/client/auth'
export const MainPage = ({ user }: { user: AuthUser }) => {
const { data: tasks, isLoading, error } = useQuery(getTasks)

View File

@ -6,7 +6,7 @@ import { getTasks } from 'wasp/rpc/queries'
import { Todo, areThereAnyTasks } from './Todo'
import { MainPage } from './MainPage'
import type { AuthUser } from 'wasp/auth'
import { getMe } from 'wasp/auth/useAuth'
import { getMe } from 'wasp/client/auth'
import { Tasks } from 'wasp/crud/Tasks'
const mockTasks = [

View File

@ -1,13 +1,15 @@
import { ResetPasswordForm } from "wasp/auth/forms/ResetPassword";
import { LoginForm } from "wasp/auth/forms/Login";
import { VerifyEmailForm } from "wasp/auth/forms/VerifyEmail";
import { SignupForm } from "wasp/auth/forms/Signup";
import {
LoginForm,
SignupForm,
VerifyEmailForm,
ResetPasswordForm,
ForgotPasswordForm,
FormError,
FormInput,
FormItemGroup,
FormLabel,
} from "wasp/auth/forms/internal/Form";
} from 'wasp/client/auth'
// import {
// SignInButton as GitHubSignInButton,
// signInUrl as gitHubSignInUrl,
@ -17,8 +19,7 @@ import {
// signInUrl as googleSignInUrl,
// } from "wasp/auth/helpers/Google";
import { ForgotPasswordForm } from "wasp/auth/forms/ForgotPassword";
import { Link, routes } from "wasp/router";
import { Link, routes } from 'wasp/router'
export function SignupPage() {
return (
@ -32,15 +33,15 @@ export function SignupPage() {
<FormItemGroup>
<FormLabel>Address</FormLabel>
<FormInput
{...register("address", {
required: "Address is required",
{...register('address', {
required: 'Address is required',
})}
/>
{errors.address && (
<FormError>{errors.address.message}</FormError>
)}
</FormItemGroup>
);
)
}}
/>
{/* <div style={{ marginTop: "1rem" }}>
@ -55,7 +56,7 @@ export function SignupPage() {
</span>
<span>The link to the login page is {routes.LoginRoute.build()}.</span>
</main>
);
)
}
export function LoginPage() {
@ -70,17 +71,17 @@ export function LoginPage() {
I don't have an account yet (<Link to="/signup">go to signup</Link>).
</span>
</main>
);
)
}
export function RequestPasswordResetPage() {
return <ForgotPasswordForm />;
return <ForgotPasswordForm />
}
export function PasswordResetPage() {
return <ResetPasswordForm />;
return <ResetPasswordForm />
}
export function EmailVerificationPage() {
return <VerifyEmailForm />;
return <VerifyEmailForm />
}

View File

@ -37,6 +37,7 @@ import Wasp.Generator.Job.Process (runNodeCommandAsJob)
import Wasp.Generator.Monad (Generator)
import qualified Wasp.Generator.NpmDependencies as N
import Wasp.Generator.SdkGenerator.AuthG (genAuth)
import Wasp.Generator.SdkGenerator.Client.AuthG (genNewClientAuth)
import qualified Wasp.Generator.SdkGenerator.Common as C
import Wasp.Generator.SdkGenerator.CrudG (genCrud)
import Wasp.Generator.SdkGenerator.EmailSenderG (depsRequiredByEmail, genEmailSender)
@ -112,6 +113,8 @@ genSdkReal spec =
<++> genMiddleware spec
<++> genExportedTypesDir spec
<++> genEmailSender spec
-- New API
<++> genNewClientAuth spec
where
genFileCopy = return . C.mkTmplFd

View File

@ -0,0 +1,87 @@
module Wasp.Generator.SdkGenerator.Client.AuthG
( genNewClientAuth,
)
where
import Data.Aeson (object, (.=))
import qualified Data.Aeson as Aeson
import StrongPath (File', Path', Rel, relfile)
import Wasp.AppSpec (AppSpec)
import qualified Wasp.AppSpec.App as AS.App
import qualified Wasp.AppSpec.App.Auth as AS.Auth
import Wasp.AppSpec.Valid (getApp)
import Wasp.Generator.FileDraft (FileDraft)
import Wasp.Generator.Monad (Generator)
import Wasp.Generator.SdkGenerator.Common (SdkTemplatesDir)
import qualified Wasp.Generator.SdkGenerator.Common as C
import Wasp.Util ((<++>))
genNewClientAuth :: AppSpec -> Generator [FileDraft]
genNewClientAuth spec =
case maybeAuth of
Nothing -> return []
Just auth ->
sequence
[ genAuthIndex auth,
genAuthUI auth
]
<++> genAuthEmail auth
<++> genAuthUsername auth
<++> genAuthGoogle auth
<++> genAuthGitHub auth
where
maybeAuth = AS.App.auth $ snd $ getApp spec
genAuthIndex :: AS.Auth.Auth -> Generator FileDraft
genAuthIndex auth =
return $
C.mkTmplFdWithData
[relfile|client/auth/index.ts|]
tmplData
where
tmplData = getAuthProvidersJson auth
genAuthUI :: AS.Auth.Auth -> Generator FileDraft
genAuthUI auth =
return $
C.mkTmplFdWithData
[relfile|client/auth/ui.ts|]
tmplData
where
tmplData = getAuthProvidersJson auth
genAuthEmail :: AS.Auth.Auth -> Generator [FileDraft]
genAuthEmail auth =
if AS.Auth.isEmailAuthEnabled auth
then sequence [genFileCopy [relfile|client/auth/email.ts|]]
else return []
genAuthUsername :: AS.Auth.Auth -> Generator [FileDraft]
genAuthUsername auth =
if AS.Auth.isUsernameAndPasswordAuthEnabled auth
then sequence [genFileCopy [relfile|client/auth/username.ts|]]
else return []
genAuthGoogle :: AS.Auth.Auth -> Generator [FileDraft]
genAuthGoogle auth =
if AS.Auth.isGoogleAuthEnabled auth
then sequence [genFileCopy [relfile|client/auth/google.ts|]]
else return []
genAuthGitHub :: AS.Auth.Auth -> Generator [FileDraft]
genAuthGitHub auth =
if AS.Auth.isGitHubAuthEnabled auth
then sequence [genFileCopy [relfile|client/auth/github.ts|]]
else return []
getAuthProvidersJson :: AS.Auth.Auth -> Aeson.Value
getAuthProvidersJson auth =
object
[ "isGoogleAuthEnabled" .= AS.Auth.isGoogleAuthEnabled auth,
"isGitHubAuthEnabled" .= AS.Auth.isGitHubAuthEnabled auth,
"isUsernameAndPasswordAuthEnabled" .= AS.Auth.isUsernameAndPasswordAuthEnabled auth,
"isEmailAuthEnabled" .= AS.Auth.isEmailAuthEnabled auth
]
genFileCopy :: Path' (Rel SdkTemplatesDir) File' -> Generator FileDraft
genFileCopy = return . C.mkTmplFd

View File

@ -308,6 +308,7 @@ library
Wasp.Generator.SdkGenerator.EmailSender.Providers
Wasp.Generator.SdkGenerator.WebSocketGenerator
Wasp.Generator.SdkGenerator.RouterGenerator
Wasp.Generator.SdkGenerator.Client.AuthG
Wasp.Generator.ServerGenerator
Wasp.Generator.ServerGenerator.JsImport
Wasp.Generator.ServerGenerator.ApiRoutesG