Skip to content
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

Open
wants to merge 107 commits into
base: main
Choose a base branch
from

Conversation

anttiasmala
Copy link
Collaborator

@anttiasmala anttiasmala commented Apr 4, 2024

Nousi pari kysymystä mieleen, joten ajattelin pushata ja kysyä ennenkuin lähtee isommin tekemään 😄

…to handle registering. Added some basic handler functions there
…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
Copy link

vercel bot commented Apr 4, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
lahjalista ❌ Failed (Inspect) May 1, 2024 9:32pm

pages/register.tsx Outdated Show resolved Hide resolved
Comment on lines 26 to 36
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',
};
Copy link
Collaborator Author

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ää Recordia? KnownFrontEndErrorTextsin 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:

Suggested change
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',
};

Copy link
Owner

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 {

Copy link
Collaborator Author

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 😅

Comment on lines 11 to 18
const luciaLongSession = new Lucia(adapter, {
sessionExpiresIn: new TimeSpan(30, 'd'),
sessionCookie: {
attributes: {
secure: process.env.NODE_ENV === 'production',
},
},
});
Copy link
Collaborator Author

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 😄

Copy link
Owner

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;
Copy link
Collaborator Author

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

Copy link
Owner

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
Comment on lines 10 to 34
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,
};
},
});
Copy link
Collaborator Author

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

Copy link
Owner

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
Comment on lines 36 to 44
declare module 'lucia' {
interface Register {
Lucia: typeof lucia;
DatabaseUserAttributes: DatabaseUserAttributes;
DatabaseSessionAttributes: DatabaseSessionAttributes;
}
}
interface DatabaseUserAttributes extends User {}
interface DatabaseSessionAttributes extends CreateSession {}
Copy link
Collaborator Author

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

Suggested change
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 😄

Copy link
Owner

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ä.

Suggested change
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
Copy link
Collaborator Author

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_casella, osa kebab-casella ja osa sitten PascalCasella 🤣

Copy link
Owner

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.

Copy link
Collaborator Author

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ä bcryptin kanssa toimiessani 👍

Tosin tässä sitä ongelmaa nyt ei ole kun pari hassua riviä, mutta kuitenkin

Comment on lines +21 to +38
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,
},
};
}
Copy link
Collaborator Author

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 Nextin 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

Copy link
Owner

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.

Copy link
Collaborator Author

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
Comment on lines 21 to 24
return {
props: {
user: {},
},
Copy link
Collaborator Author

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 😄

Copy link
Owner

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: '/',
    },
  };
}

@anttiasmala anttiasmala changed the title WIP | Antti/login Antti | kirjautuminen ja rekistöröityminen sekä authentication Apr 18, 2024
Comment on lines +270 to +273
<div
className="fixed top-0 left-0 max-w-full w-full h-full bg-transparent"
onClick={() => closeUserWindow()}
/>
Copy link
Collaborator Author

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

Copy link
Owner

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 👍

Copy link
Owner

@samuliasmala samuliasmala left a 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.

pages/login.tsx Outdated Show resolved Hide resolved
Comment on lines +38 to +40
expiresAt DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
Copy link
Owner

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.

.env.example Outdated Show resolved Hide resolved
@anttiasmala
Copy link
Collaborator Author

anttiasmala commented Apr 20, 2024

Ilmeisesti Sessio-taulun migraatio on unohtunut PR:stä? Jos lisäät sen niin tsekkaan sitten PR:n.

Äsh, joo jäi migraatio tekemättä. Oon käyttänyt tuota npm run prisma db push:ia kehitysvaiheessa, sen takia unohdin tehdä migraation. Meikän moka, pahoittelut! Korjaan saman tien! 👍

EDIT: onko tätä komentoa järkevä käyttää npm run prisma db push?

@samuliasmala
Copy link
Owner

EDIT: onko tätä komentoa järkevä käyttää npm run prisma db push?

Kyllä on! Yleinen tapa on käyttää db push komentoa kun tekee muutosta/PR:ää, ja sitten lopuksi kun PR on valmis tekee migrate dev komennolla migraation. Näin ei tule miljoonaa migraatiotiedostoa testauksista, vaan yksi lopullisesta versiosta.

Prisman dokumentaatiossa:

Use db push to prototype a change to an existing schema, then run prisma migrate dev to generate a migration from your changes (you will be asked to reset)

@anttiasmala
Copy link
Collaborator Author

Nyt on korjattu. Testailin itse ja näytti sekä migrate reset että migrate deploy toimivan 👍

Copy link
Owner

@samuliasmala samuliasmala left a 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.

Comment on lines +8 to +10
const checkedEmailAddress = email.toLowerCase().match(emailRegex);

if (!checkedEmailAddress) {
Copy link
Owner

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)

Suggested change
const checkedEmailAddress = email.toLowerCase().match(emailRegex);
if (!checkedEmailAddress) {
if (!email.toLowerCase().match(emailRegex)) {

backend/auth.ts Outdated
Comment on lines 36 to 44
declare module 'lucia' {
interface Register {
Lucia: typeof lucia;
DatabaseUserAttributes: DatabaseUserAttributes;
DatabaseSessionAttributes: DatabaseSessionAttributes;
}
}
interface DatabaseUserAttributes extends User {}
interface DatabaseSessionAttributes extends CreateSession {}
Copy link
Owner

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ä.

Suggested change
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;
}
}

Comment on lines +17 to +33
getUserAttributes({
createdAt,
email,
firstName,
lastName,
updatedAt,
uuid,
}: User): User {
return {
uuid: uuid,
firstName: firstName,
lastName: lastName,
email: email,
createdAt: createdAt,
updatedAt: updatedAt,
};
},
Copy link
Owner

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:

Suggested change
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
Comment on lines 10 to 34
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,
};
},
});
Copy link
Owner

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 }> {
Copy link
Owner

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';

Suggested change
): Promise<{ user: User; session: Session } | { user: null; session: null }> {
): Promise<{ user: LuciaUser; session: Session } | { user: null; session: null }> {

Comment on lines +21 to +38
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,
},
};
}
Copy link
Owner

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,
Copy link
Owner

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)}
Copy link
Owner

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 👍

Comment on lines 26 to 36
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',
};
Copy link
Owner

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
Copy link
Owner

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants