Add ID generation methods, add tags to userset updates
This commit is contained in:
parent
05299383a4
commit
ee2d6c4dde
|
@ -2,3 +2,4 @@ DATABASE_URL="file:./db.sqlite"
|
||||||
PORT=8443
|
PORT=8443
|
||||||
ADMIN_PASS=
|
ADMIN_PASS=
|
||||||
SALT=
|
SALT=
|
||||||
|
COLOR_SALT=
|
||||||
|
|
|
@ -26,6 +26,7 @@ Brandon's server originally used MongoDB for storing user data, but there are to
|
||||||
- Usernames/colors
|
- Usernames/colors
|
||||||
- Allowing color changing can be toggled in the config, similar to MPP.com
|
- Allowing color changing can be toggled in the config, similar to MPP.com
|
||||||
- Default user parameters can be set
|
- Default user parameters can be set
|
||||||
|
- Configurable ID and color generation methods
|
||||||
- Channels
|
- Channels
|
||||||
- Channel list
|
- Channel list
|
||||||
- Channel settings
|
- 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
|
- Server must be setup as a pm2/docker/systemd process for automatic restarting
|
||||||
- Ability to change tags
|
- Ability to change tags
|
||||||
- Similar to the MPP.net server, but uses a Brandon-style admin message
|
- Similar to the MPP.net server, but uses a Brandon-style admin message
|
||||||
|
- Ability to rename channels
|
||||||
|
- Chat clearing similar to MPP.net
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
@ -67,6 +70,7 @@ Brandon's server originally used MongoDB for storing user data, but there are to
|
||||||
- Test every frontend
|
- Test every frontend
|
||||||
- Test fishing bot
|
- Test fishing bot
|
||||||
- Remote console
|
- Remote console
|
||||||
|
- Modify frontend to use templating
|
||||||
|
|
||||||
## Backlog/Notes
|
## 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
|
- Split script.js into multiple files
|
||||||
- Implement tags as a server option, toggles code on frontend
|
- Implement tags as a server option, toggles code on frontend
|
||||||
- Same with color changing
|
- Same with color changing
|
||||||
- Bun memory usage can skyrocket
|
|
||||||
- Reload config files on save
|
- Reload config files on save
|
||||||
- Expose API?
|
- Expose API?
|
||||||
|
|
||||||
|
@ -115,7 +118,7 @@ such as enabling the color changing option in the userset modal menu, or sending
|
||||||
$ cp .env.template .env
|
$ 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
|
- Edit the files in the `config` folder to match your needs
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
# Which channels to load on startup.
|
# Channel config file
|
||||||
|
|
||||||
forceLoad:
|
forceLoad:
|
||||||
- lobby
|
- lobby
|
||||||
- test/awkward
|
- test/awkward
|
||||||
|
|
||||||
# Default channel settings for lobby channels.
|
|
||||||
lobbySettings:
|
lobbySettings:
|
||||||
lobby: true
|
lobby: true
|
||||||
chat: true
|
chat: true
|
||||||
|
@ -11,36 +10,20 @@ lobbySettings:
|
||||||
visible: true
|
visible: true
|
||||||
color: "#73b3cc"
|
color: "#73b3cc"
|
||||||
color2: "#273546"
|
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:
|
defaultSettings:
|
||||||
chat: true
|
chat: true
|
||||||
crownsolo: false
|
crownsolo: false
|
||||||
color: "#3b5054"
|
color: "#3b5054"
|
||||||
color2: "#001014"
|
color2: "#001014"
|
||||||
visible: true
|
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:
|
lobbyRegexes:
|
||||||
- ^lobby[0-9][0-9]$
|
- ^lobby[0-9][0-9]$
|
||||||
- ^lobby[0-9]$
|
- ^lobby[0-9]$
|
||||||
- ^lobby$
|
- ^lobby$
|
||||||
- ^lobbyNaN$
|
- ^lobbyNaN$
|
||||||
- ^test/.+$
|
- ^test/.+$
|
||||||
|
|
||||||
# The channel to use for the lobby backdoor.
|
|
||||||
lobbyBackdoor: lolwutsecretlobbybackdoor
|
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
|
fullChannel: test/awkward
|
||||||
|
|
||||||
# Whether or not to publish channel user limits in the channel list.
|
|
||||||
sendLimit: false
|
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
|
chownOnRejoin: true
|
||||||
|
sendTags: false
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# Notification config file
|
||||||
|
|
||||||
# Whether to allow HTML in notifications.
|
# Whether to allow HTML in notifications.
|
||||||
# This is a security risk, so only enable this if you trust your admins.
|
# This is a security risk, so only enable this if you trust your admins.
|
||||||
allowXSS: true
|
allowXSS: true
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# Rate limit config file
|
||||||
|
|
||||||
# Difference between rate limits and rate limit chains:
|
# 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 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.
|
# Rate limit chains, on the other hand, will allow messages to be sent until the rate limit chain's limit has been reached.
|
||||||
|
|
|
@ -1,24 +1,29 @@
|
||||||
|
# User data config file
|
||||||
|
|
||||||
# The default username for new users.
|
# The default username for new users.
|
||||||
defaultName: Anonymous
|
defaultName: Anonymous
|
||||||
|
|
||||||
# The default user flags for new users.
|
# 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:
|
defaultFlags:
|
||||||
volume: 100
|
volume: 100
|
||||||
|
|
||||||
# Whether or not to allow users to change their color.
|
# 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
|
enableColorChanging: true
|
||||||
|
|
||||||
# Allows custom data inside note messages.
|
# Whether to allow custom data inside note messages.
|
||||||
# This was in the original server, but not in MPP.net's server.
|
# 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 drarwing script.
|
# This only exists for backwards compatibility with scripts like nagalun's drawing script.
|
||||||
enableCustomNoteData: true
|
enableCustomNoteData: true
|
||||||
|
|
||||||
# Whether or not to enable tags that are sent publicly.
|
# 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
|
enableTags: true
|
||||||
|
|
||||||
# This is the user data that the server will use to send admin chat messages with.
|
# 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:
|
adminParticipant:
|
||||||
_id: "0"
|
_id: "0"
|
||||||
name: mpp
|
name: mpp
|
||||||
|
@ -30,12 +35,28 @@ adminParticipant:
|
||||||
enableAdminEval: true
|
enableAdminEval: true
|
||||||
|
|
||||||
# The token validation scheme. Valid values are "none", "jwt" and "uuid".
|
# 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".
|
# This server will still validate existing tokens generated with other schemes if not set to "none", mimicking MPP.net's server.
|
||||||
tokenAuth: none
|
# 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.
|
# This is to change what is sent in the "b" message.
|
||||||
# "none" will disable the browser challenge,
|
# "none" will disable the browser challenge,
|
||||||
# "obf" will sent an obfuscated function to the client,
|
# "obf" will sent an obfuscated function to the client,
|
||||||
# and "basic" will just send a simple function that expects a boolean.
|
# 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
|
||||||
|
|
|
@ -18,6 +18,7 @@ model User {
|
||||||
flags String @default("{}") // JSON flags object
|
flags String @default("{}") // JSON flags object
|
||||||
tag String // JSON tag
|
tag String // JSON tag
|
||||||
tokens String @default("[]") // JSON tokens
|
tokens String @default("[]") // JSON tokens
|
||||||
|
group String @default("default") // Permission group
|
||||||
}
|
}
|
||||||
|
|
||||||
model ChatHistory {
|
model ChatHistory {
|
||||||
|
|
|
@ -53,7 +53,9 @@ export class Channel extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async deleteChatHistory() {
|
private async deleteChatHistory() {
|
||||||
await deleteChatHistory(this.getID());
|
try {
|
||||||
|
await deleteChatHistory(this.getID());
|
||||||
|
} catch (err) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public logger: Logger;
|
public logger: Logger;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { createEnv } from "@t3-oss/env-core";
|
import { createEnv } from "@t3-oss/env-core";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import { config } from "../ws/usersConfig";
|
||||||
|
|
||||||
// Best way to do env ever
|
// Best way to do env ever
|
||||||
export const env = createEnv({
|
export const env = createEnv({
|
||||||
|
@ -7,7 +8,8 @@ export const env = createEnv({
|
||||||
PORT: z.coerce.number(),
|
PORT: z.coerce.number(),
|
||||||
HOST: z.union([z.string().url(), z.string().ip()]).optional(),
|
HOST: z.union([z.string().url(), z.string().ip()]).optional(),
|
||||||
SALT: z.string().min(10),
|
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,
|
isServer: true,
|
||||||
// Bun loads process.env automatically so we don't have to use modules
|
// Bun loads process.env automatically so we don't have to use modules
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { createHash, randomBytes } from "crypto"; import env from "./env";
|
import { createHash, randomBytes } from "crypto"; import env from "./env";
|
||||||
import { spoop_text } from "./helpers";
|
import { spoop_text } from "./helpers";
|
||||||
|
import { config } from "../ws/usersConfig";
|
||||||
|
|
||||||
export function createID() {
|
export function createID() {
|
||||||
// Maybe I could make this funnier than it needs to be...
|
// Maybe I could make this funnier than it needs to be...
|
||||||
|
@ -21,24 +22,46 @@ export function createID() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createUserID(ip: string) {
|
export function createUserID(ip: string) {
|
||||||
return createHash("sha256")
|
if (config.idGeneration == "random") {
|
||||||
.update(ip)
|
return createID();
|
||||||
.update(env.SALT)
|
} else if (config.idGeneration == "sha256") {
|
||||||
.digest("hex")
|
return createHash("sha256")
|
||||||
.substring(0, 24);
|
.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() {
|
export function createSocketID() {
|
||||||
return crypto.randomUUID();
|
return crypto.randomUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createColor(ip: string) {
|
export function createColor(_id: string) {
|
||||||
return (
|
if (config.colorGeneration == "random") {
|
||||||
"#" +
|
return "#" + Math.floor(Math.random() * 16777215).toString(16);
|
||||||
createHash("sha256")
|
} else if (config.colorGeneration == "sha256") {
|
||||||
.update(ip)
|
return "#" + createHash("sha256")
|
||||||
|
.update(_id)
|
||||||
.update(env.SALT)
|
.update(env.SALT)
|
||||||
.digest("hex")
|
.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";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,12 +143,14 @@ export class Socket extends EventEmitter {
|
||||||
|
|
||||||
// Send a challenge to the browser for MPP.net frontends
|
// Send a challenge to the browser for MPP.net frontends
|
||||||
if (config.browserChallenge == "basic") {
|
if (config.browserChallenge == "basic") {
|
||||||
|
// Basic function
|
||||||
this.sendArray([{
|
this.sendArray([{
|
||||||
m: "b",
|
m: "b",
|
||||||
code: `~return true;`
|
code: `~return true;`
|
||||||
}]);
|
}]);
|
||||||
} else if (config.browserChallenge == "obf") {
|
} else if (config.browserChallenge == "obf") {
|
||||||
|
// Obfuscated challenge building
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -524,7 +526,8 @@ export class Socket extends EventEmitter {
|
||||||
id: part.id,
|
id: part.id,
|
||||||
name: part.name,
|
name: part.name,
|
||||||
x: cursorPos.x,
|
x: cursorPos.x,
|
||||||
y: cursorPos.y
|
y: cursorPos.y,
|
||||||
|
tag: config.enableTags ? part.tag : undefined
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,11 +50,11 @@ export const hi: ServerEventListener<"hi"> = {
|
||||||
// Validate the token
|
// Validate the token
|
||||||
const valid = await validateToken(socket.getUserID(), msg.token);
|
const valid = await validateToken(socket.getUserID(), msg.token);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
socket.ban(60000, "Invalid token");
|
//socket.ban(60000, "Invalid token");
|
||||||
return;
|
//return;
|
||||||
|
} else {
|
||||||
|
token = msg.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
token = msg.token;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ export interface UsersConfig {
|
||||||
enableAdminEval: boolean;
|
enableAdminEval: boolean;
|
||||||
tokenAuth: "jwt" | "uuid" | "none";
|
tokenAuth: "jwt" | "uuid" | "none";
|
||||||
browserChallenge: "none" | "obf" | "basic";
|
browserChallenge: "none" | "obf" | "basic";
|
||||||
|
idGeneration: "random" | "sha256" | "mpp" | "uuid";
|
||||||
|
colorGeneration: "random" | "sha256" | "mpp" | "white";
|
||||||
}
|
}
|
||||||
|
|
||||||
export const usersConfigPath = "config/users.yml";
|
export const usersConfigPath = "config/users.yml";
|
||||||
|
@ -31,7 +33,9 @@ export const defaultUsersConfig: UsersConfig = {
|
||||||
},
|
},
|
||||||
enableAdminEval: false,
|
enableAdminEval: false,
|
||||||
tokenAuth: "none",
|
tokenAuth: "none",
|
||||||
browserChallenge: "none"
|
browserChallenge: "none",
|
||||||
|
idGeneration: "mpp",
|
||||||
|
colorGeneration: "mpp"
|
||||||
};
|
};
|
||||||
|
|
||||||
// Importing this elsewhere causes bun to segfault
|
// Importing this elsewhere causes bun to segfault
|
||||||
|
|
Loading…
Reference in New Issue