wanbotz-security
Version:
Protect Your Script Using WanBotz Security
315 lines (254 loc) ⢠9.75 kB
JavaScript
const fs = require("fs");
const chalk = require("chalk");
const readlineSync = require("readline-sync");
const passwordPrompt = require("password-prompt");
const { Pool } = require("pg");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const readline = require("readline");
function question(query) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve) => rl.question(query, (answer) => {
rl.close();
resolve(answer);
}));
}
const pool = new Pool({
connectionString: "postgresql://WanDB_owner:npg_4bOotp5KADWQ@ep-lively-tooth-a8czukgu-pooler.eastus2.azure.neon.tech/WanDB?sslmode=require",
ssl: { rejectUnauthorized: false }
});
const SECRET_KEY = "WanzzDevsJaya2025";
const path = require("path");
const SESSION_DIR = "./session";
const SESSION_FILE = path.join(SESSION_DIR, "authed.json");
if (!fs.existsSync(SESSION_DIR)) {
fs.mkdirSync(SESSION_DIR, { recursive: true });
}
if (!fs.existsSync(SESSION_FILE)) {
fs.writeFileSync(SESSION_FILE, "{}");
}
async function getPassword(promptText) {
return await passwordPrompt(promptText, { method: "hide" });
}
async function register() {
console.log(chalk.green("\n====== REGISTER ======"));
const username = readlineSync.question("Username: ");
const number = readlineSync.question("Nomor HP (628xxx): ");
const password = await getPassword("Password: ");
if (!username || !number || !password) {
console.log(chalk.red("Harap isi semua pertanyaan!"));
return;
}
try {
const hashedPassword = await bcrypt.hash(password, 10);
const token = jwt.sign({ username }, SECRET_KEY, { expiresIn: "7d" });
await pool.query("INSERT INTO users (username, password, number, token) VALUES ($1, $2, $3, $4)",
[username, hashedPassword, number, token]);
console.log(chalk.green("Registerasi Berhasilš!"));
} catch (err) {
console.log(chalk.red("Gagal register, mungkin username atau nomor telah terpakai."));
}
}
async function login() {
console.log(chalk.blue("\n====== LOGIN ======"));
const username = await question("Username: ");
try {
const result = await pool.query("SELECT * FROM users WHERE username = $1", [username]);
if (result.rows.length === 0) {
console.log(chalk.red("User tidak ditemukan!"));
return;
}
const user = result.rows[0];
let sessions = {};
if (fs.existsSync(SESSION_FILE)) {
sessions = JSON.parse(fs.readFileSync(SESSION_FILE));
}
if (sessions[username] === user.token) {
console.log(chalk.green("Login sukses!"));
return;
}
const password = await getPassword("Password: ");
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) {
console.log(chalk.red("Password salah!"));
return;
}
sessions[username] = user.token;
fs.writeFileSync(SESSION_FILE, JSON.stringify(sessions, null, 2));
console.log(chalk.green("Login sukses!"));
} catch (err) {
console.log(chalk.red("Terjadi kesalahan saat login!"));
}
}
async function deleteUser() {
console.log(chalk.red("\n====== DELETE USERS ======"));
const username = readlineSync.question("Masukkan username: ");
try {
const result = await pool.query("SELECT * FROM users WHERE username = $1", [username]);
if (result.rows.length === 0) {
console.log(chalk.red("User tidak ditemukan!"));
return;
}
const konfirmasi = readlineSync.question(`Apakah anda yakin ingin menghapus "${username}"? (y/n): `);
if (konfirmasi.toLowerCase() !== "y") {
console.log(chalk.blue("Penghapusan dibatalkan"));
return;
}
await pool.query("DELETE FROM users WHERE username = $1", [username]);
if (fs.existsSync(SESSION_FILE)) {
let sessions = JSON.parse(fs.readFileSync(SESSION_FILE));
delete sessions[username];
fs.writeFileSync(SESSION_FILE, JSON.stringify(sessions, null, 2));
}
console.log(chalk.green(`User "${username}" berhasil dihapus!`));
} catch (err) {
console.log(chalk.red("Terjadi kesalahan saat menghapus user!"));
}
}
async function resetPassword() {
console.log(chalk.cyan("\n====== RESET PASSWORD ======"));
const username = readlineSync.question("Username: ");
try {
const result = await pool.query("SELECT * FROM users WHERE username = $1", [username]);
if (result.rows.length === 0) {
console.log(chalk.red("User tidak ditemukan!"));
return;
}
const user = result.rows[0];
const oldPassword = await getPassword("Password lama: ");
const validPassword = await bcrypt.compare(oldPassword, user.password);
if (!validPassword) {
console.log(chalk.red("Password lama salah!!"));
return;
}
const newPassword = await getPassword("Password baru: ");
if (!newPassword) {
console.log(chalk.red("Password tidak boleh kosong!"));
return;
}
const hashedNewPassword = await bcrypt.hash(newPassword, 10);
await pool.query("UPDATE users SET password = $1 WHERE username = $2", [hashedNewPassword, username]);
console.log(chalk.green("Password berhasil diganti!!"));
} catch (err) {
console.log(chalk.red("Terjadi kesalahan saat mereset password!!"));
}
}
async function renameUser() {
console.log(chalk.yellow("\n====== RENAME USER ======"));
const oldUsername = readlineSync.question("Username lama: ");
try {
const result = await pool.query("SELECT * FROM users WHERE username = $1", [oldUsername]);
if (result.rows.length === 0) {
console.log(chalk.red("User tidak ditemukan!"));
return;
}
const user = result.rows[0];
const password = await getPassword("Password: ");
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) {
console.log(chalk.red("Password salah!"));
return;
}
const newUsername = readlineSync.question("Username baru: ");
if (!newUsername) {
console.log(chalk.red("Username baru tidak boleh kosong!"));
return;
}
const checkUser = await pool.query("SELECT * FROM users WHERE username = $1", [newUsername]);
if (checkUser.rows.length > 0) {
console.log(chalk.red("Username sudah digunakan!"));
return;
}
await pool.query("UPDATE users SET username = $1 WHERE username = $2", [newUsername, oldUsername]);
if (fs.existsSync(SESSION_FILE)) {
let sessions = JSON.parse(fs.readFileSync(SESSION_FILE));
if (sessions[oldUsername]) {
sessions[newUsername] = sessions[oldUsername];
delete sessions[oldUsername];
fs.writeFileSync(SESSION_FILE, JSON.stringify(sessions, null, 2));
}
}
console.log(chalk.green(`Username berhasil diubah dari "${oldUsername}" ke "${newUsername}"!`));
} catch (err) {
console.log(chalk.red("Terjadi kesalahan saat rename username!"));
}
}
async function resetNumber() {
console.log(chalk.magenta("\n====== RESET NUMBER ======"));
const username = readlineSync.question("Username: ");
try {
const result = await pool.query("SELECT * FROM users WHERE username = $1", [username]);
if (result.rows.length === 0) {
console.log(chalk.red("User tidak ditemukan!"));
return;
}
const user = result.rows[0];
const password = await getPassword("Password: ");
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) {
console.log(chalk.red("Password salah!"));
return;
}
const newNumber = readlineSync.question("Nomor HP baru (628xxx): ");
if (!/^628\d+$/.test(newNumber)) {
console.log(chalk.red("Format nomor HP tidak valid! Harus dimulai dengan 628."));
return;
}
await pool.query("UPDATE users SET number = $1 WHERE username = $2", [newNumber, username]);
console.log(chalk.green("Nomor HP berhasil diperbarui!"));
} catch (err) {
console.log(chalk.red("Terjadi kesalahan saat reset nomor HP!"));
}
}
async function listUsers() {
console.log(chalk.cyan("\n====== LIST USER ======"));
try {
const result = await pool.query("SELECT id, username, number FROM users ORDER BY id ASC");
if (result.rows.length === 0) {
console.log(chalk.red("Tidak ada user terdaftar."));
return;
}
console.log(chalk.yellow("\nID | Username | Nomor HP"));
console.log(chalk.yellow("--------------------------------"));
result.rows.forEach(user => {
console.log(`${user.id.toString().padEnd(4)} | ${user.username.padEnd(12)} | ${user.number}`);
});
} catch (err) {
console.log(chalk.red("Terjadi kesalahan saat mengambil data user!"));
}
}
async function main() {
console.log(chalk.yellow("\n====== Wan Database ======"));
console.log("1. Register");
console.log("2. Login");
console.log("3. Hapus User");
console.log("4. Reset Password");
console.log("5. Rename User");
console.log("6. Reset Number");
console.log("7. List User");
console.log("8. Exit");
const pilihan = readlineSync.question("Pilih menu: ");
if (pilihan === "1") {
await register();
} else if (pilihan === "2") {
await login();
} else if (pilihan === "3") {
await deleteUser();
} else if (pilihan === "4") {
await resetPassword();
} else if (pilihan === "5") {
await renameUser();
} else if (pilihan === "6") {
await resetNumber();
} else if (pilihan === "7") {
await listUsers();
} else if (pilihan === "0") {
console.log(chalk.blue("Exit..."));
process.exit();
}
main();
}
module.exports = { register, login, deleteUser, resetPassword, renameUser, resetNumber, listUsers, SESSION_DIR, SESSION_FILE }