summary refs log tree commit diff
diff options
context:
space:
mode:
authorWlodekM <[email protected]>2024-07-03 16:39:35 +0300
committerWlodekM <[email protected]>2024-07-03 16:39:35 +0300
commit7c9edccaa58a1e10c349469bccc44f0834cf4e2f (patch)
tree1e9f75ce9d4742ae3deefae9ffc017ea845ad9d5
parent0912c5ddb27df466ac90bafe7ca72da545259019 (diff)
auth and :jsonGet
-rw-r--r--README.md2
-rw-r--r--accounts.js31
-rw-r--r--commands.js43
-rw-r--r--db/users.json1
-rw-r--r--index.js49
5 files changed, 108 insertions, 18 deletions
diff --git a/README.md b/README.md
index bc14503..e08f31f 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ node index.js
 - ~~Config (JSON)~~
 - ~~MOTD~~
 - ~~Custom commands (plugins)~~
-- Auth (optional)
+- ~~Auth (optional)~~
 
 ## IN PROGRESS
 
diff --git a/accounts.js b/accounts.js
new file mode 100644
index 0000000..f45ab6e
--- /dev/null
+++ b/accounts.js
@@ -0,0 +1,31 @@
+import { createHash } from "crypto"
+import cuid from 'cuid';
+import fs from "fs"
+
+if(!fs.existsSync("db")) fs.mkdirSync("db");
+if(!fs.existsSync("db/users.json")) fs.writeFileSync("db/users.json", "{}");
+
+const db = JSON.parse(fs.readFileSync("db/users.json").toString())
+
+function syncDB() {
+    fs.writeFileSync("db/users.json", JSON.stringify(db))
+}
+
+export function checkAccount(username) {
+    return db[username] != undefined
+}
+
+export function createAccount(username, password) {
+    let hashedPassword = createHash('sha256').update(password).digest('hex');
+    db[username] = {
+        id: cuid(),
+        password: hashedPassword,
+        t: Number(new Date()) / 1000
+    };
+    syncDB();
+}
+
+export function checkPassword(username, password) {
+    let hashedPassword = createHash('sha256').update(password).digest('hex');
+    return db[username]?.password === hashedPassword
+}
\ No newline at end of file
diff --git a/commands.js b/commands.js
index 5c7a440..3fbd63e 100644
--- a/commands.js
+++ b/commands.js
@@ -8,10 +8,10 @@ export const commands = {
             if(args.length < 1) return user.socket.send("Error: You need to specify a channel (example: /join #home).");
             if(!args[0].startsWith("#")) return user.socket.send("Error: Channel not found, run /channels to see a list of channels.");
             if(!server.channels.includes(args[0].replace("#", ""))) return user.socket.send("Error: Channel not found, run /channels to see a list of channels.");
-            sendInChannel(`${user.username} left #${user.channel}.`, user.channel)
+            sendInChannel(`${user.name()} left #${user.channel}.`, user.channel)
             user.channel = args[0].replace("#", "");
-            console.info(`${user.username} went to #${user.channel}`)
-            sendInChannel(`${user.username} joined #${user.channel}!`, user.channel)
+            console.info(`${user.name()} went to #${user.channel}`)
+            sendInChannel(`${user.name()} joined #${user.channel}!`, user.channel)
         }
     },
     'channels': {
@@ -29,8 +29,8 @@ export const commands = {
             if(args[0].length < 3 ) return user.socket.send("Error: Nick too short.");
             if(args[0].length > 20) return user.socket.send("Error: Nick too long.");
             if(Object.values(server.users).find(usr => usr.username == args[0])) return user.socket.send("Error: Nick already used.");
-            sendInChannel(`${user.username} changed their nick to ${args[0]}!`, user.channel)
-            user.username = args[0];
+            sendInChannel(`${user.name()} changed their nick to ${args[0]}!`, user.channel)
+            user.nickname = args[0];
         }
     },
     'about': {
@@ -45,7 +45,7 @@ export const commands = {
         aliases: [],
         command: function({user, server, args}) {
             if(args.length < 1) return user.socket.send('Please provide username');
-            if(Object.values(server.users).find(usr => usr.username == args[0])) return user.socket.send('User not found');
+            if(!Object.values(server.users).find(usr => usr.username == args[0])) return user.socket.send('User not found');
             let userFound = Object.values(server.users).find(usr => usr.username == args[0])
             userFound.id = Object.keys(server.users).find(usr => server.users[usr].username == args[0])
             user.socket.send(`${userFound.username}\nClient: ${userFound.client ?? "<Unknown>"}\nID: ${userFound.id}`)
@@ -55,7 +55,7 @@ export const commands = {
         name: 'users',
         aliases: [],
         command: function({user, server, args}) {
-            user.socket.send(`Users${args[0] != "global" ? ` in ${user.channel}` : ""}:\n${Object.values(server.users).filter(usr => (usr.channel == user.channel) || args[0] == "global").map(usr => ` * ${usr.username}`).join("\n")}`)
+            user.socket.send(`Users${args[0] != "global" ? ` in ${user.channel}` : ""}:\n${Object.values(server.users).filter(usr => (usr.channel == user.channel) || args[0] == "global").map(usr => ` * ${usr.name()}`).join("\n")}`)
         }
     },
     'help': {
@@ -65,6 +65,35 @@ export const commands = {
             user.socket.send(`Commands available:\n${Object.values(commands).map(cmd => `* /${cmd.name} (Aliases: ${(cmd.aliases.join(", ")) || "<None>"})`).join("\n")}`)
         }
     },
+    'login': {
+        name: 'login',
+        aliases: ['signin'],
+        command: function({server, args, user, sendInChannel}) {
+            if(args.length < 2) return user.socket.send(`Usage: /login <username> <password>`);
+            if(!server.accounts.checkAccount(args[0])) return user.socket.send(`Account "${args[0]}" not found!`);
+            if(!server.accounts.checkPassword(args[0], args[1])) return user.socket.send(`Password incorrect.`);
+            user.username = args[0];
+            user.nickname = "";
+            user.guest = false;
+            sendInChannel(`${user.name()} logged in as ${args[0]}!`, user.channel)
+        }
+    },
+    'register': {
+        name: 'register',
+        aliases: ['signup'],
+        command: function({server, args, user, sendInChannel}) {
+            if(args.length < 2) return user.socket.send(`Usage: /register <username> <password>`);
+            if(args[0].length < 3)  return user.socket.send(`Username too short!`);
+            if(args[0].length > 20) return user.socket.send(`Username too long!`);
+            if(args[1].length < 6)  return user.socket.send(`Password too short!`);
+            if(server.accounts.checkAccount(args[0])) return user.socket.send(`User with username "${args[0]}" already exists!`);
+            server.accounts.createAccount(args[0], args[1]);
+            user.username = args[0];
+            user.nickname = "";
+            user.guest = false;
+            sendInChannel(`${user.name()} logged in as ${args[0]}!`, user.channel)
+        }
+    },
 }
 
 export function register(cmd, data) {
diff --git a/db/users.json b/db/users.json
new file mode 100644
index 0000000..6cf28da
--- /dev/null
+++ b/db/users.json
@@ -0,0 +1 @@
+{"wlodekm":{"id":"cly5vozj9000188i8e7wyfrv4","password":"fa4920b0404de71b545ed34855c099d274869553118f5dab6b9d6232a813caf3","t":1720013610.213}}
\ No newline at end of file
diff --git a/index.js b/index.js
index c17c134..73c92db 100644
--- a/index.js
+++ b/index.js
@@ -1,6 +1,7 @@
 import { WebSocketServer } from "ws";
 import { getRandomInt } from "./lib.js"
 import { commands } from "./commands.js";
+import * as accounts from "./accounts.js"
 import cuid from 'cuid';
 import fs from 'fs';
 
@@ -8,6 +9,7 @@ const server = {
     config: JSON.parse(String(fs.readFileSync("config.json"))),
     channels: ["home", "off-topic"],
     users: {},
+    accounts: accounts,
 }
 
 const ws = new WebSocketServer({
@@ -37,10 +39,13 @@ ws.on('connection', (socket, request) => {
         socket.close(1001, "Server full")
     }
     let userID = cuid()
+    console.info(`${userID} joined the server.`)
     socket.send(format(server.config.motd))
     let anonID = getRandomInt(0, 99999)
     server.users[userID] = {
         username: `Anonymous${"0".repeat(5 - anonID.toString().length) + anonID.toString()}`,
+        nickname: `Anonymous${"0".repeat(5 - anonID.toString().length) + anonID.toString()}`,
+        guest: true,
         socket: socket,
         joinReq: request,
         t: {
@@ -48,12 +53,14 @@ ws.on('connection', (socket, request) => {
             unix: Math.floor(new Date().getTime() / 1000),
             str: String(new Date())
         },
-        channel: 'home'
+        channel: 'home',
+        name: function(){return this.nickname != "" ? this.nickname : this.username}
     }
-    console.info(`${server.users[userID].username} joined the server!`)
-    sendInChannel(`${server.users[userID].username} joined #${server.users[userID].channel}!`, server.users[userID].channel)
+    const user = server.users[userID]
+    console.info(`${user.name()} joined the server!`)
+    sendInChannel(`${user.name()} joined #${server.users[userID].channel}!`, server.users[userID].channel)
     socket.on('close', function (code, reason) {
-        sendInChannel(`${server.users[userID].username} left.`, server.users[userID].channel)
+        sendInChannel(`${user.name()} left.`, server.users[userID].channel)
         delete server.users[userID]
     })
     socket.on('message', function (rawData) {
@@ -61,12 +68,12 @@ ws.on('connection', (socket, request) => {
             let args = String(rawData).replace("/", "").split(" ");
             let command = args.shift();
             let commandObj = Object.values(commands).find(cmd => cmd.name == command || cmd.aliases.includes(command))
-            console.log(`${server.users[userID].username} used /${command}`)
+            console.log(`${user.name()} used /${command}`)
             if (!commandObj) return socket.send(`Error: Command "${command}" not found!`);
-            let user = server.users[userID]
             try {
                 commandObj.command({ user, command, args, sendInChannel, server, commands })
             } catch (error) {
+                console.error(error)
                 user.socket.send(`Unexpected error ocurred while running the command`)
             }
             return
@@ -80,24 +87,46 @@ ws.on('connection', (socket, request) => {
             return
         }
         if (rawData.toString().startsWith(":jsonGet")) {
-            let params = String(rawData).replace(":jsonGet", "").split(" ");
+            let params = String(rawData).split(" ");
+            params.shift()
             switch (params[0]) {
                 case 'channels':
                     socket.send(JSON.stringify(server.channels));
                     break;
                 case 'users':
-                    socket.send(JSON.stringify(server.users));
+                    socket.send(JSON.stringify(Object.values(server.users).map(usr => {return {
+                        username: usr.username,
+                        nickname: usr.nickname,
+                        t: usr.t,
+                        channel: user.channel,
+                        displayName: user.name()
+                    }})));
+                    break;
+                case 'usersLocal':
+                    socket.send(
+                        JSON.stringify(
+                            Object.values(server.users)
+                            .filter(usr => (usr.channel == user.channel))
+                            .map(usr => {return {
+                                username: usr.username,
+                                nickname: usr.nickname,
+                                t: usr.t,
+                                channel: user.channel,
+                                displayName: user.name()
+                            }})
+                        ));
                     break;
             
                 default:
+                    socket.send(`unknown "${params[0]}"`);
                     break;
             }
             return
         }
         if (rawData.length < 1) return socket.send("Error: message too short!")
         if (rawData.length >= 2000) return socket.send("Error: message too long!")
-        sendInChannel(`<${server.users[userID].username}> ${rawData}`, server.users[userID].channel)
-        console.log(`(#${server.users[userID].channel}) <${server.users[userID].username}> ${rawData}`)
+        sendInChannel(`<${user.name()}${user.guest ? " (guest)" : ""}> ${rawData}`, server.users[userID].channel)
+        console.log(`(#${server.users[userID].channel}) <${user.name()}> ${rawData}`)
     })
 })