Revert "issue-129 Add custom auth ui/ux"
This reverts commit fc4906757a.
This commit is contained in:
@@ -18,7 +18,7 @@ export const handler = async (req, _context) => {
|
|||||||
email: 'k.hutten@protonmail.ch',
|
email: 'k.hutten@protonmail.ch',
|
||||||
confirmation_sent_at: '2020-10-19T18:09:01Z',
|
confirmation_sent_at: '2020-10-19T18:09:01Z',
|
||||||
app_metadata: { provider: 'email' },
|
app_metadata: { provider: 'email' },
|
||||||
user_metadata: { full_name: 'sick_dog', userName: 'hi bob' },
|
user_metadata: { full_name: 'sick_dog' },
|
||||||
created_at: '2020-10-19T18:09:01Z',
|
created_at: '2020-10-19T18:09:01Z',
|
||||||
updated_at: '2020-10-19T18:09:01Z'
|
updated_at: '2020-10-19T18:09:01Z'
|
||||||
}
|
}
|
||||||
@@ -62,12 +62,12 @@ export const handler = async (req, _context) => {
|
|||||||
db.user.findOne({
|
db.user.findOne({
|
||||||
where: { userName: seed },
|
where: { userName: seed },
|
||||||
})
|
})
|
||||||
const userNameSeed = enforceAlphaNumeric(user?.user_metadata?.userName)
|
const userNameSeed = enforceAlphaNumeric(email.split('@')[0])
|
||||||
const userName = await generateUniqueString(userNameSeed, isUniqueCallback) // TODO maybe come up with a better default userName?
|
const userName = await generateUniqueString(userNameSeed, isUniqueCallback) // TODO maybe come up with a better default userName?
|
||||||
const input = {
|
const input = {
|
||||||
email,
|
email,
|
||||||
userName,
|
userName,
|
||||||
name: user?.user_metadata?.full_name,
|
name: user.user_metadata && user.user_metadata.full_name,
|
||||||
id: user.id,
|
id: user.id,
|
||||||
}
|
}
|
||||||
await createUserInsecure({ input })
|
await createUserInsecure({ input })
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ import { AuthenticationError, ForbiddenError, parseJWT } from '@redwoodjs/api'
|
|||||||
* return await db.user.findOne({ where: { decoded.email } })
|
* return await db.user.findOne({ where: { decoded.email } })
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @example - User info is contained in the decoded token and roles extracted
|
* @example - User info is conatined in the decoded token and roles extracted
|
||||||
*
|
*
|
||||||
* export const getCurrentUser = async (decoded, { _token, _type }) => {
|
* export const getCurrentUser = async (decoded, { _token, _type }) => {
|
||||||
* return { ...decoded, roles: parseJWT({ decoded }).roles }
|
* return { ...decoded, roles: parseJWT({ decoded }).roles }
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
port = 8910
|
port = 8910
|
||||||
apiProxyPath = "/.netlify/functions"
|
apiProxyPath = "/.netlify/functions"
|
||||||
includeEnvironmentVariables = ['GOOGLE_ANALYTICS_ID']
|
includeEnvironmentVariables = ['GOOGLE_ANALYTICS_ID']
|
||||||
experimentalFastRefresh = true
|
|
||||||
[api]
|
[api]
|
||||||
port = 8911
|
port = 8911
|
||||||
[browser]
|
[browser]
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"event": "signup",
|
|
||||||
"instance_id": "403b7d63-17f9-48f1-a85f-3d6b41c7dad1",
|
|
||||||
"user": {
|
|
||||||
"id": "641222ee-3e61-4253-8c11-9f764779bcc5",
|
|
||||||
"aud": "",
|
|
||||||
"role": "",
|
|
||||||
"email": "k.hutten2@protonmail.ch",
|
|
||||||
"confirmation_sent_at": "2020-10-19T18:09:01Z",
|
|
||||||
"app_metadata": { "provider": "email" },
|
|
||||||
"user_metadata": { "full_name": "sick_dog", "userName": "hi bob" },
|
|
||||||
"created_at": "2020-10-19T18:09:01Z",
|
|
||||||
"updated_at": "2020-10-19T18:09:01Z"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material-ui/core": "^4.11.0",
|
"@material-ui/core": "^4.11.0",
|
||||||
"@redwoodjs/auth": "^0.21.0",
|
"@redwoodjs/auth": "^0.20.0",
|
||||||
"@redwoodjs/forms": "^0.20.0",
|
"@redwoodjs/forms": "^0.20.0",
|
||||||
"@redwoodjs/router": "^0.20.0",
|
"@redwoodjs/router": "^0.20.0",
|
||||||
"@redwoodjs/web": "^0.20.0",
|
"@redwoodjs/web": "^0.20.0",
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
"controlkit": "^0.1.9",
|
"controlkit": "^0.1.9",
|
||||||
"get-active-classes": "^0.0.11",
|
"get-active-classes": "^0.0.11",
|
||||||
"golden-layout": "^1.5.9",
|
"golden-layout": "^1.5.9",
|
||||||
"gotrue-js": "^0.9.27",
|
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
"monaco-editor": "^0.20.0",
|
"monaco-editor": "^0.20.0",
|
||||||
"monaco-editor-webpack-plugin": "^1.9.1",
|
"monaco-editor-webpack-plugin": "^1.9.1",
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ const Routes = () => {
|
|||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<Route path="/account-recovery/update-password" page={UpdatePasswordPage} name="updatePassword" />
|
|
||||||
{/* <Route path="/account-recovery/update-password/{recoveryToken}" page={UpdatePasswordPage} name="updatePassword" /> */}
|
|
||||||
<Route path="/account-recovery" page={AccountRecoveryPage} name="accountRecovery" />
|
|
||||||
<Route path="/" page={PartsPage} name="home" />
|
<Route path="/" page={PartsPage} name="home" />
|
||||||
<Route notfound page={NotFoundPage} />
|
<Route notfound page={NotFoundPage} />
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const InputText = ({ value, isEditable, onChange, className }) => {
|
|||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="absolute inset-0 mb-2 rounded bg-gray-200 shadow-inners" />
|
<div className="absolute inset-0 mb-2 rounded bg-gray-200 shadow-inner bg-gray-100" />
|
||||||
<input
|
<input
|
||||||
className="pl-2 pt-1 text-indigo-800 font-medium mb-px pb-px bg-transparent relative"
|
className="pl-2 pt-1 text-indigo-800 font-medium mb-px pb-px bg-transparent relative"
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
import { getActiveClasses } from 'get-active-classes'
|
|
||||||
import { TextField, FieldError } from '@redwoodjs/forms'
|
|
||||||
import { useFormContext } from 'react-hook-form'
|
|
||||||
|
|
||||||
// COPY of InputText but using TextField for use with redwood forms. Maybe I should combine them back into one or otherwise try and share code between these two.
|
|
||||||
|
|
||||||
const InputText = ({ type = 'text', className, name, validation }) => {
|
|
||||||
const { errors } = useFormContext()
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className={getActiveClasses('relative inline-block', className)}>
|
|
||||||
<FieldError
|
|
||||||
className="absolute -my-4 text-sm text-red-500 font-ropa-sans"
|
|
||||||
name={name}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className={getActiveClasses(
|
|
||||||
'absolute inset-0 mb-2 rounded bg-gray-200 shadow-inner',
|
|
||||||
{ 'border border-red-500': errors[name] }
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
className={getActiveClasses(
|
|
||||||
'pl-2 pt-1 text-indigo-800 font-medium mb-px pb-px bg-transparent relative w-full'
|
|
||||||
)}
|
|
||||||
name={name}
|
|
||||||
readOnly={false}
|
|
||||||
type={type}
|
|
||||||
validation={validation}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default InputText
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import InputTextForm from './InputTextForm'
|
|
||||||
|
|
||||||
export const generated = () => {
|
|
||||||
return <InputTextForm />
|
|
||||||
}
|
|
||||||
|
|
||||||
export default { title: 'Components/InputTextForm' }
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { render } from '@redwoodjs/testing'
|
|
||||||
|
|
||||||
import InputTextForm from './InputTextForm'
|
|
||||||
|
|
||||||
describe('InputTextForm', () => {
|
|
||||||
it('renders successfully', () => {
|
|
||||||
expect(() => {
|
|
||||||
render(<InputTextForm />)
|
|
||||||
}).not.toThrow()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -7,18 +7,17 @@ import {
|
|||||||
} from './mockEditorParts'
|
} from './mockEditorParts'
|
||||||
import Svg from 'src/components/Svg'
|
import Svg from 'src/components/Svg'
|
||||||
import OutBound from 'src/components/OutBound'
|
import OutBound from 'src/components/OutBound'
|
||||||
|
import { useAuth } from '@redwoodjs/auth'
|
||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
import LoginModal from 'src/components/LoginModal'
|
|
||||||
import { useState } from 'react'
|
|
||||||
|
|
||||||
const LandingSection = () => {
|
const LandingSection = () => {
|
||||||
const [isLoginModalOpen, setIsLoginModalOpen] = useState(false)
|
const { logIn } = useAuth()
|
||||||
const recordedLogin = async () => {
|
const recordedLogin = () => {
|
||||||
ReactGA.event({
|
ReactGA.event({
|
||||||
category: 'login',
|
category: 'login',
|
||||||
action: 'landing section CTA',
|
action: 'landing section CTA',
|
||||||
})
|
})
|
||||||
setIsLoginModalOpen(true)
|
logIn()
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="mt-16">
|
<div className="mt-16">
|
||||||
@@ -164,12 +163,10 @@ const LandingSection = () => {
|
|||||||
with more integrations coming soon.
|
with more integrations coming soon.
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
className="bg-texture bg-purple-800 text-center w-full py-6 rounded-b-md border border-indigo-300 border-opacity-0 hover:border-opacity-100 hover:shadow-xl"
|
className="font-bold text-2xl bg-texture bg-purple-800 text-center w-full py-6 rounded-b-md border border-indigo-300 border-opacity-0 hover:border-opacity-100 hover:shadow-xl"
|
||||||
onClick={recordedLogin}
|
onClick={recordedLogin}
|
||||||
>
|
>
|
||||||
<span className="font-bold text-2xl text-indigo-200">
|
<span className="text-indigo-200">Start Hacking Now</span>
|
||||||
Start Hacking Now
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -182,11 +179,6 @@ const LandingSection = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<LoginModal
|
|
||||||
open={isLoginModalOpen}
|
|
||||||
onClose={() => setIsLoginModalOpen(false)}
|
|
||||||
shouldStartWithSignup
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,183 +0,0 @@
|
|||||||
import { useState } from 'react'
|
|
||||||
import Dialog from '@material-ui/core/Dialog'
|
|
||||||
import Tab from '@material-ui/core/Tab'
|
|
||||||
import Tabs from '@material-ui/core/Tabs'
|
|
||||||
import InputTextForm from 'src/components/InputTextForm'
|
|
||||||
import OutBound from 'src/components/OutBound'
|
|
||||||
import { Form, Submit } from '@redwoodjs/forms'
|
|
||||||
import { useAuth } from '@redwoodjs/auth'
|
|
||||||
import { Link, routes } from '@redwoodjs/router'
|
|
||||||
|
|
||||||
const LoginModal = ({ open, onClose, shouldStartWithSignup = false }) => {
|
|
||||||
const { logIn, signUp } = useAuth()
|
|
||||||
|
|
||||||
const [tab, setTab] = useState(shouldStartWithSignup ? 0 : 1)
|
|
||||||
const onTabChange = (_, newValue) => {
|
|
||||||
setTab(newValue)
|
|
||||||
setError('')
|
|
||||||
}
|
|
||||||
const [checkBox, setCheckBox] = useState(true)
|
|
||||||
const [error, setError] = useState('')
|
|
||||||
|
|
||||||
const onSubmitSignUp = async ({ email, password, name, userName }) => {
|
|
||||||
try {
|
|
||||||
setError('')
|
|
||||||
await signUp({
|
|
||||||
email,
|
|
||||||
password,
|
|
||||||
remember: { full_name: name, userName },
|
|
||||||
})
|
|
||||||
onClose()
|
|
||||||
} catch (errorEvent) {
|
|
||||||
setError(errorEvent?.json?.error_description)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const onSubmitSignIn = async ({ email, password }) => {
|
|
||||||
try {
|
|
||||||
setError('')
|
|
||||||
await logIn({ email, password, remember: true })
|
|
||||||
onClose()
|
|
||||||
} catch (errorEvent) {
|
|
||||||
setError(errorEvent?.json?.error_description)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Dialog open={open} onClose={onClose}>
|
|
||||||
<div className="bg-gray-100 max-w-2xl rounded-lg shadow-lg">
|
|
||||||
<Tabs
|
|
||||||
value={tab}
|
|
||||||
onChange={onTabChange}
|
|
||||||
centered
|
|
||||||
textColor="primary"
|
|
||||||
indicatorColor="primary"
|
|
||||||
>
|
|
||||||
<Tab label="Sign Up" />
|
|
||||||
<Tab label="Sign In" />
|
|
||||||
</Tabs>
|
|
||||||
{error && (
|
|
||||||
<div className="text-sm text-red-500 font-ropa-sans pt-4 text-center">
|
|
||||||
{error}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{tab === 0 ? (
|
|
||||||
<SignUpForm
|
|
||||||
onSubmitSignUp={onSubmitSignUp}
|
|
||||||
checkBox={checkBox}
|
|
||||||
setCheckBox={setCheckBox}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<SignInForm onSubmitSignIn={onSubmitSignIn} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Dialog>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const Field = ({ name, type = 'text', validation }) => (
|
|
||||||
<>
|
|
||||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
|
||||||
{name}:
|
|
||||||
</span>
|
|
||||||
<InputTextForm
|
|
||||||
type={type}
|
|
||||||
className="text-xl"
|
|
||||||
name={name}
|
|
||||||
validation={validation}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
const HeroButton = ({ text }) => (
|
|
||||||
<Submit className="bg-texture bg-purple-800 py-6 w-full flex items-center justify-center rounded-b border border-indigo-300 border-opacity-0 hover:border-opacity-100 hover:shadow-xl">
|
|
||||||
<span className="font-bold text-2xl text-indigo-200">{text}</span>
|
|
||||||
</Submit>
|
|
||||||
)
|
|
||||||
|
|
||||||
const SignInForm = ({ onSubmitSignIn }) => (
|
|
||||||
<Form className="w-full" onSubmit={onSubmitSignIn}>
|
|
||||||
<div className="p-8">
|
|
||||||
<div
|
|
||||||
className="grid items-center gap-2"
|
|
||||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
name="email"
|
|
||||||
validation={{
|
|
||||||
required: true,
|
|
||||||
pattern: {
|
|
||||||
value: /[^@]+@[^.]+\..+/,
|
|
||||||
message: 'please enter a valid email address',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Field
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
validation={{ required: true }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Link
|
|
||||||
to={routes.accountRecovery()}
|
|
||||||
className="underline text-sm text-gray-500 block text-center"
|
|
||||||
>
|
|
||||||
forgot your password?
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
<HeroButton text="Sign In" />
|
|
||||||
</Form>
|
|
||||||
)
|
|
||||||
|
|
||||||
const SignUpForm = ({ onSubmitSignUp, checkBox, setCheckBox }) => (
|
|
||||||
<Form className="w-full" onSubmit={onSubmitSignUp}>
|
|
||||||
<div className="p-8">
|
|
||||||
<div
|
|
||||||
className="grid items-center gap-2"
|
|
||||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
|
||||||
>
|
|
||||||
<Field name="name" validation={{ required: true }} />
|
|
||||||
<Field
|
|
||||||
name="userName"
|
|
||||||
validation={{
|
|
||||||
required: true,
|
|
||||||
pattern: {
|
|
||||||
value: /^[a-zA-Z0-9-_]+$/,
|
|
||||||
message: 'Only alphanumeric and dash characters allowed',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Field
|
|
||||||
name="email"
|
|
||||||
validation={{
|
|
||||||
required: true,
|
|
||||||
pattern: {
|
|
||||||
value: /[^@]+@[^.]+\..+/,
|
|
||||||
message: 'please enter a valid email address',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Field
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
validation={{ required: true }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex pt-4">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={checkBox}
|
|
||||||
onChange={() => setCheckBox(!checkBox)}
|
|
||||||
/>{' '}
|
|
||||||
<span className="pl-4 text-gray-500 text-sm max-w-sm">
|
|
||||||
Stay up-to-date with CadHub's progress with the founder's (
|
|
||||||
<OutBound className="underline" to="https://twitter.com/IrevDev">
|
|
||||||
Kurt's
|
|
||||||
</OutBound>
|
|
||||||
) newsletter
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<HeroButton text="Sign Up" />
|
|
||||||
</Form>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default LoginModal
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import LoginModal from './LoginModal'
|
|
||||||
|
|
||||||
export const generated = () => {
|
|
||||||
return <LoginModal open={true} />
|
|
||||||
}
|
|
||||||
|
|
||||||
export default { title: 'Components/LoginModal' }
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { render } from '@redwoodjs/testing'
|
|
||||||
|
|
||||||
import LoginModal from './LoginModal'
|
|
||||||
|
|
||||||
describe('LoginModal', () => {
|
|
||||||
it('renders successfully', () => {
|
|
||||||
expect(() => {
|
|
||||||
render(<LoginModal />)
|
|
||||||
}).not.toThrow()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { AuthProvider } from '@redwoodjs/auth'
|
import { AuthProvider } from '@redwoodjs/auth'
|
||||||
import GoTrue from 'gotrue-js'
|
import netlifyIdentity from 'netlify-identity-widget'
|
||||||
|
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { RedwoodProvider, FatalErrorBoundary } from '@redwoodjs/web'
|
import { RedwoodProvider, FatalErrorBoundary } from '@redwoodjs/web'
|
||||||
import FatalErrorPage from 'src/pages/FatalErrorPage'
|
import FatalErrorPage from 'src/pages/FatalErrorPage'
|
||||||
@@ -17,6 +16,8 @@ import './cascade/css/main.css'
|
|||||||
import 'monaco-editor/min/vs/editor/editor.main.css'
|
import 'monaco-editor/min/vs/editor/editor.main.css'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
|
|
||||||
|
netlifyIdentity.init()
|
||||||
|
|
||||||
function initCascadeStudio() {
|
function initCascadeStudio() {
|
||||||
// if ('serviceWorker' in navigator) {
|
// if ('serviceWorker' in navigator) {
|
||||||
// navigator.serviceWorker.register('service-worker.js').then(function(registration) {
|
// navigator.serviceWorker.register('service-worker.js').then(function(registration) {
|
||||||
@@ -48,14 +49,9 @@ function initCascadeStudio() {
|
|||||||
}
|
}
|
||||||
initCascadeStudio()
|
initCascadeStudio()
|
||||||
|
|
||||||
const goTrueClient = new GoTrue({
|
|
||||||
APIUrl: 'https://cadhub.xyz/.netlify/identity',
|
|
||||||
setCookie: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<FatalErrorBoundary page={FatalErrorPage}>
|
<FatalErrorBoundary page={FatalErrorPage}>
|
||||||
<AuthProvider client={goTrueClient} type="goTrue">
|
<AuthProvider client={netlifyIdentity} type="netlify">
|
||||||
<RedwoodProvider>
|
<RedwoodProvider>
|
||||||
<Routes />
|
<Routes />
|
||||||
</RedwoodProvider>
|
</RedwoodProvider>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { Link, routes, navigate } from '@redwoodjs/router'
|
import { Link, routes } from '@redwoodjs/router'
|
||||||
import { useAuth } from '@redwoodjs/auth'
|
import { useAuth } from '@redwoodjs/auth'
|
||||||
import { Flash, useQuery, useFlash } from '@redwoodjs/web'
|
import { Flash } from '@redwoodjs/web'
|
||||||
import Tooltip from '@material-ui/core/Tooltip'
|
import Tooltip from '@material-ui/core/Tooltip'
|
||||||
|
import { useQuery } from '@redwoodjs/web'
|
||||||
import Popover from '@material-ui/core/Popover'
|
import Popover from '@material-ui/core/Popover'
|
||||||
import { getActiveClasses } from 'get-active-classes'
|
import { getActiveClasses } from 'get-active-classes'
|
||||||
import { useLocation } from '@redwoodjs/router'
|
import { useLocation } from '@redwoodjs/router'
|
||||||
import LoginModal from 'src/components/LoginModal'
|
|
||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
|
|
||||||
export const QUERY = gql`
|
export const QUERY = gql`
|
||||||
@@ -26,13 +26,11 @@ let previousSubmission = ''
|
|||||||
let previousUserID = ''
|
let previousUserID = ''
|
||||||
|
|
||||||
const MainLayout = ({ children }) => {
|
const MainLayout = ({ children }) => {
|
||||||
const { logOut, isAuthenticated, currentUser, client } = useAuth()
|
const { logIn, logOut, isAuthenticated, currentUser } = useAuth()
|
||||||
const { addMessage } = useFlash()
|
|
||||||
const { data, loading } = useQuery(QUERY, {
|
const { data, loading } = useQuery(QUERY, {
|
||||||
skip: !currentUser?.sub,
|
skip: !currentUser?.sub,
|
||||||
variables: { id: currentUser?.sub },
|
variables: { id: currentUser?.sub },
|
||||||
})
|
})
|
||||||
const [isLoginModalOpen, setIsLoginModalOpen] = useState(false)
|
|
||||||
const [isOpen, setIsOpen] = useState(false)
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
const [anchorEl, setAnchorEl] = useState(null)
|
const [anchorEl, setAnchorEl] = useState(null)
|
||||||
const [popoverId, setPopoverId] = useState(undefined)
|
const [popoverId, setPopoverId] = useState(undefined)
|
||||||
@@ -61,7 +59,7 @@ const MainLayout = ({ children }) => {
|
|||||||
category: 'login',
|
category: 'login',
|
||||||
action: 'navbar login',
|
action: 'navbar login',
|
||||||
})
|
})
|
||||||
setIsLoginModalOpen(true)
|
logIn()
|
||||||
}
|
}
|
||||||
|
|
||||||
const { pathname, params } = useLocation()
|
const { pathname, params } = useLocation()
|
||||||
@@ -87,38 +85,6 @@ const MainLayout = ({ children }) => {
|
|||||||
previousUserID = currentUser
|
previousUserID = currentUser
|
||||||
}
|
}
|
||||||
}, [data, currentUser, isAuthenticated])
|
}, [data, currentUser, isAuthenticated])
|
||||||
const hash = window.location.hash
|
|
||||||
useEffect(() => {
|
|
||||||
const [key, token] = hash.slice(1).split('=')
|
|
||||||
if (key === 'confirmation_token') {
|
|
||||||
console.log('confirming with', token)
|
|
||||||
client
|
|
||||||
.confirm(token, true)
|
|
||||||
.then(() => {
|
|
||||||
addMessage('Email confirmed', { classes: 'rw-flash-success' })
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
addMessage('Problem confirming email', {
|
|
||||||
classes: 'bg-red-300 text-red-900',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else if (key === 'recovery_token') {
|
|
||||||
// http://localhost:8910/#recovery_token=LwsC-KpgmiDwGo-ZcGH0tA
|
|
||||||
// https://mandrillapp.com/track/click/31128206/cadhub.xyz?p=eyJzIjoiWFlFbDk5YTVYU0FOSmEtZ3ZtUXlDSW13QURrIiwidiI6MSwicCI6IntcInVcIjozMTEyODIwNixcInZcIjoxLFwidXJsXCI6XCJodHRwczpcXFwvXFxcL2NhZGh1Yi54eXpcXFwvI3JlY292ZXJ5X3Rva2VuPUx3c0MtS3BnbWlEd0dvLVpjR0gwdEFcIixcImlkXCI6XCJjODU1ZWM1MjZiZmQ0Y2JmYmUyNmM4OTk2ZGU4ODczOFwiLFwidXJsX2lkc1wiOltcIjJkMjljMDI0NTY5MzcxODcxMmI0ODA0M2U3MDYyOTA1ZDc1NzVkNjlcIl19In0
|
|
||||||
// #recovery_token=LwsC-KpgmiDwGo-ZcGH0tA
|
|
||||||
// navigate(routes.updatePassword({ recoveryToken: token }))
|
|
||||||
client
|
|
||||||
.recover(token, true)
|
|
||||||
.then(() => {
|
|
||||||
navigate(routes.updatePassword())
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
addMessage('Problem recovering account', {
|
|
||||||
classes: 'bg-red-300 text-red-900',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [hash, client]) // complaining about not having addMessage, however adding it puts useEffect into a loop
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header id="cadhub-main-header">
|
<header id="cadhub-main-header">
|
||||||
@@ -232,11 +198,7 @@ const MainLayout = ({ children }) => {
|
|||||||
)}
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
<Flash timeout={1500} />
|
<Flash timeout={1000} />
|
||||||
<LoginModal
|
|
||||||
open={isLoginModalOpen}
|
|
||||||
onClose={() => setIsLoginModalOpen(false)}
|
|
||||||
/>
|
|
||||||
<main>{children}</main>
|
<main>{children}</main>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
import { routes, navigate } from '@redwoodjs/router'
|
|
||||||
import { useAuth } from '@redwoodjs/auth'
|
|
||||||
import { Form, Submit } from '@redwoodjs/forms'
|
|
||||||
import { useFlash } from '@redwoodjs/web'
|
|
||||||
|
|
||||||
import InputTextForm from 'src/components/InputTextForm'
|
|
||||||
import MainLayout from 'src/layouts/MainLayout'
|
|
||||||
import Seo from 'src/components/Seo/Seo'
|
|
||||||
|
|
||||||
const AccountRecoveryPage = () => {
|
|
||||||
const { addMessage } = useFlash()
|
|
||||||
const { client } = useAuth()
|
|
||||||
const onSubmit = ({ email }) => {
|
|
||||||
client
|
|
||||||
.requestPasswordRecovery(email)
|
|
||||||
.then(() => {
|
|
||||||
addMessage('Email sent', { classes: 'rw-flash-success' })
|
|
||||||
setTimeout(() => {
|
|
||||||
navigate(routes.home())
|
|
||||||
}, 500)
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
addMessage('Problem sending email', {
|
|
||||||
classes: 'bg-red-300 text-red-900',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<MainLayout>
|
|
||||||
<Seo
|
|
||||||
title="Account recovery"
|
|
||||||
description="Send recovery email"
|
|
||||||
lang="en-US"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<section className="max-w-md mx-auto mt-20">
|
|
||||||
<h2 className="text-xl text-indigo-500 pb-4">Send recovery email</h2>
|
|
||||||
<Form onSubmit={onSubmit}>
|
|
||||||
<div
|
|
||||||
className="grid items-center gap-2"
|
|
||||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
|
||||||
>
|
|
||||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
|
||||||
email:
|
|
||||||
</span>
|
|
||||||
<InputTextForm
|
|
||||||
className="text-xl"
|
|
||||||
name="email"
|
|
||||||
validation={{
|
|
||||||
required: true,
|
|
||||||
pattern: {
|
|
||||||
value: /[^@]+@[^.]+\..+/,
|
|
||||||
message: 'please enter a valid email address',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Submit className="bg-indigo-200 text-indigo-800 p-2 px-4 shadow hover:shadow-lg mt-4 rounded">
|
|
||||||
Send email
|
|
||||||
</Submit>
|
|
||||||
</Form>
|
|
||||||
</section>
|
|
||||||
</MainLayout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AccountRecoveryPage
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import AccountRecoveryPage from './AccountRecoveryPage'
|
|
||||||
|
|
||||||
export const generated = () => {
|
|
||||||
return <AccountRecoveryPage />
|
|
||||||
}
|
|
||||||
|
|
||||||
export default { title: 'Pages/AccountRecoveryPage' }
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { render } from '@redwoodjs/testing'
|
|
||||||
|
|
||||||
import AccountRecoveryPage from './AccountRecoveryPage'
|
|
||||||
|
|
||||||
describe('AccountRecoveryPage', () => {
|
|
||||||
it('renders successfully', () => {
|
|
||||||
expect(() => {
|
|
||||||
render(<AccountRecoveryPage />)
|
|
||||||
}).not.toThrow()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
import { routes, navigate } from '@redwoodjs/router'
|
|
||||||
import { useAuth } from '@redwoodjs/auth'
|
|
||||||
import { Form, Submit } from '@redwoodjs/forms'
|
|
||||||
import { useFlash } from '@redwoodjs/web'
|
|
||||||
|
|
||||||
import InputTextForm from 'src/components/InputTextForm'
|
|
||||||
import MainLayout from 'src/layouts/MainLayout'
|
|
||||||
import Seo from 'src/components/Seo/Seo'
|
|
||||||
|
|
||||||
const UpdatePasswordPage = () => {
|
|
||||||
const { addMessage } = useFlash()
|
|
||||||
const { client } = useAuth()
|
|
||||||
const onSubmit = ({ password, confirm }) => {
|
|
||||||
if (password !== confirm) {
|
|
||||||
addMessage("Passwords don't match, try again", {
|
|
||||||
classes: 'bg-red-300 text-red-900',
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
client
|
|
||||||
.currentUser()
|
|
||||||
.update({ password })
|
|
||||||
.then(() => {
|
|
||||||
addMessage('Email updated', { classes: 'rw-flash-success' })
|
|
||||||
setTimeout(() => {
|
|
||||||
navigate(routes.home())
|
|
||||||
}, 500)
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
addMessage('Problem updating email', {
|
|
||||||
classes: 'bg-red-300 text-red-900',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<MainLayout>
|
|
||||||
<Seo
|
|
||||||
title="Account recovery"
|
|
||||||
description="Send recovery email"
|
|
||||||
lang="en-US"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<section className="max-w-md mx-auto mt-20">
|
|
||||||
<h2 className="text-xl text-indigo-500 pb-4">Reset Password</h2>
|
|
||||||
<Form onSubmit={onSubmit}>
|
|
||||||
<div
|
|
||||||
className="grid items-center gap-2"
|
|
||||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
|
||||||
>
|
|
||||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
|
||||||
password:
|
|
||||||
</span>
|
|
||||||
<InputTextForm
|
|
||||||
className="text-xl"
|
|
||||||
name="email"
|
|
||||||
type="password"
|
|
||||||
validation={{
|
|
||||||
required: true,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
|
||||||
confirm:
|
|
||||||
</span>
|
|
||||||
<InputTextForm
|
|
||||||
className="text-xl"
|
|
||||||
name="email"
|
|
||||||
type="password"
|
|
||||||
validation={{
|
|
||||||
required: true,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Submit className="bg-indigo-200 text-indigo-800 p-2 px-4 shadow hover:shadow-lg mt-4 rounded">
|
|
||||||
Update
|
|
||||||
</Submit>
|
|
||||||
</Form>
|
|
||||||
</section>
|
|
||||||
</MainLayout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default UpdatePasswordPage
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import UpdatePasswordPage from './UpdatePasswordPage'
|
|
||||||
|
|
||||||
export const generated = () => {
|
|
||||||
return <UpdatePasswordPage />
|
|
||||||
}
|
|
||||||
|
|
||||||
export default { title: 'Pages/UpdatePasswordPage' }
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { render } from '@redwoodjs/testing'
|
|
||||||
|
|
||||||
import UpdatePasswordPage from './UpdatePasswordPage'
|
|
||||||
|
|
||||||
describe('UpdatePasswordPage', () => {
|
|
||||||
it('renders successfully', () => {
|
|
||||||
expect(() => {
|
|
||||||
render(<UpdatePasswordPage />)
|
|
||||||
}).not.toThrow()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
20
yarn.lock
20
yarn.lock
@@ -2366,10 +2366,10 @@
|
|||||||
lodash.omitby "^4.6.0"
|
lodash.omitby "^4.6.0"
|
||||||
merge-graphql-schemas "^1.7.6"
|
merge-graphql-schemas "^1.7.6"
|
||||||
|
|
||||||
"@redwoodjs/auth@^0.21.0":
|
"@redwoodjs/auth@^0.20.0":
|
||||||
version "0.21.0"
|
version "0.20.0"
|
||||||
resolved "https://registry.yarnpkg.com/@redwoodjs/auth/-/auth-0.21.0.tgz#967deef0d0421ea9f6bc205857ad9265d2f5df55"
|
resolved "https://registry.yarnpkg.com/@redwoodjs/auth/-/auth-0.20.0.tgz#c08c0b735a0b09ef84dc6d357fa2803d61f1d389"
|
||||||
integrity sha512-o3HuRTs79BqmnZX2zvK6+ffebxJE+T/nqwDDdOmCjXUitSsYbLSJkG4ffUuMtSWCFCxf/ytaFB245nS8Vin3XQ==
|
integrity sha512-M1rPtiXzU7YagQ120zEkp5qvJruWRcFLUfBhgexGYgnEkqFIKFGLQL9pBywoZ6kxNjI7x/pbghz6FS7H/lzw/g==
|
||||||
|
|
||||||
"@redwoodjs/cli@^0.20.0":
|
"@redwoodjs/cli@^0.20.0":
|
||||||
version "0.20.0"
|
version "0.20.0"
|
||||||
@@ -8671,13 +8671,6 @@ good-listener@^1.2.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
delegate "^3.1.2"
|
delegate "^3.1.2"
|
||||||
|
|
||||||
gotrue-js@^0.9.27:
|
|
||||||
version "0.9.27"
|
|
||||||
resolved "https://registry.yarnpkg.com/gotrue-js/-/gotrue-js-0.9.27.tgz#ed01b47e97781f10f26458ff77d83d97bcc65e08"
|
|
||||||
integrity sha512-XSQ9XGELrnf6bKYaGk+2z1E6aW6+wZ3S6ns3JQz9tXesBuwVPDv/xOTTZ/Qrtu85GJgxTjhJH447w09a73Tneg==
|
|
||||||
dependencies:
|
|
||||||
micro-api-client "^3.2.1"
|
|
||||||
|
|
||||||
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4:
|
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4:
|
||||||
version "4.2.4"
|
version "4.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||||
@@ -11338,11 +11331,6 @@ methods@~1.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||||
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
|
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
|
||||||
|
|
||||||
micro-api-client@^3.2.1:
|
|
||||||
version "3.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/micro-api-client/-/micro-api-client-3.3.0.tgz#52dd567d322f10faffe63d19d4feeac4e4ffd215"
|
|
||||||
integrity sha512-y0y6CUB9RLVsy3kfgayU28746QrNMpSm9O/AYGNsBgOkJr/X/Jk0VLGoO8Ude7Bpa8adywzF+MzXNZRFRsNPhg==
|
|
||||||
|
|
||||||
microevent.ts@~0.1.1:
|
microevent.ts@~0.1.1:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/microevent.ts/-/microevent.ts-0.1.1.tgz#70b09b83f43df5172d0205a63025bce0f7357fa0"
|
resolved "https://registry.yarnpkg.com/microevent.ts/-/microevent.ts-0.1.1.tgz#70b09b83f43df5172d0205a63025bce0f7357fa0"
|
||||||
|
|||||||
Reference in New Issue
Block a user