From c862e417d2407cb3b032f2f200b663ac57a947d5 Mon Sep 17 00:00:00 2001 From: Chilling Star Date: Sat, 28 Sep 2024 15:11:42 +0000 Subject: [PATCH] alot of fixes! --- README.md | 46 +--- bun.lockb | Bin 0 -> 212858 bytes database.db | Bin 0 -> 16384 bytes package.json | 6 +- postcss.config.mjs | 6 +- server.ts | 520 +++++++++++--------------------------- src/app/login/page.tsx | 6 +- src/app/page.tsx | 59 ++--- src/app/register/page.tsx | 110 ++++---- 9 files changed, 246 insertions(+), 507 deletions(-) create mode 100755 bun.lockb create mode 100644 database.db diff --git a/README.md b/README.md index 91f264e..2149f82 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,14 @@ # Limbo - - -Limbo is a fast and lightweight chat application built with Next.js, React.js, TypeScript, MongoDB, and Socket.IO. It features a login/register mechanism built from scratch. - +Limbo is a fast and lightweight chat application built with Next.js, React.js, +TypeScript, MongoDB, and Socket.IO. It features a login/register mechanism built +from scratch. [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/chillingstar/limbo)](https://github.com/chillingstar/limbo/commits) [![GitHub last commit](https://img.shields.io/github/last-commit/chillingstar/limbo)](https://github.com/chillingstar/limbo/commits) - - ## Features - - - Real-time messaging using Socket.IO - User authentication and registration @@ -22,32 +17,25 @@ Limbo is a fast and lightweight chat application built with Next.js, React.js, T - Lightweight and scalable architecture - - ## Technologies Used - - -- Next.js: A React framework for server-side rendering and static site generation. +- Next.js: A React framework for server-side rendering and static site + generation. - React.js: A JavaScript library for building user interfaces. -- TypeScript: A statically typed superset of JavaScript that compiles to plain JavaScript. +- TypeScript: A statically typed superset of JavaScript that compiles to plain + JavaScript. - MongoDB: A NoSQL database for storing and retrieving data. -- Socket.IO: A library for real-time, bidirectional communication between web clients and servers. - - +- Socket.IO: A library for real-time, bidirectional communication between web + clients and servers. ## Getting Started - - To get started with Limbo, follow these steps: - - 1. Clone the repository: `git clone https://github.com/chillingstar/limbo.git` 2. Install dependencies: `npm install` @@ -56,20 +44,14 @@ To get started with Limbo, follow these steps: 4. Start the development server: `npm run dev` -5. Open your browser and navigate to `http://localhost:80`, or whatever port that you entered. - - +5. Open your browser and navigate to `http://localhost:80`, or whatever port + that you entered. ## Contributing - - -Contributions are welcome! If you find any bugs or have suggestions for improvements, please open an issue or submit a pull request. - - +Contributions are welcome! If you find any bugs or have suggestions for +improvements, please open an issue or submit a pull request. ## License - - -This project is licensed under the [StarProjects License](LICENSE). \ No newline at end of file +This project is licensed under the [StarProjects License](LICENSE). diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..0df9e6aec1a534a450b1413976d93b0fa1ea9687 GIT binary patch literal 212858 zcmeFZd0b6x_dkA0NFk*}MG~4+N+C4Qp+TdeXgCd;=K&RpC>0?MrYJ*XERrE43dyW8 zj}3&BdHAi>+1F$9y6@VD@9XvX<9A=ry?dW)UF*Hpy4E%Az0dK;%BY5ihN!yv1gNqD zB8Iz#2MEBW>=)?n>*?diR`v`G@plbVjuiFc1eysS;I+@TWzEwM;JzC=S z?B@J0>b4fbUz0{OH0$&LEf#AyDnsGt!2d9wst=c-6j**f{%(OF4Gs4531g3A1q6Dq zmA#^ahVigi!Yo$2G$@J!_6NlJWk3Ny54Kyl7x4T;IVM9PVEnij0_Y3v+W=8dlaGV* zL)`*U^BZN?-zUH)$Tc)H+SSj`Cp3)pl9JyA900sa6l(Y4_&o{r{vh8^Av?f5(8DLd zYgTWL{r!OGcOW3@q5T*?AGbV8|2U*V5am?7>pLKi~kZ6dD9TK7p7TL)l$GDdO z_5qBh(A^dO=gnsEff39@h>w4Wt0#-)4Kxd54vOKKvK&@9W_c62xM)gEHEE28euR_=D{c z6xM?r>sKf|2MGVg2LcK0hqC=6*dZ*IyLVt@0AP@^zblw!xkD$=-dRA*!%;xA6B-)g zgYk#Cf-)2`P6Hti*e*cjBOu7%FAyfczJV;3ILJ2xVw|SHLA$46(xCrC6grA=_#RNl zd}M$=j+d8fxECgD%^*%3%K%Y62N3%a2gVV{0HPlm_=9mQfOfG z!O`ceZx(AVv?ITtEC(M!J9Hub8>J^QlEo5%dL-lm3oq1B-vK`3xap1J%>N01Sa%N$ z>C}vH?OaBzp`$tdbPo*l^?}5@xrVaGYxsD$y1TQ3!a`X(a-4kl`}nh!Jvx_8XWShi z$9z8qyV#GLfSC7CZ&!8A@vsi$IsIw^#C9^zV7T4cp`k2x1UmrC|8IP%6*zI9QRKv{ zL&YD$c6G;z;H1Ry_XZIA;Xz>lJF0V@oKt4827`PL;1IwyfRN(&7)tIAi1X2$l8*&M zJt;t#;_QP+(}7JH)#O>iwWS4-n@^fNMaYj|YoY1NxW;xA0K6 zK-fRp)j9QIN*)#pn;OKwU>rxj2jm!k0J}467CR~^1oJUVljAQeI*6_86UwTm>Y-t- zVd0_d&}mS|d7=l1{zBOS;GMy;x*UEl z3Z+1f{{7iu-hmzv9MoZ}jBkSeVBW$5f_#D?Bft0O_xd@|$8|*3MJdHE02~PN96;TcAfYIoI5x!`PUT-|eM>KIX$CFbwV+VBA0l<5vJgJE7t3A+YpVEMrdpf_y?; z(UN}*C_uRea?}g+W(W9qMzhXS_18w6{*iNS7A!Q>Bj*4)7k@w3CV(F1{k|EepH~4f zzQg7m`Cto<9alhUg33%2g~^MKgTQb3$XvnV^T2e3n7@1F*Bl#_iy3+gx@qFw#{aGW{}IsR2aj&|y8 zIq}I*yd`!Vc@PdFlmMuUg5Dr#$8qDQ^uB`~9I#plls@nXYXMda5&5A*El8X6W1{1A3{D2A9Z zlhZ%DS)BE=1rX1#GnBrEA53N_x2bsH9QB3MBg8Y5v%|yw?SXejw`OzV-7tqUUx{DW zfM~d1cK3D->D+!;=fMuf0b|s;?%A+^286L#2j_A6v6Dh4xM#q;SOQ``j41SDM+5+s zr2%!c60!96Fo>w_JPM-jS-@xoN?OxzZz zW4ouHYgicDgQX677$-Y4Jj@6Du|tEy*>F@}g-sfH>`*u_z?U@W;k=s)qmA*n!oiLm z9|&^nU&wrp{0H1X;QaCkbPo&h31CB}{d_?$5dL64VSiQz-(IfsIpY`};-fqt=2=j9 zKs4T88^EkazC54=U?bSW^-~Q9w?y�C8QpgLAwu$%i_|xegHfOYW15137WMr0@YC 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 Bs&N1S literal 0 HcmV?d00001 diff --git a/package.json b/package.json index b4aa49f..1f13f8a 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,6 @@ "dotenv": "^16.4.5", "events": "^3.3.0", "express": "^4.19.2", - "mongoose": "^8.4.1", - "mysql2": "^3.10.0", "net": "^1.0.2", "next": "14.2.3", "react": "^18", @@ -21,7 +19,9 @@ "readable-stream": "^4.5.2", "sha256": "^0.2.0", "socket.io": "^4.7.5", - "socket.io-client": "^4.7.5" + "socket.io-client": "^4.7.5", + "sqlite": "^5.1.1", + "sqlite3": "^5.1.7" }, "devDependencies": { "@types/node": "^20.14.2", diff --git a/postcss.config.mjs b/postcss.config.mjs index 6f94347..1a69fd2 100644 --- a/postcss.config.mjs +++ b/postcss.config.mjs @@ -1,8 +1,8 @@ /** @type {import('postcss-load-config').Config} */ const config = { - plugins: { - tailwindcss: {}, - }, + plugins: { + tailwindcss: {}, + }, }; export default config; diff --git a/server.ts b/server.ts index 009acf2..f5db12a 100644 --- a/server.ts +++ b/server.ts @@ -1,359 +1,190 @@ // DotENV -const dotenv = require("dotenv"); -dotenv.config(); +import "dotenv/config"; // Express, Next, Socket.IO, etc... -const express = require("express"); -const next = require("next"); -const http = require("http"); -const socketIo = require("socket.io"); -const cors = require("cors"); +import express from "express"; +import next from "next"; +import http from "http"; +import { Server as socketIo } from "socket.io"; +import cors from "cors"; // Database -const mysql = require("mysql2/promise"); -const mongoose = require("mongoose"); +import sqlite3 from "sqlite3"; +import { open } from "sqlite"; // Initialization const dev = process.env.NODE_ENV !== "production"; const nextApp = next({ dev }); -const nodeCrypto = require("node:crypto"); +import * as nodeCrypto from "crypto"; const handle = nextApp.getRequestHandler(); const app = express(); -let pool; -let Account; +let db; +(async () => { + db = await open({ + filename: "./database.db", + driver: sqlite3.Database, + }); +})(); + +(async () => { + db = await open({ + filename: "./database.db", + driver: sqlite3.Database, + }); + await db.exec(`CREATE TABLE IF NOT EXISTS account ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL UNIQUE, + passwordHash TEXT NOT NULL, + token TEXT + )`); +})(); app.use( cors({ origin: "*", methods: ["GET", "POST"], optionsSuccessStatus: 200, - }) + }), ); app.use(express.json()); -switch (process.env.DATABASE.toLowerCase()) { - case "mongodb": - console.log("Using MongoDB."); - async function ConnectMongoDB() { - await mongoose.connect( - `mongodb+srv://${encodeURIComponent( - process.env.DB_USER - )}:${encodeURIComponent(process.env.DB_PASSWORD)}@${ - process.env.DB_HOST - }/?retryWrites=true&w=majority&appName=${process.env.DB_NAME}`, - { - useNewUrlParser: true, - useUnifiedTopology: true, - } - ); - } - - ConnectMongoDB(); - - const db = mongoose.connection; - - db.on("error", console.error.bind(console, "connection error:")); - db.once("open", function () { - console.log("Connected to MongoDB"); - }); - - const accountSchema = new mongoose.Schema({ - username: String, - passwordHash: String, - token: String, - isAdmin: Boolean, - isBanned: Boolean, - }); - - const AccountModel = mongoose.model("Account", accountSchema); - if (process.env.DATABASE.toLowerCase() === "mongodb") { - Account = AccountModel; - } - - app.post("/api/checktoken", async (req, res) => { - console.log(`Token check from ${req.ip}`); - const data = req.body; - let token = data.token; - - if (!token) { - res.status(400).send("No token provided"); - return; - } +app.post("/api/checktoken", async (req, res) => { + const { token } = req.body; - let account = await Account.findOne({ token: token }); - - if (account) { - res.status(200).send("Token is valid"); - } else { - res.status(401).send("Token is invalid"); - } - }); + if (!token) { + res.status(400).send("No token provided"); + return; + } - app.post("/api/login", async (req, res) => { - const data = req.body; - let username = data.username; + const account = await db.get(`SELECT username FROM account WHERE token = ?`, [ + token, + ]); - console.log(`Login request from ${req.ip} as ${username}`); - if (!new RegExp("^(([A-Za-z0-9]){3,16})+$").test(username)) { - res - .status(400) - .send( - "Username must be 3-16 characters long and contain only letters and numbers" - ); - return; - } + if (account) { + res.status(200).json({ message: "Token is valid" }); + } else { + res.status(401).json({ message: "Token is invalid" }); + } +}); - let password = data.password; - if (!new RegExp("^([A-Za-z0-9])+$").test(password)) { - res.status(400).send("Password must contain only letters and numbers"); - return; - } +app.post("/api/login", async (req, res) => { + const data = req.body; + let username = data.username; - let passwordHash = nodeCrypto.hash( - "sha256", - nodeCrypto.hash("sha512", password) + console.log(`Login request from ${req.ip} as ${username}`); + if (!new RegExp("^(([A-Za-z0-9]){3,16})+$").test(username)) { + res + .status(400) + .send( + "Username must be 3-16 characters long and contain only letters and numbers", ); - - let account = await Account.findOne({ username: username }); - - if (account) { - if (passwordHash === account.passwordHash) { - if (account.isBanned) { - res.status(403).send("You are banned from the server."); - return; - } - - if (account.token === null) { - let token = nodeCrypto.randomBytes(16).toString("hex"); - account.token = token; - await account.save(); - res.status(200).json({ token: token }); - } else { - res.status(200).json({ token: account.token }); - } - } else { - res.status(401).send("Invalid password"); - } + return; + } + let password = data.password; + if (!new RegExp("^([A-Za-z0-9])+$").test(password)) { + res.status(400).send("Password must contain only letters and numbers"); + return; + } + + let passwordHash = nodeCrypto.createHash("sha512").update(password).digest("hex"); + + const account = await db.get(`SELECT * FROM account WHERE username = ?`, [ + username, + ]); + + if (account) { + if (passwordHash === account.passwordHash) { + if (account.token === null) { + let token = nodeCrypto.randomBytes(16).toString("hex"); + await db.run(`UPDATE account SET token = ? WHERE username = ?`, [ + token, + username, + ]); + res.status(200).json({ token: token }); } else { - res.status(404).send("Account not found"); - } - }); - - app.post("/api/register", async (req, res) => { - const data = req.body; - - let username = data.username; - let password = data.password; - console.log(`Register request from ${req.ip} as ${username}`); - - if (!new RegExp("^([A-Za-z0-9])+$").test(password)) { - res.status(400).send("Password must contain only letters and numbers"); - return; - } - - if (new RegExp("^(([A-Za-z0-9]){3,16})+$").test(username)) { - let account = await Account.findOne({ username: username }); - - if (account) { - res.status(409).send("Username already exists"); - } else { - let passwordHash = nodeCrypto.hash( - "sha256", - nodeCrypto.hash("sha512", password) - ); - let newAccount = new Account({ - username: username, - passwordHash: passwordHash, - token: null, - isAdmin: false, - }); - await newAccount.save(); - res.status(200).send("Account created"); - } - } else { - res - .status(400) - .send( - "Username must be 3-16 characters long and contain only letters and numbers" - ); - } - }); - - break; - - case "mysql": - console.log("Using MySQL."); - - let connection; - - async function ConnectMySQL() { - connection = await mysql.createConnection({ - host: process.env.DB_HOST, - user: process.env.DB_USER, - password: process.env.DB_PASSWORD, - database: process.env.DB_NAME, - }); - - try { - await connection.connect(); - console.log("Connected to MySQL"); - } catch (error) { - console.error("Error connecting to MySQL:", error); + res.status(200).json({ token: account.token }); } + } else { + res.status(401).send("Invalid password"); } + } else { + res.status(404).send("Account not found"); + } +}); - ConnectMySQL(); - - pool = mysql.createPool({ - host: process.env.DB_HOST, - user: process.env.DB_USER, - password: process.env.DB_PASSWORD, - database: process.env.DB_NAME, - }); - - app.post("/api/checktoken", async (req, res) => { - console.log(`Token check from ${req.ip}`); - const token = req.body; - - if (!token) { - res.status(400).send("No token provided"); - return; - } - - const [rows] = await pool.query( - `SELECT username FROM account WHERE token = "${token}";` - ); - - console.log(rows); - - if (rows.length > 0) { - res.status(200).json({ message: "Token is valid" }); - } else { - res.status(401).json({ message: "Token is invalid" }); - } - }); - - app.post("/api/login", async (req, res) => { - const data = req.body; - let username = data.username; - - console.log(`Login request from ${req.ip} as ${username}`); - if (!new RegExp("^(([A-Za-z0-9]){3,16})+$").test(username)) { - res - .status(400) - .send( - "Username must be 3-16 characters long and contain only letters and numbers" - ); - return; - } - let password = data.password; - if (!new RegExp("^([A-Za-z0-9])+$").test(password)) { - res.status(400).send("Password must contain only letters and numbers"); - return; - } - - let passwordHash = nodeCrypto.hash( - "sha256", - nodeCrypto.hash("sha512", password) +app.post("/api/register", async (req, res) => { + const data = req.body; + + let username = data.username; + let password = data.password; + + console.log(`Register request from ${req.ip} as ${username}`); + if (!new RegExp("^([A-Za-z0-9])+$").test(password)) { + res.status(400).send("Password must contain only letters and numbers"); + return; + } + + if (new RegExp("^(([A-Za-z0-9]){3,16})+$").test(username)) { + const account = await db.get(`SELECT * FROM account WHERE username = ?`, [ + username, + ]); + if (account) { + res.status(409).send("Username already exists"); + } else { + let passwordHash = nodeCrypto.createHash("sha512").update(password).digest("hex"); + await db.run( + `INSERT INTO account (username, passwordHash, token) VALUES (?, ?, NULL)`, + [username, passwordHash], ); - - const [rows] = await pool.query( - "SELECT * FROM account WHERE username = ?", - [username] + res.status(200).send("Account created"); + } + } else { + res + .status(400) + .send( + "Username must be 3-16 characters long and contain only letters and numbers", ); - - if (rows.length > 0) { - let account = rows[0]; - - if (passwordHash === account.passwordHash) { - if (account.token === null) { - let token = nodeCrypto.randomBytes(16).toString("hex"); - await pool.query( - "UPDATE account SET token = ? WHERE username = ?", - [token, username] - ); - res.status(200).json({ token: token }); - } else { - res.status(200).json({ token: account.token }); - } - } else { - res.status(401).send("Invalid password"); - } - } else { - res.status(404).send("Account not found"); - } - }); - - app.post("/api/register", async (req, res) => { - const data = req.body; - - let username = data.username; - let password = data.password; - - console.log(`Register request from ${req.ip} as ${username}`); - if (!new RegExp("^([A-Za-z0-9])+$").test(password)) { - res.status(400).send("Password must contain only letters and numbers"); - return; - } - - if (new RegExp("^(([A-Za-z0-9]){3,16})+$").test(username)) { - const [rows] = await pool.query( - "SELECT * FROM account WHERE username = ?", - [username] - ); - if (rows.length > 0) { - res.status(409).send("Username already exists"); - } else { - let passwordHash = nodeCrypto.hash( - "sha256", - nodeCrypto.hash("sha512", password) - ); - await pool.query( - "INSERT INTO account (username, passwordHash, token, isAdmin, isBanned) VALUES (?, ?, NULL, FALSE, FALSE)", - [username, passwordHash] - ); - res.status(200).send("Account created"); - } - } else { - res - .status(400) - .send( - "Username must be 3-16 characters long and contain only letters and numbers" - ); - } - }); - break; - default: - console.error("Invalid database selected"); - process.exit(1); - break; -} + } +}); nextApp.prepare().then(() => { const server = http.createServer(app); - const io = new socketIo.Server(server); - + const io = new socketIo(server); + + /** + * Handles a new socket connection. + * + * @param socket - The socket instance representing the connection. + * + * This function sets up event listeners for the following events: + * - "connectionPing": Verifies the provided token and announces the connection if valid. + * - "message": Validates and sanitizes incoming messages, then broadcasts them if the token is valid. + * + * Events: + * - "connectionPing": Expects a token and verifies it against the database. If valid, announces the connection. + * - "message": Expects an object with `token` and `message` properties. Validates and sanitizes the message, then broadcasts it if the token is valid. + * + * Error Handling: + * - Logs any errors encountered during database queries. + * - Emits an error event if the token is invalid or if there are issues parsing the token. + */ const onConnection = (socket) => { console.log(`User ${socket.handshake.address} connected`); - + socket.on("connectionPing", async (token) => { try { - if (process.env.DATABASE === "mongodb") { - var account = await Account.findOne({ token }); - } - else { - var [rows] = await pool.query("SELECT * FROM account WHERE token = ?", [token]); - var account = rows[0]; - } + const account = await db.get(`SELECT * FROM account WHERE token = ?`, [ + token, + ]); if (account) { io.emit("announcement", `${account.username} has connected!`); } } catch (error) { console.error("Error executing query:", error); } - }) + }); socket.on("message", async (message) => { if (!message || !message.token || !message.message) { @@ -374,60 +205,11 @@ nextApp.prepare().then(() => { .replace(/"/g, """); try { - if (process.env.DATABASE === "mongodb") { - var account = await Account.findOne({ token }); - } else { - var [rows] = await pool.query( - "SELECT * FROM account WHERE token = ?", - [token] - ); - var account = rows[0]; - } + const account = await db.get(`SELECT * FROM account WHERE token = ?`, [ + token, + ]); if (account) { - if (account.isAdmin) { - io.emit("adminMessage", `${account.username}: ${content}`); - - if (content.startsWith("?ban")) { - let username = content.split(" ")[1]; - if (username) { - if (process.env.DATABASE === "mongodb") { - let target = await Account.findOne({ username: username }); - if (target.isAdmin) { - socket.emit("announcement", "You cannot ban another admin"); - return; - } - await Account.updateOne({ username: username }, { isBanned: true }); - } else { - await pool.query("UPDATE account SET isBanned = TRUE WHERE username = ?", [username]); - } - - io.emit("announcement", `${username} has been banned by admin ${account.username}`); - - let target = io.sockets.sockets.find((socket) => socket.handshake.auth.token === username); - if (target) { - target.emit("error", JSON.stringify({ message: `You have been banned by Admin ${account.username}`, logout: true })); - } - } else { - socket.emit("announcement", "Invalid target, or arguments."); - } - } else if (content.startsWith("?unban")) { - let username = content.split(" ")[1]; - if (username) { - if (process.env.DATABASE === "mongodb") { - await Account.updateOne({ username: username }, { isBanned: false }); - } - else { - await pool.query("UPDATE account SET isBanned = FALSE WHERE username = ?", [username]); - } - io.emit("announcement", `${username} has been forgiven by admin ${account.username}`); - } - else { - socket.io.emit("announcement", "Invalid target, or arguments."); - } - } - } else { - io.emit("message", `${account.username}: ${content}`); - } + io.emit("message", `${account.username}: ${content}`); } else { io.emit("error", JSON.stringify({ logout: true })); } @@ -435,17 +217,6 @@ nextApp.prepare().then(() => { console.error("Error executing query:", error); } }); - - socket.on("disconnect", async (token) => { - console.log(`User ${socket.handshake.address} disconnected`); - if (process.env.DATABASE === "mongodb") { - var account = await Account.findOne({ token }); - } else { - var [rows] = await pool.query("SELECT * FROM account WHERE token = ?", [token]); - var account = rows[0]; - } - io.emit("announcement", `User ${account} has disconnected`); - }); }; io.on("connection", onConnection); @@ -454,8 +225,7 @@ nextApp.prepare().then(() => { let port = process.env.SERVER_PORT || 80; - server.listen(port, (err) => { - if (err) throw err; + server.listen(port, () => { console.log(`> Ready on http://localhost:${port}`); }); diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 1c6d63e..4a7d291 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -32,8 +32,6 @@ export default function Login() { setError("Invalid username or password"); } else if (response.status === 500) { setError("An error occurred while logging in"); - } else if (response.status === 403) { - setError("You are banned from the server."); } else { setError("An error occurred while logging in"); } @@ -60,7 +58,7 @@ export default function Login() { type="text" value={username} onChange={(e) => setUsername(e.target.value)} - className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" + className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm text-black" />
@@ -75,7 +73,7 @@ export default function Login() { type="password" value={password} onChange={(e) => setPassword(e.target.value)} - className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" + className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm text-black" />
- {error &&

{error}

} +
+ + setUsername(e.target.value)} + onInput={(e) => checkUsername(e.currentTarget.value)} + className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm text-black" + /> +
+
+ + setPassword(e.target.value)} + className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm text-black" + /> +
+
+ + setConfirmPassword(e.target.value)} + className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm text-black" + /> +
+ + {error &&

{error}

}