feat: midterm shit done
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import { createErrorResponse } from '../../utils';
|
||||
|
||||
export async function onRequestGet(context) {
|
||||
try {
|
||||
const { env, params } = context;
|
||||
const { filename } = params;
|
||||
|
||||
if (!filename) {
|
||||
return createErrorResponse("Filename is required", 400);
|
||||
}
|
||||
|
||||
const key = "avatars/" + filename;
|
||||
const object = await env.MY_BUCKET.get(key);
|
||||
|
||||
if (object === null) {
|
||||
return new Response("Object Not Found", { status: 404 });
|
||||
}
|
||||
|
||||
const headers = new Headers();
|
||||
object.writeHttpMetadata(headers);
|
||||
headers.set("etag", object.httpEtag);
|
||||
|
||||
return new Response(object.body, {
|
||||
headers,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Avatar retrieval error:", error);
|
||||
return createErrorResponse("Server Error", 500);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { verifyJWT } from '../../middleware/auth';
|
||||
import { createErrorResponse, createSuccessResponse } from '../../utils';
|
||||
import { fileTypeFromBuffer } from 'file-type';
|
||||
|
||||
export async function onRequestPut(context) {
|
||||
try {
|
||||
const { request, env } = context;
|
||||
|
||||
// Verify the JWT token
|
||||
const authResult = await verifyJWT(context);
|
||||
if (authResult) {
|
||||
return authResult; // Return the error response from the middleware
|
||||
}
|
||||
|
||||
const formData = await request.formData();
|
||||
const avatar = formData.get('avatar');
|
||||
|
||||
if (!avatar) {
|
||||
return createErrorResponse("Missing avatar", 400);
|
||||
}
|
||||
|
||||
if (avatar.size > 2 * 1024 * 1024) {
|
||||
return createErrorResponse("Avatar must be less than 2MB", 400);
|
||||
}
|
||||
|
||||
const buffer = await avatar.arrayBuffer();
|
||||
const fileTypeResult = await fileTypeFromBuffer(buffer);
|
||||
|
||||
if (!fileTypeResult) {
|
||||
return createErrorResponse("Unsupported file type", 400);
|
||||
}
|
||||
|
||||
if (fileTypeResult.mime !== 'image/jpeg' && fileTypeResult.mime !== 'image/png') {
|
||||
return createErrorResponse("Avatar must be a JPG or PNG image", 400);
|
||||
}
|
||||
|
||||
// Upload the avatar to R2
|
||||
const fileExtension = fileTypeResult.ext;
|
||||
const objectName = `avatars/${context.user.userId}.${fileExtension}`;
|
||||
await env.MY_BUCKET.put(objectName, buffer);
|
||||
|
||||
// Store the filename in D1
|
||||
await env.DB.prepare("UPDATE users SET avatar = ? WHERE id = ?").bind(objectName, context.user.userId).run();
|
||||
|
||||
return createSuccessResponse({ message: "Avatar uploaded successfully" });
|
||||
} catch (error) {
|
||||
console.error("Avatar upload error:", error);
|
||||
return createErrorResponse("Avatar upload failed", 500);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export function onRequest(context) {
|
||||
return new Response("Hello, world!")
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { SignJWT } from 'jose';
|
||||
import { createSuccessResponse, createErrorResponse } from "../utils";
|
||||
|
||||
export async function onRequestPost(context) {
|
||||
try {
|
||||
const { request, env } = context;
|
||||
|
||||
const { username, password } = await request.json();
|
||||
|
||||
if (!username || !password) {
|
||||
return createErrorResponse("Missing username or password", 400);
|
||||
}
|
||||
|
||||
if (username.length < 3) {
|
||||
return createErrorResponse("Username must be at least 3 characters", 400);
|
||||
}
|
||||
|
||||
if (password.length < 8) {
|
||||
return createErrorResponse("Password must be at least 8 characters", 400);
|
||||
}
|
||||
|
||||
if (!/^[a-zA-Z0-9]+$/.test(username)) {
|
||||
return createErrorResponse("Username must be alphanumeric", 400);
|
||||
}
|
||||
|
||||
// Get the stored password from D1
|
||||
const { results } = await env.DB.prepare("SELECT password FROM users WHERE username = ?").bind(username).all();
|
||||
|
||||
if (!results || results.length === 0) {
|
||||
return new Response(JSON.stringify({"error": "Invalid username or password"}), { status: 403, headers: { 'Content-Type': 'application/json' } });
|
||||
}
|
||||
|
||||
const storedPassword = results[0].password;
|
||||
|
||||
// Compare the password to the stored password
|
||||
if (password !== storedPassword) {
|
||||
return new Response(JSON.stringify({"error": "Invalid username or password"}), { status: 403, headers: { 'Content-Type': 'application/json' } });
|
||||
}
|
||||
|
||||
// Get the user ID
|
||||
const { results: userResults } = await env.DB.prepare("SELECT * FROM users WHERE username = ?").bind(username).all();
|
||||
const jwtPayload = (({ id, username }) => ({ id, username }))(userResults[0]);
|
||||
|
||||
// Generate a JWT token
|
||||
const jwt = await new SignJWT(jwtPayload)
|
||||
.setProtectedHeader({ alg: 'HS256' })
|
||||
.setIssuedAt()
|
||||
.setIssuer('urn:example:issuer')
|
||||
.setAudience('urn:example:audience')
|
||||
.setExpirationTime('2h')
|
||||
.sign(new TextEncoder().encode(env.JWT_SECRET));
|
||||
|
||||
return createSuccessResponse({ jwt });
|
||||
} catch (error) {
|
||||
console.error("Login error:", error);
|
||||
return createErrorResponse("Login failed", 500);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { verifyJWT } from "../middleware/auth";
|
||||
import { createErrorResponse, createSuccessResponse } from "../utils";
|
||||
|
||||
export async function onRequest(context) {
|
||||
try {
|
||||
// Verify JWT token
|
||||
const authResult = await verifyJWT(context);
|
||||
if (authResult) {
|
||||
return authResult; // Return error response if authentication fails
|
||||
}
|
||||
|
||||
// Get user information from context
|
||||
const { user } = context;
|
||||
|
||||
// Fetch user profile from D1 database
|
||||
const { results } = await context.env.DB.prepare("SELECT * FROM users WHERE id = ?").bind(user.userId).all();
|
||||
if (!results || results.length === 0) {
|
||||
// use 401 instead to redirect to login page
|
||||
return createErrorResponse("User not found", 401);
|
||||
}
|
||||
const userProfile = results[0];
|
||||
const { password, ...profile } = userProfile; // Exclude password from the profile
|
||||
|
||||
// Return the profile as a JSON response
|
||||
return createSuccessResponse(profile, 200);
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
return createErrorResponse("Internal Server Error", 500);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { verifyJWT } from '../middleware/auth';
|
||||
import { createErrorResponse, createSuccessResponse } from '../utils';
|
||||
|
||||
export async function onRequestGet(context) {
|
||||
try {
|
||||
const { env } = context;
|
||||
|
||||
// Get the messages from D1
|
||||
const { results } = await env.DB.prepare("SELECT messages.id, userId, username, message, timestamp, users.avatar FROM messages LEFT JOIN users ON users.id = messages.userId").all();
|
||||
|
||||
return createSuccessResponse({ messages: results });
|
||||
} catch (error) {
|
||||
console.error("Get messages error:", error);
|
||||
return createErrorResponse("Get messages failed", 500);
|
||||
}
|
||||
}
|
||||
|
||||
export async function onRequestPost(context) {
|
||||
try {
|
||||
const { request, env } = context;
|
||||
|
||||
// Verify the JWT token
|
||||
const authResult = await verifyJWT(context);
|
||||
if (authResult) {
|
||||
return authResult; // Return the error response from the middleware
|
||||
}
|
||||
|
||||
const { message } = await request.json();
|
||||
|
||||
if (!message) {
|
||||
return new Response(JSON.stringify({"error": "Missing message"}), {
|
||||
status: 400,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
// Generate a unique ID for the message
|
||||
const messageId = crypto.randomUUID();
|
||||
|
||||
// Store the message in D1
|
||||
await env.DB.prepare("INSERT INTO messages (id, userId, message) VALUES (?, ?, ?)")
|
||||
.bind(messageId, context.user.userId, message)
|
||||
.run();
|
||||
|
||||
return new Response(JSON.stringify({ id: messageId, username: context.user.username, message }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Message posting error:", error);
|
||||
return createErrorResponse("Message posting failed", 500);
|
||||
}
|
||||
}
|
||||
|
||||
export async function onRequestDelete(context) {
|
||||
try {
|
||||
const { request, env } = context;
|
||||
|
||||
// Verify the JWT token
|
||||
const authResult = await verifyJWT(context);
|
||||
if (authResult) {
|
||||
return authResult; // Return the error response from the middleware
|
||||
}
|
||||
|
||||
const { messageId } = await request.json();
|
||||
|
||||
if (!messageId) {
|
||||
return new Response(JSON.stringify({"error": "Missing messageId"}), {
|
||||
status: 400,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
// Delete the message from D1
|
||||
await env.DB.prepare("DELETE FROM messages WHERE id = ?").bind(messageId).run();
|
||||
|
||||
return createSuccessResponse({ message: "Message deleted successfully" });
|
||||
} catch (error) {
|
||||
console.error("Message deletion error:", error);
|
||||
return createErrorResponse("Message deletion failed", 500);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { createErrorResponse } from '../utils';
|
||||
|
||||
export async function onRequestPost(context) {
|
||||
try {
|
||||
const { request, env } = context;
|
||||
|
||||
const { username, password } = await request.json();
|
||||
|
||||
if (!username || !password) {
|
||||
return createErrorResponse("Missing username or password", 400);
|
||||
}
|
||||
|
||||
if (username.length < 3) {
|
||||
return createErrorResponse("Username must be at least 3 characters", 400);
|
||||
}
|
||||
|
||||
if (password.length < 8) {
|
||||
return createErrorResponse("Password must be at least 8 characters", 400);
|
||||
}
|
||||
|
||||
if (!/^[a-zA-Z0-9]+$/.test(username)) {
|
||||
return createErrorResponse("Username must be alphanumeric", 400);
|
||||
}
|
||||
|
||||
// Check if the username already exists
|
||||
const { results: existingUsers } = await env.DB.prepare("SELECT id FROM users WHERE username = ?").bind(username).all();
|
||||
if (existingUsers.length > 0) {
|
||||
return createErrorResponse("Username already exists", 400);
|
||||
}
|
||||
|
||||
// Store the username and password in D1
|
||||
await env.DB.prepare("INSERT INTO users (username, password, avatar) VALUES (?, ?, ?)").bind(username, password, "avatars/default.png").run();
|
||||
|
||||
// Get the user ID
|
||||
const { results } = await env.DB.prepare("SELECT id FROM users WHERE username = ?").bind(username).all();
|
||||
const userId = results[0].id;
|
||||
|
||||
// Registration successful, return success response
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
message: "Registration successful. Please login.",
|
||||
}),
|
||||
{
|
||||
headers: { "Content-Type": "application/json" },
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Registration error:", error);
|
||||
return createErrorResponse("Server Error", 500);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
* @typedef {import('@cloudflare/workers-types').D1Database} D1Database
|
||||
*/
|
||||
|
||||
export async function onRequestGet(context) {
|
||||
const DB = context.env.DB;
|
||||
|
||||
// return all users
|
||||
const stmt = await DB.prepare("SELECT * FROM users");
|
||||
const users = (await stmt.run()).results;
|
||||
|
||||
return new Response(JSON.stringify(users), {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
export async function onRequestPost(context) {
|
||||
/**
|
||||
* @type {D1Database}
|
||||
*/
|
||||
const DB = context.env.DB;
|
||||
const { name } = await context.request.json();
|
||||
|
||||
// create a new user
|
||||
const stmt = DB.prepare("INSERT INTO users (name) VALUES (?)").bind(name);
|
||||
|
||||
try {
|
||||
const result = await stmt.run();
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error("Failed to create user");
|
||||
}
|
||||
|
||||
const userId = result.meta.last_row_id;
|
||||
const stmt2 = await DB.prepare("SELECT * FROM users WHERE id = ?").bind(userId);
|
||||
const userResult = await stmt2.run();
|
||||
const user = userResult.results[0];
|
||||
|
||||
return new Response(JSON.stringify(user), {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
status: 201,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error creating user:", error);
|
||||
return new Response("Error creating user", { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as jose from 'jose';
|
||||
import { createErrorResponse } from "../utils";
|
||||
|
||||
export async function verifyJWT(context) {
|
||||
const { request, env } = context;
|
||||
|
||||
// Check for a valid JWT token
|
||||
const authHeader = request.headers.get("Authorization");
|
||||
if (!authHeader) {
|
||||
return createErrorResponse("Missing Authorization header", 401);
|
||||
}
|
||||
|
||||
const token = authHeader.split(" ")[1];
|
||||
|
||||
try {
|
||||
// Verify the token
|
||||
const { payload, protectedHeader } = await jose.jwtVerify(token, new TextEncoder().encode(env.JWT_SECRET), {
|
||||
issuer: 'urn:example:issuer',
|
||||
audience: 'urn:example:audience',
|
||||
});
|
||||
context.user = { userId: payload.id, username: payload.username };
|
||||
return; // Continue to the next middleware or function
|
||||
} catch (error) {
|
||||
return createErrorResponse("Invalid or expired token", 401);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export function createErrorResponse(message, status) {
|
||||
return new Response(JSON.stringify({"error": message}), {
|
||||
status: status,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
export function createSuccessResponse(data, status = 200) {
|
||||
return new Response(JSON.stringify(data), {
|
||||
status: status,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user