add per-user server passwords

This commit is contained in:
Zoey 2024-04-19 13:17:06 -07:00
parent 38164a6cc5
commit d56bf8b7e4
No known key found for this signature in database
GPG key ID: 8611B896D1AAFAF2
2 changed files with 34 additions and 6 deletions

View file

@ -1,3 +1,5 @@
use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use crate::level::generation::LevelGeneration;
@ -9,8 +11,9 @@ pub struct ServerConfig {
pub name: String,
/// the server's motd
pub motd: String,
/// the server's password, if any
pub password: Option<String>,
/// the server's protection mode
#[serde(rename = "password")]
pub protection_mode: ServerProtectionMode,
/// the level's size
pub level_size: Option<ConfigCoordinates>,
/// the level's spawn point
@ -24,7 +27,7 @@ impl Default for ServerConfig {
Self {
name: "classic server wowie".to_string(),
motd: "here's the default server motd".to_string(),
password: None,
protection_mode: ServerProtectionMode::None,
level_size: None,
spawn: None,
generation: LevelGeneration::Empty,
@ -42,3 +45,15 @@ pub struct ConfigCoordinates {
/// the Z coordinate
pub z: usize,
}
/// enum for the different kinds of server protection
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ServerProtectionMode {
/// the server is unprotected and anyone can join with any username
None,
/// the server requires a password to join, but you can use any username if you know the password
Password(String),
/// the server requires a password to join and the password is checked against each username
PasswordsByUser(BTreeMap<String, String>),
}

View file

@ -14,6 +14,7 @@ use crate::{
client::ClientPacket, server::ServerPacket, PacketReader, PacketWriter, ARRAY_LENGTH,
},
player::{Player, PlayerType},
server::config::ServerProtectionMode,
};
use super::ServerData;
@ -113,11 +114,23 @@ async fn handle_stream_inner(
let mut data = data.write().await;
if let Some(password) = &data.config.password {
match &data.config.protection_mode {
ServerProtectionMode::None => {}
ServerProtectionMode::Password(password) => {
if verification_key != *password {
return Ok(Some("Incorrect password!".to_string()));
}
}
ServerProtectionMode::PasswordsByUser(passwords) => {
if !passwords
.get(&username)
.map(|password| verification_key == *password)
.unwrap_or_default()
{
return Ok(Some("Incorrect password!".to_string()));
}
}
}
for player in &data.players {
if player.username == username {