New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Antti | kirjautuminen ja rekistöröityminen sekä authentication #23
base: main
Are you sure you want to change the base?
Conversation
…to handle registering. Added some basic handler functions there
…so credits can be given easier
…t middleware interfering. Most likely will be replaced / deleted, but it works for now in development stage
…rst name etc to make development easier and faster
…written multiple times
…st for user creation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
utils/handleError.ts
Outdated
type KnownFrontEndErrorTexts = | ||
| 'email was not unique!' | ||
| 'invalid credentials!' | ||
| 'invalid request body!' | ||
| (string & Record<never, never>); | ||
|
||
const FRONT_END_HANDLER: Record<KnownFrontEndErrorTexts, string> = { | ||
'email was not unique!': 'Sähköposti on jo käytössä', | ||
'invalid credentials!': 'Sähköposti tai salasana on virheellinen!', | ||
'invalid request body!': 'Sähköposti tai salasana on virheellinen', | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Olisiko tälle parempaa toteutusta 😄
Lyhykäisyydessään tuon tehtävä on kääntää serveriltä tulevat virheet (ovat englanniksi) suomeksi. Onko tuon tekemiseen jokin parempi tapa kuin käyttää Record
ia? KnownFrontEndErrorTexts
in idea on se, että osaa ehdottaa ennaltatiedettyjen virheiden tekstit suoraan. Rivillä 30 | (string & Record<never, never>);
idea on vain "kiertää" TypeScriptin virhe. Ei liene kovin järkevä tapa 😂
Jos Record
on paras tapa toteuttaa, teoriassa lienee parempi tehdä ilman KnownFrontEndErrorTexts
-typeä?
Tähän tapaan:
type KnownFrontEndErrorTexts = | |
| 'email was not unique!' | |
| 'invalid credentials!' | |
| 'invalid request body!' | |
| (string & Record<never, never>); | |
const FRONT_END_HANDLER: Record<KnownFrontEndErrorTexts, string> = { | |
'email was not unique!': 'Sähköposti on jo käytössä', | |
'invalid credentials!': 'Sähköposti tai salasana on virheellinen!', | |
'invalid request body!': 'Sähköposti tai salasana on virheellinen', | |
}; | |
const FRONT_END_HANDLER: Record<string, string> = { | |
'email was not unique!': 'Sähköposti on jo käytössä', | |
'invalid credentials!': 'Sähköposti tai salasana on virheellinen!', | |
'invalid request body!': 'Sähköposti tai salasana on virheellinen', | |
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Itse tekisin tuon virheen määrityksen näin
const FRONT_END_HANDLER = {
'email was not unique!': 'Sähköposti on jo käytössä',
'invalid credentials!': 'Sähköposti tai salasana on virheellinen!',
'invalid request body!': 'Sähköposti tai salasana on virheellinen',
} as const;
type KnownFrontEndErrorTexts = keyof typeof FRONT_END_HANDLER;
Kun määrittelyn tekee näin pitää teksti hakea seuraavasti
const responseText = e.response.data.toLowerCase();
const frontendText =
FRONT_END_HANDLER[responseText as KnownFrontEndErrorTexts];
if (frontendText) {
console.error(frontendText);
return frontendText;
} else {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow! 😮 Erittäin siisti tapa toteuttaa tuo, kiitos! Ei käynyt mielessäkään toteuttaa tuolla tavalla, toivottavasti tulevaisuudessa tulee 😅
pages/api/auth/login.ts
Outdated
const luciaLongSession = new Lucia(adapter, { | ||
sessionExpiresIn: new TimeSpan(30, 'd'), | ||
sessionCookie: { | ||
attributes: { | ||
secure: process.env.NODE_ENV === 'production', | ||
}, | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tähän en löytynyt vastausta Lucian dokumenteista tai netistä. Ainoa tapa mikä näyttäisi olevan Session
-keksien pituuden määrittämiseen on sessionExpiresIn
-arvo. Tässä olisi kaksi vaihtoehtoa eli lyhyempi (2 vk) ja pidempi (30 päivää). Se määräytyy, onko "Muista minut" -painike painettu kirjautumisen yhteydessä. Tämä Session
-arvo sitten tallennetaan tietokantaan
Eihän sessionExpiresIn
-arvoa pysty vaihtamaan enää lennosta, kun jollekkin muuttujalle on määritetty Class
-arvo? Googlen mukaan ei ja AI sanoi kanssa, että ei ole mahdollista. Ajattelin vielä varmistaa 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
En usko että sessionExpiresIn
arvoa voi vaihtaa myöhemmin, eli tämä on oikea tapa. Siirtäisin tämän kuitenkin auth.ts
tiedostoon, jotta molemmat lucia-objektit on määritetty samassa paikassa.
|
||
const { email, password, rememberMe } = req.body as UserLoginDetails; | ||
|
||
const lucia = rememberMe ? luciaLongSession : luciaShortSession; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tämä määrittää sen, että kumpaa "istunnon" pituutta käytettään
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Näin hyvä, mutta siirtäisin tosiaan luciaLongSession
samaan tiedostoon mistä luciaShortSession
importataan.
backend/auth.ts
Outdated
export const lucia = new Lucia(adapter, { | ||
sessionExpiresIn: new TimeSpan(14, 'd'), | ||
sessionCookie: { | ||
attributes: { | ||
secure: process.env.NODE_ENV === 'production', | ||
}, | ||
}, | ||
getUserAttributes({ | ||
createdAt, | ||
email, | ||
firstName, | ||
lastName, | ||
updatedAt, | ||
uuid, | ||
}: User): User { | ||
return { | ||
uuid: uuid, | ||
firstName: firstName, | ||
lastName: lastName, | ||
email: email, | ||
createdAt: createdAt, | ||
updatedAt: updatedAt, | ||
}; | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Onko kaksi viikkoa hyvä pituus, ennenkuin vaaditaan uudelleenkirjautuminen?
Tämä on muuten otettu Lucian ohjeista, mutta User
-type on vaihdettu omaan, joka toimii tässä paremmin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Laittaisin 1 tunti jos ei valitse "Muista minut" ja 30 päivää jos valitsee sen.
backend/auth.ts
Outdated
declare module 'lucia' { | ||
interface Register { | ||
Lucia: typeof lucia; | ||
DatabaseUserAttributes: DatabaseUserAttributes; | ||
DatabaseSessionAttributes: DatabaseSessionAttributes; | ||
} | ||
} | ||
interface DatabaseUserAttributes extends User {} | ||
interface DatabaseSessionAttributes extends CreateSession {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rivi 38 on Lucian ohjeista, muistaakseni rivit 39 ja 40 ovat itse tekemiäni
Rivit 43 ja 44 näyttäisi olevan ihan turhat
declare module 'lucia' { | |
interface Register { | |
Lucia: typeof lucia; | |
DatabaseUserAttributes: DatabaseUserAttributes; | |
DatabaseSessionAttributes: DatabaseSessionAttributes; | |
} | |
} | |
interface DatabaseUserAttributes extends User {} | |
interface DatabaseSessionAttributes extends CreateSession {} | |
declare module 'lucia' { | |
interface Register { | |
Lucia: typeof lucia; | |
DatabaseUserAttributes: User; | |
DatabaseSessionAttributes: CreateSession; | |
} | |
} |
Täytyy laittaa testiin ennenkuin tekee muutoksia, ettei mikään hajoa, mutta tämmöisen huomasin 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rivit 43 ja 44 näyttäisi olevan ihan turhat
Taitaa olla sitä varten jos haluaa lisätä jotain custom-attribuutteja tietokantaan Userille tai Sessiolle mutta tässä tapauksessa tarpeettomia.
Muutama huomio tähän kohtaan: DatabaseUserAttributes
kohtaan pitää laittaa Database-tyyppi. Nyt näyttää siltä, että getUserAttributes
saa User
tyypin, eli sen voisi välittää semmoisenaan eteenpäin. Oikeasti se saa PrismaUser
tyypin, jolloin siitä pitää poistaa id
ja password
kentät (kuten olet tehnyt, eli sun getUserAttributes
on implementoitu oikein vaikka tyypitys on väärin).
DatabaseSessionAttributes
on sitä varten, jos sessio-tauluun haluaa tallentaa jotain custom-tietoja (esim. mistä maasta sessio on). Meillä ei ole mitään custom-tietoja, eli sen rivin voi poistaa.
Jotta PrismaUser
saa importattua import type { User, PrismaUser } from '~/shared/types';
komennolla pitää muokata types.ts
tiedostoa, ks. kommentti siellä.
declare module 'lucia' { | |
interface Register { | |
Lucia: typeof lucia; | |
DatabaseUserAttributes: DatabaseUserAttributes; | |
DatabaseSessionAttributes: DatabaseSessionAttributes; | |
} | |
} | |
interface DatabaseUserAttributes extends User {} | |
interface DatabaseSessionAttributes extends CreateSession {} | |
declare module 'lucia' { | |
interface Register { | |
Lucia: typeof lucia; | |
DatabaseUserAttributes: PrismaUser; | |
} | |
} |
icons/index.ts
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
En tiedä onko sulla kokemusta tästä, mutta lienee turha tämä index.ts
-tiedosto. Itse tykkään importtaa SVG:t suoraan tiedostosta
Edit: toisaalta index.ts
:stä importtaaminen vähentää periaatteessa rivejä, jos joutuu monta kuvaketta importtaamaan
Esim:
import SvgEyeOpen from '~/icons/eye_open';
import SvgEyeSlash from '~/icons/eye_slash';
Pitää käydä muutenkin nuo iconit läpi, kun osa niistä on snake_case
lla, osa kebab-case
lla ja osa sitten PascalCase
lla 🤣
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makuasia, kumpikin toimii hyvin. Itse en yleensä käytä tämmöisiä barrel tiedostoja.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tiedoston suoraan importtaaminen tuntuu luentavammalta kuin tuolta index.ts
:stä.
Ja mitä oon ymmärtänyt, niin monesti "indexin" importtaamminen saattaa hidastaa koodia vs esim. tietyn funktion importtaaminen, muistaakseni mainitsitkin tästä bcrypt
in kanssa toimiessani 👍
Tosin tässä sitä ongelmaa nyt ei ole kun pari hassua riviä, mutta kuitenkin
export async function getServerSideProps( | ||
context: GetServerSidePropsContext, | ||
): Promise<GetServerSidePropsResult<{ user: User }>> { | ||
const cookieData = await validateRequest(context.req, context.res); | ||
if (!cookieData.user) { | ||
return { | ||
redirect: { | ||
permanent: false, | ||
destination: '/login', | ||
}, | ||
}; | ||
} | ||
return { | ||
props: { | ||
user: JSON.parse(JSON.stringify(cookieData.user)) as User, | ||
}, | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
En tiedä onko sulla kokemusta Next
in getServerSideProps
-funktiosta, että onko kuinka helppo saada geneeriseksi. Sain importit toimimaan toisesta tiedostosta, mutta en saanut context
-argumenttia mitenkään siirrettyä sinne toiseen tiedostoon 😄 Lähinnä helpottaisi ettei tätä tarvitsisi jokaiseen tiedostoon kopioida 😅 (jos on mahdollista tehdä geneerinen)
Middlewareen kannattanee tehdä authentication-tsekkaus, mutta sitten jos authentication onkin kunnossa, niin serveriltä täytyy käyttäjän tiedot saada, tähän käytän getServerSideProps
-funktiota
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Jos siirrät funktion toiseen tiedostoon, niin näin pitäisi onnistua (tiedosto kannattaa nimetä paremmin ja laittaa oikeaan hakemistoon):
// index.tsx
import { getServerSideProps } from './getServerSideProps';
export { getServerSideProps };
// getServerSideProps.js
import { User } from '~/shared/types';
import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
import { validateRequest } from '~/backend/auth';
export async function getServerSideProps(
context: GetServerSidePropsContext,
): Promise<GetServerSidePropsResult<{ user: User }>> {
const cookieData = await validateRequest(context.req, context.res);
if (!cookieData.user) {
return {
redirect: {
permanent: false,
destination: '/login',
},
};
}
return {
props: {
user: JSON.parse(JSON.stringify(cookieData.user)) as User,
},
};
}
Middlewareen voi tehdä authentication-tsekkauksen, mutta Next.js:n dokumentaation mukaan se ei välttämättä kannata, koska Lucia tsekkaa session tietokannasta. Toisaalta suorituskykyongelmat eivät tule pitkiin aikoihin minkäänlaiseksi ongelmaksi, eli sikäli ohjauksen voi hyvin laittaa sinne.
However, since Middleware runs on every route, including prefetched routes, it's important to only read the session from the cookie (optimistic checks), and avoid database checks to prevent performance issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tällähän se lähti pelittämään! Kiitos jälleen todella paljon!! :)
Syy tosiaan sille, miksi en itse saanut toimimaan näyttäisi olevan se, että en koskaan exportannut getServerSideProps
-funktiota
En ollut siis täysin tajunnut, mitä tällä You can use getServerSideProps by exporting it from a Page Component.
tarkoitettiin, mutta nyt tiedän! 😅 👍
pages/login.tsx
Outdated
return { | ||
props: { | ||
user: {}, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tämän tarkoitus ei ole palauttaa mitään dataa, vaan ohjata käyttäjä pois /login
-sivulta takaisin -> /
sivulle, jos käyttäjä on jo authentikoitu
Tällä tyhjällä user
-objektilla sain korjattua ERR_TOO_MANY_REDIRECTS
-virheen 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tarvitseeko tyhjä user
objekti palauttaa? Itse en saanut toistettua virhettä seuraavalla getServerSideProps
funktiolla
export async function getServerSideProps(context: GetServerSidePropsContext) {
const cookieData = await validateRequest(context.req, context.res);
if (!cookieData.user) {
return;
}
return {
redirect: {
permanent: false,
destination: '/',
},
};
}
<div | ||
className="fixed top-0 left-0 max-w-full w-full h-full bg-transparent" | ||
onClick={() => closeUserWindow()} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tämän idea on se, että kun käyttäjä klikkaa muuta kuin käyttäjäkuvaketta tai käyttäjä-modalia (missä lukee heidän nimi, sähköposti sekä kirjaudu ulos -nappula) sulkeutuu kyseinen käyttäjä-modal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tämä on hyvä tapa 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
En saanut tätä toimimaan omalla koneella, vaan sain seuraavan virheilmoituksen:
The table `public.Session` does not exist in the current database.
Ilmeisesti Sessio-taulun migraatio on unohtunut PR:stä? Jos lisäät sen niin tsekkaan sitten PR:n.
expiresAt DateTime | ||
createdAt DateTime @default(now()) | ||
updatedAt DateTime @updatedAt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ihan hyvä olla nuo kentät vaikka eivät pakollisia olekaan.
Äsh, joo jäi migraatio tekemättä. Oon käyttänyt tuota EDIT: onko tätä komentoa järkevä käyttää |
Kyllä on! Yleinen tapa on käyttää
|
Nyt on korjattu. Testailin itse ja näytti sekä |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nyt kaikki lahjaideat näkyvät kaikille käyttäjille, joten kaikkiin api/gifts/*
tiedostojen endpointteihin pitää lisätä autentikoinnin tarkistus. Jos käyttäjä ei ole kirjautunut palautetaan 401 Unauthorized
. Jos on kirjautunut palautetaan vain kyseisen käyttäjän lahjat.
const checkedEmailAddress = email.toLowerCase().match(emailRegex); | ||
|
||
if (!checkedEmailAddress) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Itse yhdistäisin nämä rivit seuraavasti (ja sama alla checkedPassword
)
const checkedEmailAddress = email.toLowerCase().match(emailRegex); | |
if (!checkedEmailAddress) { | |
if (!email.toLowerCase().match(emailRegex)) { |
backend/auth.ts
Outdated
declare module 'lucia' { | ||
interface Register { | ||
Lucia: typeof lucia; | ||
DatabaseUserAttributes: DatabaseUserAttributes; | ||
DatabaseSessionAttributes: DatabaseSessionAttributes; | ||
} | ||
} | ||
interface DatabaseUserAttributes extends User {} | ||
interface DatabaseSessionAttributes extends CreateSession {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rivit 43 ja 44 näyttäisi olevan ihan turhat
Taitaa olla sitä varten jos haluaa lisätä jotain custom-attribuutteja tietokantaan Userille tai Sessiolle mutta tässä tapauksessa tarpeettomia.
Muutama huomio tähän kohtaan: DatabaseUserAttributes
kohtaan pitää laittaa Database-tyyppi. Nyt näyttää siltä, että getUserAttributes
saa User
tyypin, eli sen voisi välittää semmoisenaan eteenpäin. Oikeasti se saa PrismaUser
tyypin, jolloin siitä pitää poistaa id
ja password
kentät (kuten olet tehnyt, eli sun getUserAttributes
on implementoitu oikein vaikka tyypitys on väärin).
DatabaseSessionAttributes
on sitä varten, jos sessio-tauluun haluaa tallentaa jotain custom-tietoja (esim. mistä maasta sessio on). Meillä ei ole mitään custom-tietoja, eli sen rivin voi poistaa.
Jotta PrismaUser
saa importattua import type { User, PrismaUser } from '~/shared/types';
komennolla pitää muokata types.ts
tiedostoa, ks. kommentti siellä.
declare module 'lucia' { | |
interface Register { | |
Lucia: typeof lucia; | |
DatabaseUserAttributes: DatabaseUserAttributes; | |
DatabaseSessionAttributes: DatabaseSessionAttributes; | |
} | |
} | |
interface DatabaseUserAttributes extends User {} | |
interface DatabaseSessionAttributes extends CreateSession {} | |
declare module 'lucia' { | |
interface Register { | |
Lucia: typeof lucia; | |
DatabaseUserAttributes: PrismaUser; | |
} | |
} |
getUserAttributes({ | ||
createdAt, | ||
email, | ||
firstName, | ||
lastName, | ||
updatedAt, | ||
uuid, | ||
}: User): User { | ||
return { | ||
uuid: uuid, | ||
firstName: firstName, | ||
lastName: lastName, | ||
email: email, | ||
createdAt: createdAt, | ||
updatedAt: updatedAt, | ||
}; | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GetUserAttributes
saa tyypin automaattisesti tuolta declare module
:sta eli tässä sitä ei tarvitse laittaa funktion argumenttiin (tai sitten vaihtaa oikeaan eli PrismaUser
tyyppiin.
Lisäksi yksinkertaistaisin funktiota seuraavasti:
getUserAttributes({ | |
createdAt, | |
email, | |
firstName, | |
lastName, | |
updatedAt, | |
uuid, | |
}: User): User { | |
return { | |
uuid: uuid, | |
firstName: firstName, | |
lastName: lastName, | |
email: email, | |
createdAt: createdAt, | |
updatedAt: updatedAt, | |
}; | |
}, | |
getUserAttributes(user): User { | |
const { uuid, firstName, lastName, email, createdAt, updatedAt } = user; | |
return { uuid, firstName, lastName, email, createdAt, updatedAt }; | |
}, |
backend/auth.ts
Outdated
export const lucia = new Lucia(adapter, { | ||
sessionExpiresIn: new TimeSpan(14, 'd'), | ||
sessionCookie: { | ||
attributes: { | ||
secure: process.env.NODE_ENV === 'production', | ||
}, | ||
}, | ||
getUserAttributes({ | ||
createdAt, | ||
email, | ||
firstName, | ||
lastName, | ||
updatedAt, | ||
uuid, | ||
}: User): User { | ||
return { | ||
uuid: uuid, | ||
firstName: firstName, | ||
lastName: lastName, | ||
email: email, | ||
createdAt: createdAt, | ||
updatedAt: updatedAt, | ||
}; | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Laittaisin 1 tunti jos ei valitse "Muista minut" ja 30 päivää jos valitsee sen.
export async function validateRequest( | ||
req: IncomingMessage, | ||
res: ServerResponse, | ||
): Promise<{ user: User; session: Session } | { user: null; session: null }> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nähdäkseni tässä olisi syytä käyttää Lucian user-tyyppiä, eli seuraavasti olettaen että import tehty import type { Session, User as LuciaUser } from 'lucia';
): Promise<{ user: User; session: Session } | { user: null; session: null }> { | |
): Promise<{ user: LuciaUser; session: Session } | { user: null; session: null }> { |
export async function getServerSideProps( | ||
context: GetServerSidePropsContext, | ||
): Promise<GetServerSidePropsResult<{ user: User }>> { | ||
const cookieData = await validateRequest(context.req, context.res); | ||
if (!cookieData.user) { | ||
return { | ||
redirect: { | ||
permanent: false, | ||
destination: '/login', | ||
}, | ||
}; | ||
} | ||
return { | ||
props: { | ||
user: JSON.parse(JSON.stringify(cookieData.user)) as User, | ||
}, | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Jos siirrät funktion toiseen tiedostoon, niin näin pitäisi onnistua (tiedosto kannattaa nimetä paremmin ja laittaa oikeaan hakemistoon):
// index.tsx
import { getServerSideProps } from './getServerSideProps';
export { getServerSideProps };
// getServerSideProps.js
import { User } from '~/shared/types';
import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
import { validateRequest } from '~/backend/auth';
export async function getServerSideProps(
context: GetServerSidePropsContext,
): Promise<GetServerSidePropsResult<{ user: User }>> {
const cookieData = await validateRequest(context.req, context.res);
if (!cookieData.user) {
return {
redirect: {
permanent: false,
destination: '/login',
},
};
}
return {
props: {
user: JSON.parse(JSON.stringify(cookieData.user)) as User,
},
};
}
Middlewareen voi tehdä authentication-tsekkauksen, mutta Next.js:n dokumentaation mukaan se ei välttämättä kannata, koska Lucia tsekkaa session tietokannasta. Toisaalta suorituskykyongelmat eivät tule pitkiin aikoihin minkäänlaiseksi ongelmaksi, eli sikäli ohjauksen voi hyvin laittaa sinne.
However, since Middleware runs on every route, including prefetched routes, it's important to only read the session from the cookie (optimistic checks), and avoid database checks to prevent performance issues.
} | ||
return { | ||
props: { | ||
user: JSON.parse(JSON.stringify(cookieData.user)) as User, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ilmeisesti teet deep clonen user
objektista? JSON.parse ja stringify avulla? Siihen tarkoitukseen structuredClone
on parempi.
showUserWindow={showUserWindow} | ||
user={user} | ||
handleLogout={handleLogout} | ||
closeUserWindow={() => setShowUserWindow(false)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Joo tämä on oikein hyvä tapa 👍
utils/handleError.ts
Outdated
type KnownFrontEndErrorTexts = | ||
| 'email was not unique!' | ||
| 'invalid credentials!' | ||
| 'invalid request body!' | ||
| (string & Record<never, never>); | ||
|
||
const FRONT_END_HANDLER: Record<KnownFrontEndErrorTexts, string> = { | ||
'email was not unique!': 'Sähköposti on jo käytössä', | ||
'invalid credentials!': 'Sähköposti tai salasana on virheellinen!', | ||
'invalid request body!': 'Sähköposti tai salasana on virheellinen', | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Itse tekisin tuon virheen määrityksen näin
const FRONT_END_HANDLER = {
'email was not unique!': 'Sähköposti on jo käytössä',
'invalid credentials!': 'Sähköposti tai salasana on virheellinen!',
'invalid request body!': 'Sähköposti tai salasana on virheellinen',
} as const;
type KnownFrontEndErrorTexts = keyof typeof FRONT_END_HANDLER;
Kun määrittelyn tekee näin pitää teksti hakea seuraavasti
const responseText = e.response.data.toLowerCase();
const frontendText =
FRONT_END_HANDLER[responseText as KnownFrontEndErrorTexts];
if (frontendText) {
console.error(frontendText);
return frontendText;
} else {
icons/index.ts
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makuasia, kumpikin toimii hyvin. Itse en yleensä käytä tämmöisiä barrel tiedostoja.
…ction. Changed router.push to window.location.href
Nousi pari kysymystä mieleen, joten ajattelin pushata ja kysyä ennenkuin lähtee isommin tekemään 😄