-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into endre_tavlenavn
- Loading branch information
Showing
27 changed files
with
1,615 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { initializeAdminApp } from 'Admin/utils/firebase' | ||
import { auth } from 'firebase-admin' | ||
import { NextApiRequest, NextApiResponse } from 'next' | ||
|
||
initializeAdminApp() | ||
|
||
export default async function handler( | ||
request: NextApiRequest, | ||
response: NextApiResponse, | ||
) { | ||
const authorization = request.headers.authorization | ||
if (authorization?.startsWith('Bearer ')) { | ||
const idToken = authorization.split('Bearer ')[1] ?? '' | ||
const decodedToken = await auth().verifyIdToken(idToken) | ||
|
||
if (decodedToken) { | ||
const expiresIn = 60 * 60 * 24 * 10 // Ten days | ||
const sessionCookie = await auth().createSessionCookie(idToken, { | ||
expiresIn, | ||
}) | ||
|
||
response.setHeader( | ||
'Set-Cookie', | ||
`session=${sessionCookie};HttpOnly;Max-Age=${expiresIn};Secure;SameSite=Strict;Path=/;`, | ||
) | ||
return response | ||
.status(200) | ||
.json({ message: 'Successfully logged in!' }) | ||
} | ||
} | ||
return response.status(400).json({ error: 'Could not log in!' }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { NextApiRequest, NextApiResponse } from 'next' | ||
|
||
export default async function handler( | ||
request: NextApiRequest, | ||
response: NextApiResponse, | ||
) { | ||
response.setHeader('Set-Cookie', `session="";Max-Age=-1;Path=/`) | ||
return response.status(200).json({ message: 'Successfully logged out!' }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
next-tavla/src/Admin/scenarios/Login/components/CreateUser.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { PrimaryButton } from '@entur/button' | ||
import { TextField } from '@entur/form' | ||
import { Heading3 } from '@entur/typography' | ||
import musk from 'assets/illustrations/Musk.png' | ||
import { FirebaseError } from 'firebase/app' | ||
import Image from 'next/image' | ||
import { SyntheticEvent } from 'react' | ||
|
||
import { useAuth } from '../hooks/useAuth' | ||
import { useFirebaseAuthError } from '../hooks/useFirebaseAuthError' | ||
import { UserError } from './UserError' | ||
|
||
function CreateUser() { | ||
const { createUser } = useAuth() | ||
const { error, setError, getTextFieldPropsForType } = useFirebaseAuthError() | ||
|
||
const submitCreateUser = async (event: SyntheticEvent) => { | ||
event.preventDefault() | ||
|
||
const data = event.currentTarget as unknown as { | ||
email: HTMLInputElement | ||
password: HTMLInputElement | ||
repeat_password: HTMLInputElement | ||
} | ||
|
||
const email = data.email.value | ||
const password = data.password.value | ||
const repeatPassword = data.repeat_password.value | ||
|
||
try { | ||
await createUser(email, password, repeatPassword) | ||
} catch (error) { | ||
if (error instanceof FirebaseError) setError(error) | ||
} | ||
} | ||
|
||
return ( | ||
<div> | ||
<Image src={musk} alt="illustration" className="h-50 w-50" /> | ||
<Heading3>Logg inn med e-post</Heading3> | ||
<form className="flexColumn" onSubmit={submitCreateUser}> | ||
<TextField | ||
name="email" | ||
label="E-post" | ||
type="email" | ||
{...getTextFieldPropsForType('email')} | ||
/> | ||
<TextField | ||
name="password" | ||
label="Passord" | ||
type="password" | ||
{...getTextFieldPropsForType('password')} | ||
/> | ||
<TextField | ||
name="repeat_password" | ||
label="Gjenta passord" | ||
type="password" | ||
{...getTextFieldPropsForType('repeat_password')} | ||
/> | ||
<UserError error={error} /> | ||
<PrimaryButton type="submit">Opprett ny bruker</PrimaryButton> | ||
</form> | ||
</div> | ||
) | ||
} | ||
|
||
export { CreateUser } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { PrimaryButton } from '@entur/button' | ||
import { TextField } from '@entur/form' | ||
import { Heading3 } from '@entur/typography' | ||
import musk from 'assets/illustrations/Musk.png' | ||
import { FirebaseError } from 'firebase/app' | ||
import Image from 'next/image' | ||
import { SyntheticEvent } from 'react' | ||
import { useAuth } from '../hooks/useAuth' | ||
import { useFirebaseAuthError } from '../hooks/useFirebaseAuthError' | ||
import { UserError } from './UserError' | ||
|
||
function Email() { | ||
const { error, setError, getTextFieldPropsForType } = useFirebaseAuthError() | ||
const { login } = useAuth() | ||
|
||
const submitEmailLogin = async (event: SyntheticEvent) => { | ||
event.preventDefault() | ||
|
||
const data = event.currentTarget as unknown as { | ||
email: HTMLInputElement | ||
password: HTMLInputElement | ||
} | ||
|
||
const email = data.email.value | ||
const password = data.password.value | ||
|
||
try { | ||
await login(email, password) | ||
} catch (error: unknown) { | ||
if (error instanceof FirebaseError) { | ||
setError(error) | ||
} | ||
} | ||
} | ||
|
||
return ( | ||
<div> | ||
<Image src={musk} alt="illustration" className="h-50 w-50" /> | ||
<Heading3>Logg inn med e-post</Heading3> | ||
<form className="flexColumn" onSubmit={submitEmailLogin}> | ||
<TextField | ||
name="email" | ||
label="E-post" | ||
type="email" | ||
{...getTextFieldPropsForType('email')} | ||
/> | ||
<TextField | ||
name="password" | ||
label="Passord" | ||
type="password" | ||
{...getTextFieldPropsForType('password')} | ||
/> | ||
|
||
<UserError error={error} /> | ||
|
||
<PrimaryButton type="submit">Logg inn</PrimaryButton> | ||
</form> | ||
</div> | ||
) | ||
} | ||
|
||
export { Email } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { PrimaryButton, SecondaryButton } from '@entur/button' | ||
import { Heading3, Paragraph } from '@entur/typography' | ||
import { TLoginPage } from 'Admin/types/login' | ||
import musk from 'assets/illustrations/Musk.png' | ||
import Image from 'next/image' | ||
|
||
function Start({ pushPage }: { pushPage: (page: TLoginPage) => void }) { | ||
return ( | ||
<div> | ||
<Image src={musk} alt="illustration" className="h-50 w-50" /> | ||
<Heading3>Logg inn for å fortsette</Heading3> | ||
<Paragraph> | ||
Logg inn for å få tilgang til å opprette og administrere tavler. | ||
</Paragraph> | ||
<div className="flexColumn"> | ||
<PrimaryButton onClick={() => pushPage('email')}> | ||
Logg inn med e-post | ||
</PrimaryButton> | ||
<SecondaryButton onClick={() => pushPage('create')}> | ||
Opprett ny bruker | ||
</SecondaryButton> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
export { Start } |
9 changes: 9 additions & 0 deletions
9
next-tavla/src/Admin/scenarios/Login/components/UserError.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { SmallAlertBox } from '@entur/alert' | ||
import { TAuthError } from 'Admin/types/login' | ||
|
||
function UserError({ error }: { error?: TAuthError }) { | ||
if (!error || error.type !== 'user') return null | ||
return <SmallAlertBox variant="error">{error.value}</SmallAlertBox> | ||
} | ||
|
||
export { UserError } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { fetchWithIdToken } from 'Admin/utils' | ||
import { | ||
createUserWithEmailAndPassword, | ||
signInWithEmailAndPassword, | ||
} from 'firebase/auth' | ||
import { auth } from 'utils/firebase' | ||
|
||
import { FirebaseError } from 'firebase/app' | ||
import { useRouter } from 'next/router' | ||
|
||
function useAuth() { | ||
const router = useRouter() | ||
|
||
const login = async (email: string, password: string) => { | ||
const credential = await signInWithEmailAndPassword( | ||
auth, | ||
email, | ||
password, | ||
) | ||
await fetchWithIdToken('/api/login', await credential.user.getIdToken()) | ||
router.reload() | ||
} | ||
|
||
const logout = async () => { | ||
await fetch('/api/logout') | ||
router.reload() | ||
} | ||
|
||
const createUser = async ( | ||
email: string, | ||
password: string, | ||
repeatPassword: string, | ||
) => { | ||
if (password !== repeatPassword) | ||
throw new FirebaseError( | ||
'auth/password-no-match', | ||
'passwords does not match', | ||
) | ||
|
||
const credential = await createUserWithEmailAndPassword( | ||
auth, | ||
email, | ||
password, | ||
) | ||
await fetchWithIdToken('/api/login', await credential.user.getIdToken()) | ||
router.reload() | ||
} | ||
|
||
return { login, logout, createUser } | ||
} | ||
|
||
export { useAuth } |
Oops, something went wrong.