কম্পিউটার টিউটোরিয়াল

লুসিয়া, প্ল্যানেটস্কেল এবং আপস্ট্যাশ রেডিসের সাথে SvelteKit-এ সুরক্ষিত, টাইপ-নিরাপদ প্রমাণীকরণ

আপস্ট্যাশ ব্লগে আমাদের শেষ গাইডের পরে বাইটস নিউজলেটারে একটি স্পট স্কোর করেছে , আমি ভেবেছিলাম আমরা SvelteKit পার্টি চালু রাখব।

একজন Svelte সুপার ফ্যান হিসাবে, আমি প্রতিদিন আরও বেশি সংখ্যক লোককে বোর্ডে ঝাঁপিয়ে পড়তে দেখছি — এবং এটি আমাকে ভবিষ্যতের জন্য অবিশ্বাস্যভাবে উত্তেজিত করে তোলে৷

রাডারের নিচে যে টুলগুলো এখনও উড়ছে তার মধ্যে একটি হল লুসিয়া।

এই নির্দেশিকায় আমি আপনাকে দেখাতে যাচ্ছি কিভাবে প্রমাণীকরণ করা যায় এবং লুসিয়ার সাথে চলতে হয়। আমরা আমাদের ডাটাবেসের প্রয়োজনের জন্য প্ল্যানেটস্কেল এবং সেশনগুলি পরিচালনা করার জন্য Upstash Redis ব্যবহার করব৷

নীচে এই গাইডের জন্য আমাদের শেষ লক্ষ্যের একটি স্ক্রিনশট রয়েছে। আপনি এখানে উদাহরণ সংগ্রহস্থল খুঁজে পেতে পারেন.

লুসিয়া, প্ল্যানেটস্কেল এবং আপস্ট্যাশ রেডিসের সাথে SvelteKit-এ সুরক্ষিত, টাইপ-নিরাপদ প্রমাণীকরণ

এই গাইডটি SvelteKit-এ থাকবে, কিন্তু যেহেতু লুসিয়া যেকোন ফ্রেমওয়ার্ক সমর্থন করে, তাই এই গাইডের বেশিরভাগই সহজেই সেখানকার যেকোনো জনপ্রিয় ফ্রেমওয়ার্কে প্রয়োগ করা যেতে পারে।

লুসিয়া কি?

সহজ কথায় বলতে গেলে, লুসিয়া হল টাইপস্ক্রিপ্টের জন্য একটি লাইব্রেরি যা ব্যবহারকারীদের পরিচালনা এবং সেশনগুলিকে কেকের একটি টুকরো করে তোলে৷ মূলত, এই লাইব্রেরিটি SvelteKit-এর জন্য তৈরি করা হয়েছিল, কিন্তু এটি ক্রমাগত বিকশিত হয়েছে এবং এখন যে কোনও কাঠামোর সাথে ভাল খেলতে যথেষ্ট বহুমুখী৷

লুসিয়া সম্পর্কে যা অসাধারণ তা হল এটি ব্যবহারকারীর অভিজ্ঞতাকে ত্যাগ না করে প্রমাণীকরণের জটিলতা পরিচালনা করার জন্য আপনার প্রয়োজনীয় সমস্ত কিছু দিয়ে কীভাবে সজ্জিত করে৷ লুসিয়াকে আদিমগুলির একটি সেট হিসাবে ভাবুন - এটি আপনার উপর নির্ভর করে আপনি কীভাবে আপনার কোড গঠন করতে চান এবং ব্যবহারকারীর অভিজ্ঞতা পরিচালনা করতে চান৷ লুসিয়ার কয়েকটি মূল অংশ রয়েছে যা বোঝা গুরুত্বপূর্ণ:

মিডলওয়্যার  লুসিয়াকে বিভিন্ন ফ্রেমওয়ার্ক এবং রানটাইমের জন্য অনুরোধ এবং প্রতিক্রিয়া পড়ার অনুমতি দেয়।

আপনি কিভাবে মিডলওয়্যার কনফিগার করবেন তার একটি উদাহরণ এখানে দেওয়া হল:

import { lucia } from "lucia";
import { node } from "lucia/middleware";
 
// import { nextjs } from "lucia/middleware";
// import { h3 } from "lucia/middleware";
 
export const auth = lucia({
 env: "DEV", // "PROD" if deployed to HTTPS
 middleware: node(),
});

ডেটাবেস অ্যাডাপ্টার লুসিয়াকে ব্যবহারকারী এবং সেশন সংরক্ষণ এবং পুনরুদ্ধার করার অনুমতি দিন। একটি অ্যাডাপ্টার প্রদান করে লুসিয়া জানে কিভাবে এই ধরনের জন্য অনুসন্ধান করতে হয়। অ্যাডাপ্টার 2 ধরনের আছে; নিয়মিত অ্যাডাপ্টার, এবং সেশন অ্যাডাপ্টার। এই বিশেষ নির্দেশিকায় আমরা আমাদের ব্যবহারকারীদের সংরক্ষণ করার জন্য PlanetScale-এ হোস্ট করা একটি mySQL ডাটাবেস এবং সেশনগুলি পরিচালনা করার জন্য Upstash-এ হোস্ট করা একটি Redis উদাহরণ ব্যবহার করতে যাচ্ছি৷

আপনি কিভাবে একটি ডাটাবেস অ্যাডাপ্টার কনফিগার করবেন তার একটি উদাহরণ এখানে দেওয়া হল:

import { prisma } from "@lucia-auth/adapter-prisma";
import { PrismaClient } from "@prisma/client";
import { lucia } from "lucia";
 
const client = new PrismaClient();
 
const auth = lucia({
 env: "DEV",
 adapter: prisma(client),
});

সেই পটভূমির তথ্য দিয়ে, আসুন সরাসরি ভিতরে ঝাঁপিয়ে পড়ি।

পূর্বশর্ত

অ্যাপের সাথে উঠতে এবং চলতে এবং অনুসরণ করতে আপনার প্রয়োজন:

  • SvelteKit এর একটি মৌলিক উপলব্ধি। ফর্ম এবং রাউটিং হ্যান্ডলিং একটি প্লাস।
  • Rrizzle ORM এর সাথে প্রাথমিক পরিচিতি।
  • প্ল্যানেটস্কেলে একটি অ্যাকাউন্ট এবং ডাটাবেস।
  • একটি রেডিস ইনস্ট্যান্সে অ্যাক্সেস, উদাহরণস্বরূপ, আপস্ট্যাশ রেডিস।

শুরু করা

দক্ষতার জন্য, আমরা স্ক্র্যাচ থেকে সম্পূর্ণ অ্যাপ্লিকেশন তৈরি করব না।

পরিবর্তে, আপনি sveltekit-lucia-redis ক্লোন করতে পারেন অনুসরণ করার জন্য Upstash উদাহরণ রেপো থেকে ডিরেক্টরি।

সংগ্রহস্থল ডাউনলোড করার পরে, cd ব্যবহার করে অ্যাপ্লিকেশনটিতে নেভিগেট করুন আপনার পছন্দের প্যাকেজ ম্যানেজারের মাধ্যমে নির্ভরতাগুলিকে কমান্ড এবং ইনস্টল করুন এবং .env সেট করুন .env.example নকল করে ভেরিয়েবল .

মূল অংশগুলি বোঝা

এখানে সমস্ত গুরুত্বপূর্ণ অংশগুলির একটি দ্রুত রানডাউন রয়েছে৷

  • src/lib/server/auth/index.ts - এখানে আমরা লুসিয়া কনফিগার করি।
  • src/lib/server/drizzle - ড্রিজল আমাদের সহজেই একটি মাইএসকিউএল স্কিমা তৈরি করতে সাহায্য করে যা আমরা ড্রিজেল কিট ব্যবহার করে সুবিধামত প্ল্যানেটস্কেলে ঠেলে দিতে পারি।
  • src/lib/server/planetscale - আপস্ট্যাশ ক্লায়েন্ট রপ্তানি করে যা আমরা ব্যবহারকারীদের পরিচালনা করতে আমাদের লুসিয়া অ্যাডাপ্টার কনফিগারে ব্যবহার করি৷
  • src/lib/server/upstash - আপস্ট্যাশ ক্লায়েন্ট রপ্তানি করে যা আমরা সেশনগুলি পরিচালনা করতে আমাদের লুসিয়া অ্যাডাপ্টার কনফিগারে ব্যবহার করি৷

কোড ভাঙা

লুসিয়া কনফিগার করা হচ্ছে

আমাদের প্রথম জিনিসটি লুসিয়া কনফিগার করতে হবে। আমরা src/lib/server/auth/index.ts এ একটি নতুন ফাইল তৈরি করে এটি করতে পারি .

src/lib/server/auth/index.ts
import { planetscale } from "@lucia-auth/adapter-mysql";
import { dev } from "$app/environment";
import { lucia } from "lucia";
import { sveltekit } from "lucia/middleware";
 
import { ps } from "../planetscale";
 
export enum PROVIDER_ID {
 EMAIL = "email",
}
 
export const auth = lucia({
 adapter: {
 user: planetscale(ps, {
 user: "users",
 key: "keys",
 /**
 * Sessions are handled by Upstash Redis.
 */
 session: null,
 }),
 },
 middleware: sveltekit(),
 env: dev ? "DEV" : "PROD",
 getUserAttributes: (data) => {
 return {
 userId: data.id,
 email: data.email,
 };
 },
});
 
export type Auth = typeof auth;

এখানে কি ঘটছে তার একটি দ্রুত রানডাউন এখানে:

আমরা lucia আমদানি করি lucia থেকে ফাংশন লুসিয়ার জন্য কনফিগারেশন সেট আপ করার জন্য প্যাকেজ।

আমরা প্রথমেই adapter কনফিগার করি সম্পত্তি এখানেই আমরা লুসিয়াকে বলি কিভাবে ব্যবহারকারী এবং সেশন পরিচালনা করতে হয়।

আমরা সেশন প্রপার্টি null সেট করেছি কারণ আমরা সেশন পরিচালনা করতে Redis ব্যবহার করতে চাই। আপনি যদি 'session' স্ট্রিং ব্যবহার করেন এখানে পরিবর্তে, লুসিয়া ব্যবহারকারী এবং সেশন উভয়ের জন্য একই অ্যাডাপ্টার ব্যবহার করবে (এই স্ট্রিংগুলি আপনার ডাটাবেসের টেবিলের সাথে মিলে যায়)।

আপাতত সেশন অ্যাডাপ্টার নিয়ে চিন্তা করবেন না, আমরা পরে সেটা নিয়ে যাব।

middleware-এ সম্পত্তি আমরা লুসিয়াকে জানাতে পারি যে আমরা SvelteKit ব্যবহার করছি। এটি লুসিয়াকে অনুরোধ এবং প্রতিক্রিয়া বিষয়গুলি পড়তে অনুমতি দেবে৷

রপ্তানি করা Auth নোট নিন টাইপ এটি আমাদের auth এর ধরন বস্তু SvelteKit স্থানীয়দের সেট আপ করতে আমাদের এটির প্রয়োজন হবে।

লুসিয়ার সাথে দুর্দান্ত ধরনের অনুমান পাওয়া

লুসিয়া টাইপস্ক্রিপ্টে লেখা হয়েছে, তাই আপনি বাক্সের বাইরে দুর্দান্ত টাইপ ইনফারেন্স পাবেন। আসুন নিশ্চিত করুন যে SvelteKit Auth সম্পর্কে জানে টাইপ আমরা এইমাত্র তৈরি করেছি।

আপনার app.d.ts খুলুন ফাইল এবং নিম্নলিখিত যোগ করুন:

src/app.d.ts
import type { Auth as LuciaAuth } from "$lib/server/auth";
import type { AuthRequest, Session, User } from "lucia";
 
declare global {
 namespace App {
 // interface Error {}
 interface Locals {
 auth: AuthRequest;
 session: Session | null;
 }
 interface PageData {
 user?: User;
 }
 // interface Platform {}
 }
}
 
/// <reference types="lucia" />
declare global {
 namespace Lucia {
 type Auth = LuciaAuth;
 type DatabaseUserAttributes = {
 email: string;
 };
 type DatabaseSessionAttributes = {};
 }
}
 
export {};

Auth যোগ করে Lucia এ টাইপ করুন নামস্থান, আমরা এখন auth অ্যাক্সেস করতে পারি locals থেকে বস্তু আমাদের SvelteKit রুটে অবজেক্ট।

তবে লুসিয়া থেকে আমদানি করা যেকোনো কিছুরও এখন সঠিক ধরন থাকবে।

এখন যেহেতু আমাদের এই ধরনের আছে, আমরা hooks.server.ts সেট আপ করতে পারি . এখানেই আমরা AuthRequest বাঁধব এবং Session বর্তমান অনুরোধে আপত্তি।

এটি locals এর মাধ্যমে সার্ভারে এটিকে সহজে অ্যাক্সেসযোগ্য করে তুলবে .

src/hooks.server.ts
import type { Handle } from "@sveltejs/kit";
import { sequence } from "@sveltejs/kit/hooks";
import { auth } from "$lib/server";
 
const auth_handle: Handle = async ({ event, resolve }) => {
 event.locals.auth = auth.handleRequest(event);
 event.locals.session = await event.locals.auth.validate();
 
 return resolve(event);
};
 
export const handle = sequence(auth_handle);

আমরা sequenceও আমদানি করব যা একটি সহায়ক ফাংশন যা আমাদেরকে ক্রমানুসারে একাধিক হুক চালাতে দেয়। আমরা যখন আমাদের রুটগুলিকে সুরক্ষিত করার চেষ্টা করি তখন এটি কার্যকর হবে৷

ব্যবহারকারী মডেল তৈরি করা হচ্ছে

এখন আমরা লুসিয়া কনফিগার করেছি, আমরা আমাদের ব্যবহারকারী মডেল তৈরি করতে পারি।

আমরা ড্রিজল ওআরএম ব্যবহার করব, যেহেতু এখনই সব গরম এবং ঘটছে৷

লুসিয়া, প্ল্যানেটস্কেল এবং আপস্ট্যাশ রেডিসের সাথে SvelteKit-এ সুরক্ষিত, টাইপ-নিরাপদ প্রমাণীকরণ

এবং তাদের মেমগুলি পয়েন্টে রয়েছে৷ শুধু এটি দেখুন৷

আপনি চালিয়ে যাওয়ার আগে, আপনাকে PlanetScale-এ একটি ডাটাবেস তৈরি করতে হবে। এবং Drizzle কনফিগারেশন ফাইল সেটআপ করুন। এটি ড্রিজল CLI কে আপনার ডাটাবেসের সাথে সংযোগ করতে সাহায্য করবে।

drizzle.config.ts
import dotenv from "dotenv";
import type { Config } from "drizzle-kit";
 
dotenv.config();
 
const username = process.env.DATABASE_USERNAME;
const password = process.env.DATABASE_PASSWORD;
const host = process.env.DATABASE_HOST;
const db = process.env.DATABASE_NAME;
const connectionString = `mysql://${username}:${password}@${host}/${db}?ssl={"rejectUnauthorized":true}`;
 
export default {
 schema: "./src/lib/server/drizzle/schema/index.ts",
 driver: "mysql2",
 dbCredentials: {
 connectionString: connectionString,
 },
} satisfies Config;

যেহেতু আমরা মাইএসকিউএল অ্যাডাপ্টার ব্যবহার করছি, লুসিয়া আশা করে যে আমাদের ব্যবহারকারী মডেলের একটি নির্দিষ্ট কাঠামো থাকবে। আপনি ডক্সে এই সম্পর্কে আরও তথ্য পেতে পারেন৷

নিম্নলিখিত কোডটি src/lib/server/drizzle/schema/index.ts-এ রাখুন .

src/lib/server/drizzle/schema/index.ts
import { relations } from "drizzle-orm";
import {
 bigint,
 datetime,
 index,
 int,
 mysqlEnum,
 mysqlTable,
 timestamp,
 unique,
 varchar,
} from "drizzle-orm/mysql-core";
 
export const users = mysqlTable(
 "users",
 {
 id: varchar("id", { length: 255 }).primaryKey(),
 createdAt: timestamp("createdAt").defaultNow().onUpdateNow().notNull(),
 updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
 email: varchar("email", { length: 191 }).notNull(),
 },
 (table) => {
 return {
 idIdx: index("users_id_idx").on(table.id),
 userIdKey: unique("users_id_key").on(table.id),
 };
 },
);
 
export const keys = mysqlTable(
 "keys",
 {
 id: varchar("id", { length: 255 }).primaryKey(),
 hashedPassword: varchar("hashed_password", { length: 255 }),
 userId: varchar("user_id", { length: 255 }).notNull(),
 },
 (table) => {
 return {
 userIdIdx: index("keys_user_id_idx").on(table.userId),
 keyIdKey: unique("keys_id_key").on(table.id),
 };
 },
);

এবং pnpm drizzle-kit push:mysql চালান স্কিমাটিকে প্ল্যানেটস্কেলে ঠেলে দিতে।

ভয়লা ! আপনার কাছে এখন একটি ব্যবহারকারী মডেল রয়েছে যা লুসিয়া ব্যবহারকারীদের পরিচালনা করতে ব্যবহার করতে পারে৷

সেশন ম্যানেজমেন্ট সেট আপ করা হচ্ছে

এখন যেহেতু আমাদের ব্যবহারকারী মডেল আছে, আমরা সেশন ম্যানেজমেন্ট সেট আপ করতে পারি।

আমরা সেশন পরিচালনা করতে Upstash Redis ব্যবহার করব। আপনি এখানে একটি বিনামূল্যে অ্যাকাউন্টের জন্য সাইন আপ করতে পারেন৷

লুসিয়া, প্ল্যানেটস্কেল এবং আপস্ট্যাশ রেডিসের সাথে SvelteKit-এ সুরক্ষিত, টাইপ-নিরাপদ প্রমাণীকরণ

একবার আপনি ড্যাশবোর্ডে গেলে, আপনাকে যা করতে হবে তা হল একটি নতুন ডাটাবেস তৈরি করা এবং পরিবেশের ভেরিয়েবলগুলি অনুলিপি করা৷

লুসিয়া, প্ল্যানেটস্কেল এবং আপস্ট্যাশ রেডিসের সাথে SvelteKit-এ সুরক্ষিত, টাইপ-নিরাপদ প্রমাণীকরণ

এখন এই ভেরিয়েবলগুলিকে আপনার .env এ যোগ করুন ফাইল এবং src/lib/server/upstash/index.ts-এ নিম্নলিখিত যোগ করুন .

src/lib/server/upstash/index.ts
import { Redis } from "@upstash/redis";
import {
 UPSTASH_REDIS_REST_TOKEN,
 UPSTASH_REDIS_REST_URL,
} from "$env/static/private";
 
export const upstashClient = new Redis({
 url: UPSTASH_REDIS_REST_URL,
 token: UPSTASH_REDIS_REST_TOKEN,
});

এখন মনে রাখবেন যখন আমরা লুসিয়া কনফিগার করেছি, আমরা session সেট করেছি null এ . এটি কারণ আমরা সেশন পরিচালনা করতে Redis ব্যবহার করতে চাই। আমাদের কনফিগারেশন এখন এইরকম দেখাচ্ছে:

src/lib/server/auth/index.ts
import { planetscale } from "@lucia-auth/adapter-mysql";
import { upstash } from "@lucia-auth/adapter-session-redis";
import { dev } from "$app/environment";
import { lucia } from "lucia";
import { sveltekit } from "lucia/middleware";
 
import { ps } from "../planetscale";
import { upstashClient } from "../upstash";
 
export enum PROVIDER_ID {
 EMAIL = "email",
}
 
export const auth = lucia({
 adapter: {
 user: planetscale(ps, {
 user: "users",
 key: "keys",
 session: null,
 }),
 // Instruct Lucia to use Upstash Redis for sessions
 session: upstash(upstashClient),
 },
 middleware: sveltekit(),
 env: dev ? "DEV" : "PROD",
 getUserAttributes: (data) => {
 return {
 userId: data.id,
 email: data.email,
 };
 },
});
 
export type Auth = typeof auth;

আমাদের জন্য ভাগ্যবান, লুসিয়ার বাক্সের বাইরে একটি Upstash Redis অ্যাডাপ্টার রয়েছে৷ তাই আমাদের যা করতে হবে তা আমদানি করতে হবে এবং Upstash ক্লায়েন্টকে পাস করতে হবে।

এখন এটা সহজ ছিল!

রুট তৈরি করা হচ্ছে

এখন আমরা লুসিয়া কনফিগার করেছি, আমরা আমাদের রুট তৈরি করতে পারি।

src/routes-এ নিম্নলিখিত ফোল্ডারগুলি তৈরি করুন৷ . আপাতত কোনও ফাইল নিয়ে চিন্তা করবেন না, আমরা কিছুক্ষণের মধ্যে সেগুলি নিয়ে যাব৷

  • src/routes/auth
    • src/routes/auth/signin
    • src/routes/auth/signup
  • src/routes/app

টিপ: একই ফোল্ডারের নাম বা গোষ্ঠীর অধীনে কিছু "বৈশিষ্ট্য" থাকার ফলে পুনঃনির্দেশ করা এবং রুটগুলি সুরক্ষিত করার সময় পরিচালনা করা সহজ হয়৷

সাইনইন পৃষ্ঠা তৈরি করা হচ্ছে

অবশেষে, আমরা কিছু ফ্রন্ট-এন্ড কাজ করতে পারি! আসুন সাইন ইন পৃষ্ঠা দিয়ে শুরু করি৷

src/routes/auth/signin/+page.svelte-এ একটি নতুন ফাইল তৈরি করুন . আমি আপাতত স্টাইলিং বাদ দিতে যাচ্ছি, এবং কার্যকারিতার উপর ফোকাস করব — কিন্তু আপনি উদাহরণ সংগ্রহস্থলে সম্পূর্ণ কোড খুঁজে পেতে পারেন।

src/routes/auth/signin/+page.svelte
<script lang="ts">
 import { enhance } from '$app/forms';
 import { Button, Input, Label, PasswordInput } from '$lib/components/common';
 import type { ActionData } from './$types';
 
 export let form: ActionData;
 
 let loading = false;
 let email = '';
 let password = '';
</script>
 
<form
 method="POST"
 use:enhance={() => {
 loading = true;
 
 return async ({ update }) => {
 loading = false;
 
 update();
 };
 }}
>
 {#if form && form.error}
 <div class="p-2 mb-4 text-sm text-center text-red-900 bg-red-200 rounded-sm">
 Error: {form.error}
 </div>
 {/if}
 
 <div class="grid gap-2.5">
 <div class="grid gap-1">
 <Label for="email">Email</Label>
 <Input
 bind:value={email}
 name="email"
 placeholder="Email"
 type="email"
 autoCapitalize="none"
 autoComplete="email"
 autoCorrect="off"
 required={true}
 />
 </div>
 
 <div class="grid gap-1">
 <Label for="password">Password</Label>
 <PasswordInput name="password" placeholder="Password" bind:value={password} />
 </div>
 
 <div class="mt-6 col-span-full">
 <Button type="submit" class="w-full" disabled={loading}>
 {#if loading}
 Loading...
 {:else}
 Sign in
 {/if}
 </Button>
 </div>
 </div>
</form>

use:enhance ক্রিয়াটি ধীরে ধীরে ফর্মটিকে উন্নত করবে এবং ফর্মটি জমা দেওয়ার সময় আমাদেরকে একটি লোডিং অবস্থা দেখানোর অনুমতি দেবে৷ আপনি এখানে উন্নত সম্পর্কে আরও পড়তে পারেন৷

বাকি কোডটি বেশ স্ব-ব্যাখ্যামূলক।

সাইনইন অনুরোধ পরিচালনা করা

SvelteKit POST অনুরোধগুলি পরিচালনা করা অবিশ্বাস্যভাবে সহজ করে তোলে। আমাদের যা করতে হবে তা হল একটি +page.server.ts ফাইল তৈরি করা +page.svelte একই ডিরেক্টরিতে ফাইল করুন এবং একটি actions রপ্তানি করুন অন্তত একটি default সহ বস্তু সম্পত্তি।

src/routes/auth/signin/+page.server.ts
import { fail, redirect } from "@sveltejs/kit";
import { auth, PROVIDER_ID } from "$lib/server";
import { LuciaError } from "lucia";
 
import type { Actions, PageServerLoad } from "./$types";
 
export const actions = {
 /* our actions here */
};

আসুন ফাইলের এই অংশের মূল উপাদানগুলি অন্বেষণ করি:

আমরা PROVIDER_ID আমদানি করেছি enum এবং auth src/lib/server/auth থেকে , যা আমরা আগে তৈরি করেছি। এই auth অবজেক্টে ব্যবহারকারী এবং সেশন পরিচালনা করার জন্য আমাদের প্রয়োজনীয় সমস্ত পদ্ধতি রয়েছে।

এখন actions দেখে নেওয়া যাক বস্তু আমরা রিকোয়েস্ট অবজেক্ট থেকে ফর্ম ডেটা পেতে পারি এবং কিছু বেসিক হাউসকিপিং করতে পারি।

actions = {
 default: async ({ request, locals }) => {
 const formData = await request.formData();
 const email = formData.get("email") as string;
 const password = formData.get("password") as string;
 const fields = [email, password];
 
 if (fields.some(field => !field)) {
 return fail(400, {
 error: "All fields are required"
 });
 }

এরপরে, আমরা ব্যবহারকারীকে সাইন ইন করার চেষ্টা করব। যদি ব্যবহারকারীর অস্তিত্ব না থাকে, বা পাসওয়ার্ডটি ভুল, লুসিয়া একটি ত্রুটি নিক্ষেপ করবে। আমরা ত্রুটিটি ধরার মাধ্যমে এবং একটি ত্রুটি বার্তা সহ 400টি প্রতিক্রিয়া ফিরিয়ে দিয়ে এই ইভেন্টের জন্য প্রস্তুত হয়েছি৷

try {
 const user = await auth.useKey(PROVIDER_ID.EMAIL, email.toLowerCase(), password);
 
 const session = await auth.createSession({
 userId: user.userId,
 attributes: {}
 });
 
 locals.auth.setSession(session);
} catch (err) {
 if (
 err instanceof LuciaError &&
 (err.message === 'AUTH_INVALID_KEY_ID' || err.message === 'AUTH_INVALID_PASSWORD')
 ) {
 return fail(400, {
 error: 'Incorrect username of password'
 });
 }
 
 return fail(400, {
 error: 'An unknown error occurred'
 });
}

যদি ব্যবহারকারী বিদ্যমান থাকে এবং পাসওয়ার্ড সঠিক হয়, আমরা একটি নতুন অধিবেশন তৈরি করব৷

এবং অবশেষে, আমরা ব্যবহারকারীকে ড্যাশবোর্ডে পুনঃনির্দেশ করব।

return redirect('/app');

আপনি সম্ভবত বলতে পারেন, লুসিয়া প্রমাণীকরণের অনেক জটিলতা দূর করে। আমাদের যা করতে হবে তা হল সঠিক পদ্ধতিগুলি, এবং লুসিয়া বাকিগুলি পরিচালনা করবে৷

লুসিয়া, প্ল্যানেটস্কেল এবং আপস্ট্যাশ রেডিসের সাথে SvelteKit-এ সুরক্ষিত, টাইপ-নিরাপদ প্রমাণীকরণ

পাসওয়ার্ড হ্যাশ করা, সেশন তৈরি করা বা কুকি পরিচালনা করার দরকার নেই। লুসিয়া আমাদের জন্য সব করে। এবং এটি সব ধরনের নিরাপদ!

সাইনআপ পৃষ্ঠা তৈরি করা হচ্ছে

src/routes/auth/signup/+page.svelte-এ একটি নতুন ফাইল তৈরি করুন .

সাইন আপ পৃষ্ঠাটি সাইনইন পৃষ্ঠার সাথে খুব মিল, তাই এখানে ব্যাখ্যা করার মতো অনেক কিছু নেই৷ শুধুমাত্র পার্থক্য হল আমরা একটি পাসওয়ার্ড নিশ্চিতকরণের জন্য জিজ্ঞাসা করছি৷

৷ src/routes/auth/signup/+page.svelte
<script lang="ts">
 import { enhance } from '$app/forms';
 import { Button, Input, Label, PasswordInput } from '$lib/components/common';
 import type { ActionData } from './$types';
 
 export let form: ActionData;
 
 let loading = false;
 let email = '';
 let password = '';
 let passwordConfirmation = '';
</script>
 
<form
 method="POST"
 use:enhance={() => {
 loading = true;
 
 return async ({ update }) => {
 loading = false;
 
 update();
 };
 }}
>
 {#if form && form.error}
 <div class="p-2 mb-4 text-sm text-center text-red-900 bg-red-200 rounded-sm">
 Error: {form.error}
 </div>
 {/if}
 
 <div class="grid gap-2.5">
 <div class="grid gap-1">
 <Label for="email">Email</Label>
 <Input
 bind:value={email}
 name="email"
 placeholder="Email"
 type="email"
 autoCapitalize="none"
 autoComplete="email"
 autoCorrect="off"
 required={true}
 />
 </div>
 
 <div class="grid gap-1">
 <Label for="password">Password</Label>
 <PasswordInput name="password" placeholder="Password" bind:value={password} />
 </div>
 
 <div class="grid gap-1">
 <Label for="passwordConfirmation">Confirm password</Label>
 <PasswordInput
 name="passwordConfirmation"
 placeholder="Repeat password"
 bind:value={passwordConfirmation}
 />
 </div>
 
 <div class="mt-6 col-span-full">
 <Button type="submit" class="w-full" disabled={loading}>
 {#if loading}
 Loading...
 {:else}
 Sign in
 {/if}
 </Button>
 </div>
 </div>
</form>

সাইনআপ অনুরোধ পরিচালনা করা

src/routes/auth/signup/+page.server.ts-এ একটি নতুন ফাইল তৈরি করুন .

সাইনআপের জন্য আমাদের সাইনআপ ফর্মের মতো একই প্যাটার্ন ব্যবহার করতে হবে তবে ফর্ম থেকে ডেটা পুনরুদ্ধার থেকে শুরু করে, ব্যবহারকারী তৈরি করা এবং ইতিমধ্যে বিদ্যমান ব্যবহারকারীদের পরিচালনা করার ক্ষেত্রে ক্ষেত্রের বৈধতা থেকে শুরু করে কিছু পার্থক্য থাকবে৷

আমদানি সাইনইন পৃষ্ঠার মতোই, তাই আমরা সেই অংশটি এড়িয়ে যাব৷

আমরা রিকোয়েস্ট অবজেক্ট থেকে ফর্ম ডেটা পেয়ে শুরু করব এবং কিছু বেসিক হাউসকিপিং করব। পাসওয়ার্ড মেলে কিনা তাও আমরা পরীক্ষা করব।

const formData = await request.formData();
const email = formData.get('email') as string;
const password = formData.get('password') as string;
const passwordConfirmation = formData.get('passwordConfirmation') as string;
 
const fields = [email, password, passwordConfirmation];
 
if (fields.some((field) => !field)) {
 return fail(400, {
 error: 'All fields are required'
 });
}
 
if (password !== passwordConfirmation) {
 return fail(400, {
 error: 'Passwords do not match'
 });
}

এরপর, আমরা ড্রিজল ওআরএম ব্যবহার করে ইমেলের মাধ্যমে ব্যবহারকারীকে খুঁজে বের করার চেষ্টা করব। যদি ব্যবহারকারী বিদ্যমান থাকে, আমরা একটি ত্রুটি বার্তা সহ একটি 400 প্রতিক্রিয়া ফেরত দেব৷

try {
 const user = await db.query.users.findFirst({
 where: eq(schema.users.email, email.toLowerCase()),
 });
 
 if (user) {
 return fail(400, {
 error: "User with this email already exists"
 });
 }

ব্যবহারকারীর অস্তিত্ব না থাকলে, আমরা লুসিয়া ব্যবহার করে একটি নতুন ব্যবহারকারী তৈরি করব।

const newUser = await auth.createUser({
 key: {
 providerId: PROVIDER_ID.EMAIL,
 providerUserId: email.toLowerCase(),
 password: password,
 },
 attributes: {
 email,
 },
});

এবং অবশেষে, আমরা একটি নতুন সেশন তৈরি করব এবং ব্যবহারকারীকে ড্যাশবোর্ডে পুনঃনির্দেশ করব।

const session = await auth.createSession({
 userId: newUser.userId,
 attributes: {},
});
 
locals.auth.setSession(session);

সহজ পেসি লেবু চেপে!

বোনাস:সাইনআউট পৃষ্ঠা তৈরি করা হচ্ছে

আমরা যখন এটিতে আছি, আসুন ব্যবহারকারীকে সাইন আউট করার জন্য একটি এন্ডপয়েন্ট তৈরি করি। src/routes/auth/signout/+server.ts-এ একটি নতুন ফাইল তৈরি করুন .

এবং নিম্নলিখিত কোড যোগ করুন:

src/routes/auth/signout/+server.ts
import { auth } from "$lib/server";
 
import type { RequestHandler } from "./$types";
 
export const POST: RequestHandler = async ({ locals }) => {
 const session = await locals.auth.validate();
 
 if (!session) {
 return new Response(null, {
 status: 400,
 });
 }
 
 // Invalidate session or alternatively, you can delete all sessions: await auth.invalidateAllUserSessions(session.userId);
 await auth.invalidateSession(session.sessionId);
 
 // Remove the cookie.
 locals.auth.setSession(null);
 
 return new Response(null, {
 status: 200,
 });
};

আবার লুসিয়া সেশনগুলিকে বাতিল করা অবিশ্বাস্যভাবে সহজ করে আমাদের পিছনে রয়েছে। ব্যবহারকারী যখন সাইন আউট বোতামে ক্লিক করেন তখন আমাদের যা করতে হবে তা হল এই এন্ডপয়েন্টটিকে কল করা।

src/routes/app/+page.svelte
<script lang="ts">
 import { goto } from '$app/navigation';
 import { Button } from '$lib/components/common';
 
 async function handleSignOut() {
 const response = await fetch('/auth/signout', {
 method: 'POST',
 headers: {
 'Content-Type': 'application/json'
 }
 });
 
 if (response.ok) {
 goto('/auth/signin', {
 replaceState: true,
 invalidateAll: true
 });
 }
 }
</script>
 
<Button on:click={handleSignOut}>Sign out</Button>

এটি একটি মোড়ানো

আমরা সফলভাবে লুসিয়া, প্ল্যানেটস্কেল এবং আপস্ট্যাশ রেডিসের সাথে টাইপ-সেফ প্রমাণীকরণ তৈরি করেছি। এবং আমরা শুধুমাত্র লুসিয়া কি করতে পারে তার উপরিভাগ স্ক্র্যাচ করেছি।

আবার, আপনি এখানে এই গাইডের জন্য রেপো খুঁজে পেতে পারেন যদি আপনি লুসিয়া সম্পর্কে আরও জানতে চান, আমি দস্তাবেজগুলি চেক করার সুপারিশ করছি৷

আপনি এগিয়ে যাওয়ার আগে আপনাকে আপস্ট্যাশ ডিসকর্ড সম্প্রদায়ে আড্ডা দেওয়া উচিত — আমাদের ভাল সময় কাটছে। এবং এছাড়াও আপনি যদি আরও SvelteKit সামগ্রী চান, আপনি এটি আমার ব্লগে এখানে খুঁজে পেতে পারেন৷


  1. একটি বৃত্তের পরিধি খুঁজে পেতে জাভা প্রোগ্রাম

  2. কিভাবে HTML এ ফ্লোটিং লেআউট তৈরি করবেন?

  3. REDIS (রিমোট ডিরেক্টরি সার্ভার) - Redis টিউটোরিয়াল

  4. জাভাস্ক্রিপ্টে লুপ ব্যবহার করে একটি খালি বস্তুতে সম্পত্তি সেট করা।