Halo para seniman
yang budiman! Selamat datang kembali! Pada kesempatan kali ini, kita membuat tiga API utama untuk menangani authentication (Login, Register, dan Logout). Setiap API memiliki fungsinya masing-masing untuk mengelola sesi pengguna dan data yang tersimpan di PostgreSQL. Berikut penjelasan detailnya:
1. API untuk Register #
Kode untuk register bertugas membuat pengguna baru dengan meng-hash password mereka dan menyimpan data di database.
// src/routes/api/register/+server.ts
import type { RequestHandler } from '@sveltejs/kit';
import bcrypt from 'bcrypt';
import sql from '$lib/server/db';
// Fungsi untuk memeriksa apakah email sudah terdaftar
async function isEmailTaken(email: string): Promise<boolean> {
const result = await sql`
SELECT * FROM users WHERE email = ${email}
`;
return result.length > 0;
}
// Fungsi untuk membuat pengguna baru
async function createUser(email: string, hashedPassword: string, firstName: string, lastName: string): Promise<void> {
await sql`
INSERT INTO users (email, password, first_name, last_name)
VALUES (${email}, ${hashedPassword}, ${firstName}, ${lastName})
`;
}
// Fungsi untuk memvalidasi format email
function isValidEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
// Handler untuk menangani permintaan POST (register)
export const POST: RequestHandler = async ({ request }) => {
try {
const { email, password, firstName, lastName } = await request.json();
// Validasi email
if (!isValidEmail(email)) {
return new Response(JSON.stringify({ success: false, message: 'Invalid email format' }), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
// Cek apakah email sudah digunakan
if (await isEmailTaken(email)) {
return new Response(JSON.stringify({ success: false, message: 'Email is already taken' }), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
// Hash password
const hashedPassword = await bcrypt.hash(password, 10);
// Simpan pengguna baru di database
await createUser(email, hashedPassword, firstName, lastName);
return new Response(JSON.stringify({ success: true, message: 'User registered successfully' }), {
status: 201,
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
return new Response(JSON.stringify({ success: false, message: `Internal server error: ${error}` }), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
};
Penjelasan Kode:
isEmailTaken
: Memeriksa apakah email sudah terdaftar di database.createUser
: Menyimpan data pengguna baru dengan hashed password.isValidEmail
: Validasi format email menggunakan regex.
2. API untuk Login #
Kode untuk login bertanggung jawab memverifikasi kredensial pengguna (email dan password), membuat sesi baru, dan menyimpan token sesi ke dalam cookie pengguna.
// src/routes/api/login/+server.ts
import bcrypt from 'bcrypt';
import { randomUUID } from 'crypto'; // Untuk membuat token sesi
import type { RequestHandler } from '@sveltejs/kit';
import sql from '$lib/server/db'; // Koneksi database PostgreSQL
// Fungsi untuk mendapatkan pengguna berdasarkan email
async function getUserByEmail(email: string) {
const result = await sql`
SELECT * FROM users WHERE email = ${email}
`;
return result[0];
}
// Fungsi untuk membuat sesi baru
async function createSession(user_id: number, token: string) {
await sql`
INSERT INTO sessions (user_id, token, expires_at)
VALUES (${user_id}, ${token}, NOW() + INTERVAL '1 day')
`;
}
// Handler untuk menangani permintaan POST (login)
export const POST: RequestHandler = async ({ request, cookies }) => {
const { email, password }: { email: string; password: string } = await request.json();
// Cari pengguna berdasarkan email
const user = await getUserByEmail(email);
if (user) {
// Verifikasi password
const passwordMatch = await bcrypt.compare(password, user.password);
if (passwordMatch) {
// Jika password cocok, buat sesi baru
const sessionToken = randomUUID();
await createSession(user.id, sessionToken);
// Set token sesi ke dalam cookie
cookies.set('session', sessionToken, {
path: '/',
httpOnly: true,
secure: process.env.NODE_ENV === 'production', // Amankan cookie di production
maxAge: 60 * 60 * 24 // Kadaluarsa dalam 1 hari
});
return new Response(JSON.stringify({ success: true, message: 'Login successful' }), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
} else {
// Jika password salah
return new Response(JSON.stringify({ success: false, message: 'Invalid password' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
} else {
// Jika email tidak ditemukan
return new Response(JSON.stringify({ success: false, message: 'Invalid email' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
};
Penjelasan Kode:
getUserByEmail
: Mencari pengguna di database berdasarkan email yang diinputkan.createSession
: Membuat token sesi unik menggunakanrandomUUID()
dan menyimpannya di tabelsessions
.- Cookie
session
diset untuk menyimpan token sesi pada pengguna selama 1 hari (maxAge: 60 * 60 * 24
).
3. API untuk Logout #
Kode untuk logout bertugas menghapus sesi pengguna dari database dan menghapus cookie sesi dari browser pengguna.
// src/routes/api/logout/+server.ts
import type { RequestHandler } from '@sveltejs/kit';
import sql from '$lib/server/db';
// Fungsi untuk menghapus sesi berdasarkan token
async function deleteSessionByToken(token: string) {
await sql`
DELETE FROM sessions WHERE token = ${token}
`;
}
// Handler untuk menangani permintaan POST (logout)
export const POST: RequestHandler = async ({ cookies }) => {
const sessionToken = cookies.get('session');
if (sessionToken) {
await deleteSessionByToken(sessionToken); // Hapus sesi dari database
}
// Hapus cookie sesi
cookies.set('session', '', {
path: '/',
httpOnly: true,
maxAge: 0 // Hapus cookie segera
});
return new Response(null, {
status: 302,
headers: {
Location: '/login' // Redirect pengguna ke halaman login
}
});
};
Penjelasan Kode:
deleteSessionByToken
: Menghapus sesi pengguna dari tabelsessions
berdasarkan token sesi.- Cookie
session
dihapus denganmaxAge: 0
, yang mengakibatkan penghapusan segera. - Setelah logout berhasil, pengguna di-redirect ke halaman login (
/login
).
Penjelasan: #
-
Login API (
/api/login
):- Menerima permintaan POST dengan email dan password.
- Memeriksa apakah pengguna ada di database.
- Memverifikasi password yang diberikan dengan password yang tersimpan menggunakan bcrypt.
- Jika verifikasi berhasil, memberikan respons sukses; jika tidak, memberikan pesan kesalahan.
-
Register API (
/api/register
):- Menerima permintaan POST dengan username, email, dan password.
- Meng-hash password menggunakan bcrypt untuk keamanan.
- Menyimpan pengguna baru ke dalam database.
- Memberikan respons sukses jika registrasi berhasil.
-
Logout API (
/api/logout
):- Pada logout, biasanya Anda dapat menghapus sesi pengguna atau token autentikasi (seperti token di cookie).
- Dalam contoh ini, kita mengirim respons bahwa pengguna berhasil logout.
Dengan API ini, aplikasi Svelte Anda sudah memiliki fitur authentication dasar yang bisa dihubungkan dengan halaman frontend.