mirror of
https://github.com/wasp-lang/wasp.git
synced 2024-12-26 10:35:04 +03:00
Migrate wasp/client/auth API
This commit is contained in:
parent
d650276586
commit
615b373fd6
@ -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) => {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 }> {
|
||||
|
@ -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;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Auth from './Auth'
|
||||
import { type CustomizationOptions, State } from './types'
|
||||
|
||||
// PUBLIC API
|
||||
export function ForgotPasswordForm({
|
||||
appearance,
|
||||
logo,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Auth from './Auth'
|
||||
import { type CustomizationOptions, State } from './types'
|
||||
|
||||
// PUBLIC API
|
||||
export function LoginForm({
|
||||
appearance,
|
||||
logo,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Auth from './Auth'
|
||||
import { type CustomizationOptions, State } from './types'
|
||||
|
||||
// PUBLIC API
|
||||
export function ResetPasswordForm({
|
||||
appearance,
|
||||
logo,
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
State,
|
||||
} from './types'
|
||||
|
||||
// PUBLIC API
|
||||
export function SignupForm({
|
||||
appearance,
|
||||
logo,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Auth from './Auth'
|
||||
import { type CustomizationOptions, State } from './types'
|
||||
|
||||
// PUBLIC API
|
||||
export function VerifyEmailForm({
|
||||
appearance,
|
||||
logo,
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { signup } from '../../../email/actions/signup'
|
||||
import { login } from '../../../email/actions/login'
|
||||
|
||||
// PRIVATE API
|
||||
export function useEmail({
|
||||
onError,
|
||||
showEmailVerificationPending,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { styled } from 'wasp/core/stitches.config'
|
||||
|
||||
// PRIVATE API
|
||||
export const SocialButton = styled('a', {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
|
@ -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()}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import signup from '../../../signup'
|
||||
import login from '../../../login'
|
||||
|
||||
// PRIVATE API
|
||||
export function useUsernameAndPassword({
|
||||
onError,
|
||||
onSuccess,
|
||||
|
@ -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
|
||||
|
@ -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}>
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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)
|
||||
|
@ -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')
|
||||
|
@ -12,6 +12,7 @@ const prismaAdapter = new PrismaAdapter(
|
||||
prisma.{= authEntityLower =} as any
|
||||
);
|
||||
|
||||
// PRIVATE API
|
||||
/**
|
||||
* We are using Lucia for session management.
|
||||
*
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
5
waspc/data/Generator/templates/sdk/client/auth/email.ts
Normal file
5
waspc/data/Generator/templates/sdk/client/auth/email.ts
Normal 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'
|
2
waspc/data/Generator/templates/sdk/client/auth/github.ts
Normal file
2
waspc/data/Generator/templates/sdk/client/auth/github.ts
Normal file
@ -0,0 +1,2 @@
|
||||
// PUBLIC API
|
||||
export { signInUrl as githubSignInUrl } from '../../auth/helpers/Github'
|
2
waspc/data/Generator/templates/sdk/client/auth/google.ts
Normal file
2
waspc/data/Generator/templates/sdk/client/auth/google.ts
Normal file
@ -0,0 +1,2 @@
|
||||
// PUBLIC API
|
||||
export { signInUrl as googleSignInUrl } from '../../auth/helpers/Google'
|
20
waspc/data/Generator/templates/sdk/client/auth/index.ts
Normal file
20
waspc/data/Generator/templates/sdk/client/auth/index.ts
Normal 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'
|
23
waspc/data/Generator/templates/sdk/client/auth/ui.ts
Normal file
23
waspc/data/Generator/templates/sdk/client/auth/ui.ts
Normal 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'
|
@ -0,0 +1,2 @@
|
||||
export { default as login } from '../../auth/login'
|
||||
export { default as signup } from '../../auth/signup'
|
@ -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
|
||||
|
@ -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": {
|
||||
"*": {
|
||||
|
@ -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)
|
||||
|
@ -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 = [
|
||||
|
@ -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 />
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
87
waspc/src/Wasp/Generator/SdkGenerator/Client/AuthG.hs
Normal file
87
waspc/src/Wasp/Generator/SdkGenerator/Client/AuthG.hs
Normal 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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user