Add ID generation methods, add tags to userset updates

This commit is contained in:
Hri7566 2024-08-03 06:50:56 -04:00
parent 05299383a4
commit ee2d6c4dde
13 changed files with 99 additions and 52 deletions

View File

@ -2,3 +2,4 @@ DATABASE_URL="file:./db.sqlite"
PORT=8443
ADMIN_PASS=
SALT=
COLOR_SALT=

View File

@ -26,6 +26,7 @@ Brandon's server originally used MongoDB for storing user data, but there are to
- Usernames/colors
- Allowing color changing can be toggled in the config, similar to MPP.com
- Default user parameters can be set
- Configurable ID and color generation methods
- Channels
- Channel list
- Channel settings
@ -46,6 +47,8 @@ Brandon's server originally used MongoDB for storing user data, but there are to
- Server must be setup as a pm2/docker/systemd process for automatic restarting
- Ability to change tags
- Similar to the MPP.net server, but uses a Brandon-style admin message
- Ability to rename channels
- Chat clearing similar to MPP.net
## TODO
@ -67,6 +70,7 @@ Brandon's server originally used MongoDB for storing user data, but there are to
- Test every frontend
- Test fishing bot
- Remote console
- Modify frontend to use templating
## Backlog/Notes
@ -75,7 +79,6 @@ Brandon's server originally used MongoDB for storing user data, but there are to
- Split script.js into multiple files
- Implement tags as a server option, toggles code on frontend
- Same with color changing
- Bun memory usage can skyrocket
- Reload config files on save
- Expose API?
@ -115,7 +118,7 @@ such as enabling the color changing option in the userset modal menu, or sending
$ cp .env.template .env
```
Edit `.env` to your needs.
Edit `.env` to your needs. Some variables are required for certain features to work.
- Edit the files in the `config` folder to match your needs

View File

@ -1,9 +1,8 @@
# Which channels to load on startup.
# Channel config file
forceLoad:
- lobby
- test/awkward
# Default channel settings for lobby channels.
lobbySettings:
lobby: true
chat: true
@ -11,36 +10,20 @@ lobbySettings:
visible: true
color: "#73b3cc"
color2: "#273546"
# Default channel settings for normal user-created channels.
# Note that this allows for channel settings users can't set, like visible and lobby.
defaultSettings:
chat: true
crownsolo: false
color: "#3b5054"
color2: "#001014"
visible: true
# Regex patterns for lobby channel names.
# Any channel name that matches any of these patterns will be considered a lobby channel on instantiation.
lobbyRegexes:
- ^lobby[0-9][0-9]$
- ^lobby[0-9]$
- ^lobby$
- ^lobbyNaN$
- ^test/.+$
# The channel to use for the lobby backdoor.
lobbyBackdoor: lolwutsecretlobbybackdoor
# The channel that users get sent to when they are banned from a channel/join a channel they are already banned in/join a channel that is full and not a regular lobby.
# This will not be used for real lobby channels. (channels that start with "lobby" and may have numbers on the end)
fullChannel: test/awkward
# Whether or not to publish channel user limits in the channel list.
sendLimit: false
# Whether to give a user the crown when they join a channel they were already the owner of when they left.
# Reportedly, this is a feature on the original server, but it's not working there.
# This is corrected in MPP.net's server.
chownOnRejoin: true
sendTags: false

View File

@ -1,3 +1,5 @@
# Notification config file
# Whether to allow HTML in notifications.
# This is a security risk, so only enable this if you trust your admins.
allowXSS: true

View File

@ -1,3 +1,5 @@
# Rate limit config file
# Difference between rate limits and rate limit chains:
# Rate limits will not allow anything to be sent until the rate limit interval has passed.
# Rate limit chains, on the other hand, will allow messages to be sent until the rate limit chain's limit has been reached.

View File

@ -1,24 +1,29 @@
# User data config file
# The default username for new users.
defaultName: Anonymous
# The default user flags for new users.
# These flags control arbitrary data that could be checked by any part of the code.
# This is an internal feature available on MPP.com, but not MPP.net.
defaultFlags:
volume: 100
# Whether or not to allow users to change their color.
# Brandon's server has this set to false, but multiple users have reported it to be on before 2016.
# Based on some reports, the MPP.com server stopped allowing this around 2016.
enableColorChanging: true
# Allows custom data inside note messages.
# This was in the original server, but not in MPP.net's server.
# This only exists for backwards compatibility with scripts like nagalun's drarwing script.
# Whether to allow custom data inside note messages.
# This was in the original server, but not in MPP.net's server do to stricter sanitization.
# This only exists for backwards compatibility with scripts like nagalun's drawing script.
enableCustomNoteData: true
# Whether or not to enable tags that are sent publicly.
# This won't prevent admins from changing tags internally, but it will not be sent to clients.
# This won't prevent admins from changing tags internally, but they will not be sent to clients if set to false.
enableTags: true
# This is the user data that the server will use to send admin chat messages with.
# This is a feature available on MPP.com, but was unknown to the MPP.net developers, therefore not implemented on MPP.net.
adminParticipant:
_id: "0"
name: mpp
@ -30,12 +35,28 @@ adminParticipant:
enableAdminEval: true
# The token validation scheme. Valid values are "none", "jwt" and "uuid".
# This server will still validate existing tokens generated with other schemes if not set to "none".
tokenAuth: none
# This server will still validate existing tokens generated with other schemes if not set to "none", mimicking MPP.net's server.
# This is set to "none" by default because MPP.com does not have a token system.
tokenAuth: jwt
# The browser challenge scheme. Valid values are "none", "obf" and "basic".
# The browser challenge scheme. Valid options are "none", "obf" and "basic".
# This is to change what is sent in the "b" message.
# "none" will disable the browser challenge,
# "obf" will sent an obfuscated function to the client,
# and "basic" will just send a simple function that expects a boolean.
browserChallenge: none
browserChallenge: basic
# Scheme for generating user IDs.
# Valid options are "random", "sha256", "mpp" and "uuid".
# "random" will generate a random ID. As of writing, this is in use by MPP.com's server, but likely a mistake or poor workaround.
# "sha256" will generate a hash of the user's IP address and the server's SALT with the SHA256 algorithm.
# "mpp" will generate a hash of the user's IP address in the same way that MPP.com and MPP.net do. This is the default.
# "uuid" will generate a UUID for the user ID.
idGeneration: mpp
# Scheme for generating user colors.
# Valid options are "random", "sha256", "mpp" and "white".
# "random" will generate a random color for the user. This is not a known feature of any other server.
# "sha256" will generate a color based on a hash of the user's ID.
# "mpp" will generate a color based on the user's ID with a separate salt variable. This salt must be provided in the "COLOR_SALT" environment variable in the .env file.
colorGeneration: mpp

View File

@ -18,6 +18,7 @@ model User {
flags String @default("{}") // JSON flags object
tag String // JSON tag
tokens String @default("[]") // JSON tokens
group String @default("default") // Permission group
}
model ChatHistory {

View File

@ -53,7 +53,9 @@ export class Channel extends EventEmitter {
}
private async deleteChatHistory() {
await deleteChatHistory(this.getID());
try {
await deleteChatHistory(this.getID());
} catch (err) { }
}
public logger: Logger;

View File

@ -1,5 +1,6 @@
import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";
import { config } from "../ws/usersConfig";
// Best way to do env ever
export const env = createEnv({
@ -7,7 +8,8 @@ export const env = createEnv({
PORT: z.coerce.number(),
HOST: z.union([z.string().url(), z.string().ip()]).optional(),
SALT: z.string().min(10),
ADMIN_PASS: z.string()
ADMIN_PASS: z.string(),
COLOR_SALT: config.colorGeneration == "mpp" ? z.string().min(10) : z.string().optional(),
},
isServer: true,
// Bun loads process.env automatically so we don't have to use modules

View File

@ -1,5 +1,6 @@
import { createHash, randomBytes } from "crypto"; import env from "./env";
import { spoop_text } from "./helpers";
import { config } from "../ws/usersConfig";
export function createID() {
// Maybe I could make this funnier than it needs to be...
@ -21,24 +22,46 @@ export function createID() {
}
export function createUserID(ip: string) {
return createHash("sha256")
.update(ip)
.update(env.SALT)
.digest("hex")
.substring(0, 24);
if (config.idGeneration == "random") {
return createID();
} else if (config.idGeneration == "sha256") {
return createHash("sha256")
.update(ip)
.update(env.SALT)
.digest("hex")
.substring(0, 24);
} else if (config.idGeneration == "mpp") {
return createHash("md5")
.update("::ffff:" + ip + env.SALT)
.digest("hex")
.substring(0, 24);
}
}
export function createSocketID() {
return crypto.randomUUID();
}
export function createColor(ip: string) {
return (
"#" +
createHash("sha256")
.update(ip)
export function createColor(_id: string) {
if (config.colorGeneration == "random") {
return "#" + Math.floor(Math.random() * 16777215).toString(16);
} else if (config.colorGeneration == "sha256") {
return "#" + createHash("sha256")
.update(_id)
.update(env.SALT)
.digest("hex")
.substring(24, 24 + 6)
);
.substring(24, 24 + 6);
} else if (config.colorGeneration == "mpp") {
const hash = createHash("md5");
hash.update(_id + env.COLOR_SALT);
const output = hash.digest();
const r = output.readUInt8(0) - 0x40;
const g = output.readUInt8(1) + 0x20;
const b = output.readUInt8(2);
return "#" + r.toString(16) + g.toString(16) + b.toString(16);
} else if (config.colorGeneration == "white") {
return "#ffffff";
}
}

View File

@ -143,12 +143,14 @@ export class Socket extends EventEmitter {
// Send a challenge to the browser for MPP.net frontends
if (config.browserChallenge == "basic") {
// Basic function
this.sendArray([{
m: "b",
code: `~return true;`
}]);
} else if (config.browserChallenge == "obf") {
// Obfuscated challenge building
// TODO
}
})();
@ -524,7 +526,8 @@ export class Socket extends EventEmitter {
id: part.id,
name: part.name,
x: cursorPos.x,
y: cursorPos.y
y: cursorPos.y,
tag: config.enableTags ? part.tag : undefined
}
]);
}

View File

@ -50,11 +50,11 @@ export const hi: ServerEventListener<"hi"> = {
// Validate the token
const valid = await validateToken(socket.getUserID(), msg.token);
if (!valid) {
socket.ban(60000, "Invalid token");
return;
//socket.ban(60000, "Invalid token");
//return;
} else {
token = msg.token;
}
token = msg.token;
}
}

View File

@ -11,6 +11,8 @@ export interface UsersConfig {
enableAdminEval: boolean;
tokenAuth: "jwt" | "uuid" | "none";
browserChallenge: "none" | "obf" | "basic";
idGeneration: "random" | "sha256" | "mpp" | "uuid";
colorGeneration: "random" | "sha256" | "mpp" | "white";
}
export const usersConfigPath = "config/users.yml";
@ -31,7 +33,9 @@ export const defaultUsersConfig: UsersConfig = {
},
enableAdminEval: false,
tokenAuth: "none",
browserChallenge: "none"
browserChallenge: "none",
idGeneration: "mpp",
colorGeneration: "mpp"
};
// Importing this elsewhere causes bun to segfault