Prisijungimo be slaptažodžio diegimas Next.js 13 projekte su NextAuth.js ir Prisma

be slaptažodžio
nextjs
nextauth
prisma
Prisijungimas be slaptažodžio naudojant NextJs 13 cover image

Šiame straipsnyje bus nagrinėjami veiksmai, kurių reikia norint įdiegti autentifikavimą be slaptažodžio Next.js projekte naudojant NextAuth.js biblioteką. Be to, norėdami tai pasiekti, naudosime Prisma kaip savo duomenų bazės adapterį.

Autentifikavimas be slaptažodžio yra novatoriškas metodas, kuris pašalina tradicinių vartotojo vardo ir slaptažodžio derinių poreikį. Vietoj to, ji siūlo saugesnę ir patogesnę autentifikavimo patirtį, naudodama alternatyvius metodus, tokius kaip el. pašto stebuklingos nuorodos arba vienkartiniai kodai, siunčiami SMS žinute.

Next.js yra populiari React sistema, skirta kurti žiniatinklio programas, žinoma dėl savo paprastumo ir efektyvumo. Į savo projektą galime lengvai įtraukti autentifikavimą be slaptažodžio, integruodami NextAuth.js – autentifikavimo biblioteką, specialiai sukurtą Next.js.

Be to, mes pasikliausime Prisma kaip mūsų duomenų bazės adapteriu. „Prisma“ yra ORM (Object-Relational Mapping) įrankis, kuris supaprastina duomenų bazių sąveiką, suteikdamas saugaus tipo ir automatiškai generuojamą užklausų kūrimo priemonę. Jis palaiko kelias duomenų bazes, įskaitant PostgreSQL, MySQL ir SQLite, todėl tai yra universalus pasirinkimas mūsų autentifikavimui įgyvendinti.

Šiame vadove pateiksime nuoseklias instrukcijas, kaip nustatyti ir konfigūruoti autentifikavimą be slaptažodžio naudojant NextAuth.js Next.js projekte. Taip pat parodysime, kaip integruoti Prisma kaip mūsų duomenų bazės adapterį, leidžiantį sklandžiai bendrauti tarp mūsų programos ir duomenų bazės.

Dabar išnagrinėsime, kaip pagerinti Next.js programos saugumą ir vartotojo patirtį naudojant autentifikavimą be slaptažodžio ir NextAuth.js bei Prisma galimybes. Pradėkime.

Kas yra prisijungimas be slaptažodžio?

Prisijungimas be slaptažodžio, kaip rodo pavadinimas, yra autentifikavimo metodas, kuris pašalina tradicinių vartotojo vardo ir slaptažodžio derinių poreikį. Vietoj to, jis naudoja alternatyvias vartotojo tapatybės patvirtinimo priemones, pvz., magiškas el. pašto nuorodas arba vienkartinius kodus, siunčiamus SMS žinute. Šis metodas turi keletą pranašumų, palyginti su tradiciniais prisijungimo būdais. Pirma, tai pašalina su slaptažodžiu susijusių pažeidžiamumų, pvz., silpnų slaptažodžių arba pakartotinio slaptažodžių naudojimo, riziką. Antra, tai supaprastina vartotojo patirtį, nes nebereikia atsiminti ir įvesti sudėtingų slaptažodžių.

Norint įgyvendinti beslaptažodžio prisijungimą naudojant magiškas el. pašto nuorodas arba vienkartinius kodus, mums reikia SMTP (paprasto pašto perdavimo protokolo) serverio.

SMTP serveris yra atsakingas už el. laiškų siuntimą internetu. Be slaptažodžio autentifikavimo kontekste serveris siunčia magiškas nuorodas arba vienkartinius kodus vartotojo registruotu el. pašto adresu. Kai vartotojas pradeda prisijungimo procesą, el. laiškas su unikalia nuoroda arba kodu sugeneruojamas ir siunčiamas vartotojui. Tada vartotojas gali spustelėti nuorodą arba įvesti kodą, kad užbaigtų autentifikavimo procesą. SMTP serveris veikia kaip tarpininkas tarp programos ir vartotojo el. pašto paslaugos, užtikrinantis saugų ir patikimą autentifikavimo pranešimų pristatymą. Naudodami SMTP serverį galime efektyviai įdiegti prisijungimą be slaptažodžio ir užtikrinti sklandų autentifikavimo patirtį savo vartotojams.

Pradėkime!

Pirmiausia turime sukurti naują Next.js projektą. Norėdami tai padaryti, naudokite šią komandą:

npx create-next-app@latest

Generating a new NextJS project

Sukūrę naują Next.js projektą, galite pereiti į naujai sukurtą projekto katalogą.

Pakeitę katalogą į projektą, galėsite tyrinėti įvairius aplankus ir failus, sudarančius Next.js projekto struktūrą.

Project Structure

Norint efektyviai kurti ir organizuoti Next.js programą, būtina suprasti projekto struktūrą. Remdamiesi oficialia dokumentacija, galite pasinaudoti geriausios praktikos pavyzdžiais ir gauti įžvalgų, kaip struktūrizuoti kodą, valdyti statinius išteklius ir sukurti daugkartinio naudojimo komponentus.

Priklausomybių diegimas

Norėdami įgalinti autentifikavimą be slaptažodžio mūsų Next.js projekte naudodami NextAuth.js, pirmiausia turime įdiegti reikiamas priklausomybes. Vykdykite komandą „yarn add next-auth nodemailer“, kad pridėtumėte NextAuth.js ir nodemailer į mūsų projektą.

Mes specialiai naudojame nodemailer, nes tai populiarus ir universalus modulis el. laiškų siuntimui Node.js. Tai yra paprastas ir patikimas būdas el. paštu siųsti stebuklingas nuorodas arba vienkartinius kodus, reikalingus autentifikavimui be slaptažodžio.

Tada integruokime Prisma kaip duomenų bazės adapterį. Pradėkite diegdami reikiamus Prisma paketus naudodami komandą:

yarn add @prisma/client @next-auth/prisma-adapter

Šie paketai įgalins sklandų ryšį tarp mūsų Next.js programos ir duomenų bazės. Be to, mes taip pat turime įdiegti Prisma kaip kūrėjo priklausomybę paleisdami:

yarn add prisma --dev

Šis veiksmas užtikrina, kad turime reikiamus įrankius, kad galėtume dirbti su „Prisma“ ir jos automatiškai sugeneruota užklausų kūrimo priemone sąveikai su duomenų baze.

Įdiegę šias priklausomybes sukūrėme pagrindą beslaptažodžio autentifikavimui, naudojant NextAuth.js ir Prisma, mūsų Next.js projekte.

Nustatykite Prisma

Norint naudoti beslaptažodžio autentifikavimą Next.js projekte, būtina nustatyti Prisma ir turėti prieigą prie SMTP serverio el. laiškų siuntimui. Ši instrukcija padės jums naudoti asmeninę „Gmail“ paskyrą el. laiškams siųsti. Atlikite toliau nurodytus veiksmus, kad sąranka būtų sėkminga.

Pirmiausia sukurkite aplanką „prisma“ projekto šaknyje. Šiame aplanke bus su Prisma susiję failai ir konfigūracijos. Tada aplanke „prisma“ sukurkite naują failą pavadinimu „schema.prisma“. Schemos failas apibrėžia jūsų duomenų bazės struktūrą ir naudojamas kaip „Prisma“ automatiškai generuojamo kodo planas.

Jei schemos sąvoka dar nepažįstama, nesijaudinkite! Schema nurodo duomenų bazės lenteles, laukus, ryšius ir apribojimus. Norėdami sukurti schemą, galite peržiūrėti oficialią NextAuth.js dokumentaciją ir nukopijuoti ten pateiktą schemos pavyzdį. Ši schema yra pradinis taškas ir gali būti pritaikytas pagal jūsų programos reikalavimus.

Schema file

Tada projekto šaknyje sukurkite failą „.env“. Šiame faile bus saugomi aplinkos kintamieji, įskaitant būtinas SMTP serverio konfigūracijas. Norėdami užpildyti failą „.env“, galite nukopijuoti toliau pateiktas konfigūracijos pavyzdžius. Atitinkamuose laukuose būtinai įveskite „Gmail“ paskyros kredencialus ir SMTP serverio nustatymus.

EMAIL_SERVER_USER="YourGmailAddress"
EMAIL_SERVER_PASSWORD="GmailPassOrGeneratedPass"
EMAIL_SERVER_HOST=smtp.gmail.com
EMAIL_SERVER_PORT=587
EMAIL_FROM="noreply@example.com"

NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=ThisNeedsToBeSuperSecret

Atlikę šiuos veiksmus, nustatysite „Prisma“ ir sukonfigūravote SMTP serverį el. laiškų siuntimui naudojant „Gmail“ paskyrą. Šie parengiamieji darbai yra labai svarbūs įgalinant autentifikavimo be slaptažodžio srautą jūsų Next.js projekte.

Pastaba

Jei „Google“ paskyroje įgalinote dviejų faktorių autentifikavimą (2FA), turite sukurti programos slaptažodį. Programos slaptažodis yra atskiras slaptažodis, suteikiantis prieigą prie konkrečių programų ar įrenginių neatskleidžiant pagrindinio „Google“ paskyros slaptažodžio. Vykdykite toliau pateiktas instrukcijas, kad sugeneruotumėte programos slaptažodį.

  1. Eikite į „Google“ paskyros nustatymų puslapį apsilankę adresu https://myaccount.google.com/.

  2. Eikite į skirtuką „Sauga“.

  3. Ieškokite skilties „2FA“, slinkite žemyn ir pasirinkite „Programų slaptažodžiai“.

Google Account Security

Google Account Security

  1. Gali būti, kad būsite paraginti dar kartą įvesti „Google“ paskyros slaptažodį, kad patikrintumėte saugumą.

  2. Išskleidžiamajame meniu „Pasirinkti programą“ pasirinkite „Paštas“ arba „Kita (tinkintas pavadinimas)“.

  • Jei yra parinktis „Paštas“, pasirinkite ją.

  • Jei parinktis „Paštas“ nepasiekiama, pasirinkite „Kita (priskirtas pavadinimas)“ ir pateikite pasirinktinį identifikavimo pavadinimą.

  1. Spustelėkite mygtuką „Generuoti“ arba „Generuoti slaptažodį“.

  2. „Google“ sugeneruos jums unikalų programos slaptažodį. Užsirašykite šį slaptažodį, nes jį naudosime savo programoje el. laiškų siuntimui.

  3. Naudokite šį sugeneruotą programos slaptažodį Next.js programos SMTP serverio konfigūracijoje. Pakeiskite įprastą „Gmail“ paskyros slaptažodį šiuo programos slaptažodžiu.

Tai užtikrina, kad net ir įjungus 2FA, jūsų programa gali saugiai siųsti el. laiškus naudojant jūsų Gmail paskyrą.

PostgreSQL naudojant Supabase

Prieš tęsdami, turime užtikrinti, kad mūsų projekto duomenų bazė tinkamai veiktų. Šiam demonstravimui rekomenduojame naudoti Supabase PostgreSQL duomenų bazę. Norėdami pradėti su Supabase projektu ir gauti PostgreSQL ryšio URL, atlikite šiuos veiksmus:

  1. Eikite į supabase.io ir prisijunkite prie savo paskyros arba sukurkite naują, jei jos neturite.

  2. Kai būsite prisijungę, būsite nukreipti į „Supabase“ prietaisų skydelį. Spustelėkite „Sukurti naują projektą“, kad pradėtumėte naują projektą.

  3. Pavadinkite savo projektą ir pasirinkite regioną, esantį arčiausiai jūsų dabartinės vietos. Prisiminkite slaptažodį, jo prireiks vėliau.

  4. Sukūrę projektą būsite nukreipti į projekto prietaisų skydelį. Spustelėkite "Duomenų bazė" kairėje šoninėje juostoje, kad pasiektumėte duomenų bazės nustatymus.

  5. Skiltyje „Duomenų bazė“ rasite PostgreSQL ryšio URL. Šiame URL yra visa reikalinga informacija, reikalinga norint prisijungti prie Supabase projekto duomenų bazės, pvz., priegloba, prievadas, duomenų bazės pavadinimas, vartotojo vardas ir slaptažodis. Jis bus rodomas tokiu formatu: postgres://<naudotojo vardas>:<slaptažodis>@<host>:<port>/<database>

Postgresql connection string

  1. Nukopijuokite PostgreSQL ryšio URL ir saugokite jį. Jums reikės norint užmegzti ryšį tarp programos ir Supabase duomenų bazės.
    // .env
    
    DATABASE_URL=postgresql://postgres:[Password]@db.ixjsisbwdafsjvgifliu.supabase.co:5432/postgres
    ```

Dabar įsitikinkime, kad sugeneruojame „Prisma“ klientą, vykdydami šią komandą: „npx prisma generate“.

„Prisma Client“ yra duomenų bazės klientas, automatiškai generuojamas pagal jūsų schemą. Pagal numatytuosius nustatymus „Prisma Client“ sugeneruojamas aplanke „node_modules/.prisma/client“, bet galite [jei reikia nurodyti tinkintą vietą](https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/generating-prisma-client#using-a-custom-output-path).

Toliau pradėsime kurti pradinį perkėlimą. Vykdykite šią komandą: „npx prisma migrate dev“. Kiekvienai perkėlimui galite suteikti aprašomąjį pavadinimą.

„Prisma“ sistemoje perkėlimas yra metodas, naudojamas duomenų bazės schemos koregavimams valdyti laikui bėgant. Tai leidžia keisti duomenų bazės struktūrą neprarandant jokių iš anksto esančių duomenų. Šie perkėlimai yra labai svarbūs, nes užtikrina, kad jūsų duomenų bazės schema atitiktų jūsų programos poreikius, kai jie keičiasi. Naudodami „Prisma“ perkėlimo įrankį galite patogiai versijuoti, taikyti ir grąžinti šiuos pakeitimus, supaprastindami komandinį darbą ir palaikydami vienodą duomenų bazės schemą įvairiose aplinkose.

Dabar, jei patikrinsime savo duomenų bazę, pamatysime pradinio perkėlimo pokyčius, atsispindinčius duomenų bazės skiltyje.

Atlikdami pradinį perkėlimą pritaikėme duomenų bazės schemos pakeitimus, kaip apibrėžta perkėlimo scenarijuje.

![Database Tables after Migration](https://drive.google.com/uc?export=view&id=1PZ6ban5h4VZs3UHQoJS_5kNYkhqs-MAx)

### NextAuthJS nustatymas naudojant Prisma adapterį

„Next.js“ programoje „NextAuthJS“ naudoja fiksavimo maršrutą, dar vadinamą pakaitos simboliu arba atsarginiu maršrutu, kad tvarkytų autentifikavimo užklausas. Šis dinaminis maršrutas apibrėžiamas naudojant failais pagrįstą maršruto parinkimo sistemą Next.js.

Sukurkite aplanką pavadinimu „**api**“ savo „**app**“ kataloge. Aplanke „**api**“ sukurkite aplanką „**auth**“. Aplanke „**auth**“ kaip aplanką sukurkite išsamų maršrutą, pavadintą „**[...nextauth]**“. Galiausiai sukurkite „**route.ts**“ failą „pagrindinio maršruto“ aplanke ir pridėkite šį kodą.

```jsx
// app/api/auth/[...nextauth]/route.ts
import { PrismaAdapter } from '@next-auth/prisma-adapter';
import { PrismaClient } from '@prisma/client';
import NextAuth from 'next-auth';
import EmailProvider from 'next-auth/providers/email';

const prisma = new PrismaClient();

export const authOptions = {
  adapter: PrismaAdapter(prisma),
  providers: [
    EmailProvider({
      server: {
        host: process.env.EMAIL_SERVER_HOST,
        port: process.env.EMAIL_SERVER_PORT,
        auth: {
          user: process.env.EMAIL_SERVER_USER,
          pass: process.env.EMAIL_SERVER_PASSWORD,
        },
      },
      from: process.env.EMAIL_FROM,
    }),
  ]
};

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };

Surinktame maršruto faile importuojame NextAuthJS biblioteką ir nustatome autentifikavimo parinktis, teikėjus ir konfigūracijas. NextAuthJS tvarko gaunamų užklausų analizę, nustato būtiną autentifikavimo veiksmą ir pagal nurodytas parinktis vykdo atitinkamą logiką.

Pateiktas kodas nustato NextAuthJS su Prisma adapteriu autentifikavimui naudojant el. pašto teikėją. Paaiškinkime kiekvieną teiginį:

  1. Importas:

PrismaAdapter ir PrismaClient importuojami atitinkamai iš @next-auth/prisma-adapter ir @prisma/client. Jie naudojami „NextAuthJS“ integravimui su „Prisma“.

  • NextAuth yra importuota iš next-auth ir yra pagrindinė biblioteka, skirta autentifikavimui tvarkyti Next.js programose.

EmailProvider importuojamas iš next-auth/providers/email ir naudojamas kaip autentifikavimo el. paštu teikėjas.

  1. Prisma sąranka:
  • PrismaClient egzempliorius sukuriamas naudojant new PrismaClient(). Tai leidžia bendrauti su Prisma ORM ir pagrindine duomenų baze.
  1. Autentifikavimo parinktys:
  • authOptions yra objektas, apibrėžiantis autentifikavimo konfigūraciją NextAuthJS.

– Ypatybė adapteris nustatyta į PrismaAdapter(prisma), kuri sujungia NextAuthJS su Prisma naudojant PrismaAdapter.

– Masyve providers yra vienas teikėjas EmailProvider. Jis sukonfigūruotas naudojant reikiamą el. pašto serverio informaciją ir nuo el. pašto adresą.

  1. NextAuth Handler:
  • Funkcija NextAuth iškviečiama su authOptions kaip argumentu, sukuriant autentifikavimo tvarkyklę.

  • Gautas tvarkytuvas priskiriamas kintamajam handler.

  1. Eksportuoti:

handler eksportuojamas kaip GET ir POST, kad būtų palaikomos ir HTTP GET, ir POST užklausos.

Dabar paleiskime serverį ir išbandykime jo funkcionalumą. Pirmiausia paleiskite kūrimo serverį paleisdami „yarn dev“. Tada atidarykite naršyklę ir apsilankykite „localhost:3000“, kad pamatytumėte, kaip veikia programa.

Norėdami išbandyti autentifikavimo funkcijas, apsilankykite „localhost:3000/api/auth/signin“. Čia patirsite NextAuthJS magiją. Pateiktas šablonas, įtrauktas į NextAuthJS, leidžia prisijungti be slaptažodžio. Norėdami išbandyti, įveskite galiojantį el. pašto adresą.

Passwordless Signin Input

Kai pateiksite el. laišką, NextAuthJS atliks užkulisinį procesą. Pirmiausia jis sugeneruos ir nurodytu el. pašto adresu išsiųs el. laišką su unikalia prisijungimo nuoroda. Ši nuoroda tarnauja kaip saugus vartotojo autentifikavimo prieigos raktas. Tada, kai vartotojas spustelėja nuorodą, NextAuthJS patvirtins prieigos raktą ir autentifikuos vartotoją.

Signin Email

Ši beslaptažodžio prisijungimo funkcija padidina saugumą ir vartotojo patirtį, nes nebereikia slaptažodžių. Vartotojai gali greitai ir saugiai pasiekti savo paskyras tiesiog spustelėdami el. paštu gautą nuorodą. Tai supaprastina prisijungimo procesą ir sumažina su slaptažodžiu susijusių pažeidžiamumų riziką.

Kai vartotojas spustelėja „NextAuthJS“ sugeneruotą prisijungimo el. laišką ir patvirtinamas, užkulisiuose atliekami keli veiksmai, palengvinantys sklandų prisijungimą.

1. El. pašto nuorodos patvirtinimas: naudotojui spustelėjus prisijungimo nuorodą, NextAuthJS patvirtina nuorodoje įdėtą autentifikavimo prieigos raktą. Šis prieigos raktas užtikrina autentifikavimo proceso saugumą ir vientisumą.

2. Autentifikavimo procesas: sėkmingai patvirtinus prieigos raktą, NextAuthJS identifikuoja naudotoją ir užbaigia autentifikavimo procesą. Jis patikrina vartotojo tapatybę pagal pateiktą prieigos raktą ir visus sukonfigūruotus papildomus autentifikavimo veiksnius, pvz., kelių veiksnių autentifikavimą.

3. Seanso kūrimas: po sėkmingo autentifikavimo „NextAuthJS“ sukuria naudotojo seansą. Seansas yra nuolatinė būsena, nurodanti vartotojo autentifikavimo būseną ir leidžianti pasiekti apsaugotus išteklius, nereikalaujant iš naujo autentifikuoti vėlesnių užklausų.

4. Slapukai: „NextAuthJS“ nustato saugius tik HTTP slapukus naudotojo naršyklėje, kad galėtų valdyti seansą. Šie slapukai atlieka labai svarbų vaidmenį išlaikant vartotojo autentifikuotą būseną keliose užklausose. Slapukai paprastai apima seanso slapuką ir pasirinktinai atnaujinimo prieigos rakto slapuką, atsižvelgiant į autentifikavimo konfigūraciją.

Cookies Set By NextAuthJS

  1. Seanso slapukas: seanso slapuke yra seanso identifikatorius (pvz., atsitiktinai sugeneruota eilutė), kuris unikaliai identifikuoja naudotojo seansą. Tai padeda NextAuthJS susieti paskesnes užklausas su tinkama sesija ir vartotoju.

  2. CSRF prieigos rakto slapukas: „NextAuthJS“ nustato CSRF (angl. Cross-Site Request Forgery) prieigos rakto slapuką, kad apsaugotų nuo CSRF atakų. CSRF prieigos raktas yra unikali reikšmė, sugeneruota NextAuthJS ir saugoma slapuke. Jis naudojamas patvirtinti ir patikrinti vėlesnių vartotojo pateiktų užklausų autentiškumą. Kai vartotojas pateikia formas arba atlieka neskelbtinus veiksmus, CSRF prieigos raktas įtraukiamas į užklausos antraštes arba turinį, siekiant užtikrinti, kad užklausa kilusi iš autentifikuoto vartotojo seanso, o ne iš kenkėjiško šaltinio.

  3. Atšaukimo URL slapukas: NextAuthJS nustato atgalinio iškvietimo URL slapuką, kad išsaugotų pradinį URL, kurį vartotojas bandė pasiekti prieš nukreipdamas į autentifikavimo eigą. Šis slapukas padeda NextAuthJS nukreipti vartotoją atgal į norimą puslapį po sėkmingo autentifikavimo. Tai užtikrina sklandžią naudotojo patirtį, sklandžiai grąžindama vartotoją į numatytą paskirties vietą, o ne į bendrą nukreipimo puslapį.

Naudodama saugius tik HTTP slapukus, NextAuthJS užtikrina, kad autentifikavimo būsena išliktų saugi ir apsaugota nuo klastojimo. Slapukai yra užšifruoti, užkertant kelią neteisėtai prieigai ar piktybiniams veikėjams, kad jie negalėtų jų keisti.

Puikus darbas sėkmingai integruojant NextAuthJS su Prisma adapteriu į Next.js programą! „NextAuthJS“ lengvai ir lengvai pritaikoma, todėl dabar turite patikimą autentifikavimo sistemą.

Šiame vadove naudojamo kodo ieškokite toliau pateiktoje „GitHub“ saugykloje: https://github.com/codelabsacademy/next-auth-guide.

Bet kam čia sustoti? Jei domitės žiniatinklio kūrimu ir trokštate tobulinti savo įgūdžius, apsvarstykite galimybę kreiptis į mūsų žiniatinklio kūrimo stovyklą. Mūsų „Bootcamp“ siūlo visapusišką mokymosi patirtį, suteikiančią jums žinių ir praktinių įgūdžių, reikalingų tobulėti dinamiškame interneto kūrimo pasaulyje.

Prisijungę prie mūsų „Bootcamp“ įgysite praktinės patirties su pažangiausiomis technologijomis, dirbsite su realaus pasaulio projektais ir gausite asmenines pramonės ekspertų rekomendacijas. Nesvarbu, ar esate pradedantysis, ar patyręs kūrėjas, mūsų programa sukurta siekiant pakelti jūsų žiniatinklio kūrimo įgūdžius į kitą lygį.

Nepraleiskite šios progos paspartinti žiniatinklio kūrimo kelionę. Pateikite paraišką dalyvauti mūsų žiniatinklio kūrimo stovykloje šiandien ir išlaisvinkite visą savo potencialą įdomioje žiniatinklio kūrimo srityje. Kartu kurkime nuostabią skaitmeninę patirtį ir kurkime žiniatinklio ateitį.


Career Services background pattern

Karjeros paslaugos

Contact Section background image

Palaikykime ryšį

Code Labs Academy © 2024 Visos teisės saugomos.