CT3T Stack - Webfejlesztés 2023-ban
Mit is jelent ez pontosan?
A CT3T Stack a T3 egy újabb változata, mely tartalmaz további eszközöket és megoldásokat, amelyeket hétköznapi webes és mobilfejlesztés során használunk. A teljesség igénye nélkül a T3 stack legjobb jellemzői összefoglalhatók azzal, hogy a Type-safetyre, azaz szigorúan tipizált kódra és end-to-end biztonságra törekszik. A projekt minden pontja Typescriptet használ és a backenddel való kommunikáció REST helyett tRPC segítségével történik. Ezzel biztosítható, hogy nem kell kliens oldalon újra definiálnunk a backendes típus interface-eket, helyette a Typescript mágiával a kliens a backend procedúráiból következteti ki a típusokat.
Ez a T3 Stack néhány mondatos megfogalmazása, ennél lényegesen bővebben a stack oldalán olvashatunk.
Julius Marminge a T3 Stacket, amely alapvetően csak egy NextJS alapú full-stack framework, és a mobilfejlesztés feltörekvő keretrendszerét, az Expot ötvözve elkészítette a a create-t3-turbo stacket, amely kódja és dokumentáció az alábbi repoban megtalálható. Ezt a két technológiát egy Turborepo formájában ötvözi, amellyel felgyorsíthatóak a buildelési folyamatok és struktúráltabb projekteket készíthetünk a workspace-ek segítségével.
A create-t3-turbo stack alapján készítettem el a CT3T-t azzal a céllal, hogy megoldást kínáljak az olyan problémákra, amelyek minden projekt megkezdésekor megjelennek. A CT3T tekinthető egy fejlett, sokrétű boilerplate projektnek, ami tulajdonképpen igaz is. Most pedig vágjunk bele, miket is tartalmaz a CT3T!
A CT3T Stack
pnpm helyett npm
A pnpm egy remek csomagkezelő, amely elsősorban a cache rendszeréről és gyorsaságáról híres. Mégis, ebben a projektben az npm-et használjuk, mert úgy gondolom, hogy a legtöbb fejlesztő még sosem használta, így csapatmunka esetén megkönnyíti a beilleszkedést, ha legalább a package manager ismert. Ezenkívül a pnpm workspace kezelése valamivel bonyolultabb, mint az npm és egyéb nem várt hibák is adódnak, amiket csak workaroundokkal tudunk megoldani, így tehát az npm-re esett a választásom.
Clerk integráció
A T3 csapata által kiválasztott jelenlegi authentikációs megoldás a Next-Auth (jelenleg Auth.js névre változik). Alapvetően ez egy jó megoldás, amennyiben kizárólag webre készülünk és nem kell mobilos hitelesítéssel foglalkoznunk. A CT3T pedig nagyban leglaább olyanannyira van mobilra tervezve, mint webre, így alternatív megoldásra volt szükség.
A bejelentkezés, felhasználói profilok kezelése és a session management mindig nagy fejtörést okoz a fejlesztőknek. Semmiképp nem ajánlott saját megoldást készíteni többek között a karbantarthatóság, a biztonsági kockázatok, na és persze a munkaórák száma miatt is, így a Clerk nagyon jó választás lehet.
Egyszerű, mégis nagyszerű megoldást kínál nekünk a Clerk mind kliens oldalon (weben és mobilon egyaránt!), mind backend oldalon.
RBA, azaz Role-based access
Modern webaplikációkban gyakori a felhasználói szerepek kezelése és a hozzájuk tartozó jogosultságok. A CT3T-ben a NextJS getServerSideProps logikájának kiterjesztésével védjük le az oldalakat és biztosítjuk a kliens számára a bejelentkezett felhasználó profilját az adatbázisban található adatokkal.
Használata egyszerű, az alábbi példa alapján hozzunk létre egy új oldalt a next/src/pages mappában.
import { Role } from "@packages/db";
import { api } from "~/utils/api";
import { requireAuth, type ProtectedPage } from "~/utils/auth";
const ProtectedPage: ProtectedPage = ({ user }) => {
return (
<h1>Bejelentkezett felhasználó: {user.name}<h1>
);
};
export const getServerSideProps = requireAuth(Role.ADMIN);
export default ProtectedPage;
Adatbázis szinten minden User-hez tartozik egy **clerkId** mező, amely a Clerk által generált azonosító és egy role, ami megfelel Role enum, amit a requireAuth metódusban használunk a megfelelő jogusultsági szint megadására. A ProtectedPage típus használatával a user prop a prisma által generált User típusú objektum lesz.
A funkció implementációja megtalálható a utils/auth.ts fájlban.
Hasonlóan egyszerű megközelítéssel védhetjük le a backend procedúráinkat is. A api/src/procedures fájlban megtalálható a createProtectedProcedure függvény, amely egy function factory és olyan védett procedúrát ad vissza, amelyet bármelyik tRPC routerben lehet használni, csakúgy, mint a publicProcedure-t.
Új védett procedúrához az alábbi sort adjuk hozzá a api/src/trpc.ts fájl végére:
export const adminProcedure = createProtectedProcedure(Role.ADMIN);
A frontendhez hasonlóan a Role enumot használjuk a jogosultság megadására. Ha több role-hoz szeretnénk hozzárendelni az oldalt, akkor a paramétert tömbként adjuk át.
export const managementProcedure = requireAuth([Role.ADMIN, Role.MANAGER]);
Hogyan tovább?
A cikk folytatása innentől fokozatosan fog megjelenni. A teljesség igénye nélkül a következő témák kerülnek bemutatásra: Ratelimiter Upstash segítségével, fájlok feltöltése és kezelése (S3), Cache logika, egyéb AWS szolgáltatások integrációja és még sok más, köztük architekturális kérdésekkel és bevált gyakorlatokkal.
[...]
Szerző: Sárffy Gergő
Publikálás dátuma: 2023. 05. 03.