Formatting and cleanup

This commit is contained in:
2026-04-04 14:33:07 -04:00
parent f17e5061cd
commit 070337577c
20 changed files with 237 additions and 421 deletions

View File

@@ -292,9 +292,6 @@ async fn do_oauth_callback(
Ok(Redirect::temporary(&ui_redirect_uri).into_response())
}
// ------------------------------------------------------------------ //
// LOGIN MODE: look up (or create) the local user for this Discord account
// ------------------------------------------------------------------ //
None => {
// Find existing connection → local user_id
let local_user_id: Option<(Uuid, String)> = sqlx::query_as(
@@ -403,10 +400,6 @@ async fn do_oauth_callback(
}
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
/// Return a username derived from `base` that does not yet exist in `users`.
async fn generate_unique_username(pool: &sqlx::PgPool, base: &str) -> crate::error::Result<String> {
// Truncate to 28 chars to leave room for the `_XXXX` suffix

View File

@@ -41,10 +41,6 @@ pub fn get_routes() -> Router<Arc<AppState>> {
.route("/connections/{provider}", delete(disconnect_provider))
}
// ---------------------------------------------------------------------------
// Payloads
// ---------------------------------------------------------------------------
#[derive(Deserialize)]
struct RegisterPayload {
username: String,
@@ -71,10 +67,6 @@ struct ChangePasswordPayload {
new_password: String,
}
// ---------------------------------------------------------------------------
// Response types
// ---------------------------------------------------------------------------
#[derive(Serialize)]
pub struct ConnectionInfo {
pub provider: String,
@@ -95,10 +87,6 @@ pub struct UserInfo {
pub connections: Vec<ConnectionInfo>,
}
// ---------------------------------------------------------------------------
// DB row types
// ---------------------------------------------------------------------------
#[derive(sqlx::FromRow)]
struct DbUser {
id: Uuid,
@@ -116,10 +104,6 @@ struct DbConnection {
provider_avatar: Option<String>,
}
// ---------------------------------------------------------------------------
// Password helpers
// ---------------------------------------------------------------------------
/// Hash and salt a plaintext password with Argon2.
pub fn hash_password(password: &str) -> Result<String> {
let salt = SaltString::generate(&mut OsRng);
@@ -139,10 +123,6 @@ pub fn verify_password(password: &str, hash: &str) -> bool {
.is_ok()
}
// ---------------------------------------------------------------------------
// Cookie / session helpers
// ---------------------------------------------------------------------------
/// Build the `siren_session` HttpOnly Secure cookie.
pub fn build_session_cookie(token: String) -> Cookie<'static> {
Cookie::build(("siren_session", token))
@@ -192,10 +172,6 @@ pub async fn create_session_and_cookie(
Ok((jar, ()))
}
// ---------------------------------------------------------------------------
// Helper: load full UserInfo for a given user_id
// ---------------------------------------------------------------------------
async fn load_user_info(user_id: Uuid) -> Result<UserInfo> {
let pool = data::pool();
@@ -232,10 +208,6 @@ async fn load_user_info(user_id: Uuid) -> Result<UserInfo> {
})
}
// ---------------------------------------------------------------------------
// Handlers
// ---------------------------------------------------------------------------
async fn register(
headers: HeaderMap,
jar: CookieJar,
@@ -245,12 +217,6 @@ async fn register(
if username.is_empty() || username.len() > 32 {
return Err(Error::new(422, "Username must be 132 characters".into()));
}
if payload.password.len() < 8 {
return Err(Error::new(
422,
"Password must be at least 8 characters".into(),
));
}
let pool = data::pool();
@@ -402,13 +368,6 @@ async fn change_password(
) -> Result<StatusCode> {
let session = session.ok_or_else(|| Error::from(StatusCode::UNAUTHORIZED))?;
if payload.new_password.len() < 8 {
return Err(Error::new(
422,
"New password must be at least 8 characters".into(),
));
}
let pool = data::pool();
let existing_hash: Option<String> =

View File

@@ -61,10 +61,6 @@ pub fn get_routes() -> Router<Arc<AppState>> {
.route("/maps/{id}/ws", get(ws_handler))
}
// ---------------------------------------------------------------------------
// Access helpers
// ---------------------------------------------------------------------------
/// Fetch the role of `user_id` on `map_id`, or `None` if no record exists.
async fn get_user_role(map_id: &str, user_id: Uuid) -> Result<Option<MapRole>> {
let pool = siren_core::data::pool();
@@ -120,10 +116,6 @@ async fn is_owner(map: &GridMap, session: &Option<Session>) -> bool {
.unwrap_or(false)
}
// ---------------------------------------------------------------------------
// Map CRUD
// ---------------------------------------------------------------------------
pub async fn list_maps(
SessionAuthorization(session): SessionAuthorization,
) -> Result<Json<Vec<ListedMap>>> {
@@ -287,10 +279,6 @@ pub async fn delete_map(
Ok(StatusCode::NO_CONTENT)
}
// ---------------------------------------------------------------------------
// Permission management
// ---------------------------------------------------------------------------
pub async fn list_permissions(
SessionAuthorization(session): SessionAuthorization,
Path(id): Path<String>,
@@ -429,10 +417,6 @@ pub async fn unfavorite_map(
Ok(StatusCode::NO_CONTENT)
}
// ---------------------------------------------------------------------------
// Access Requests
// ---------------------------------------------------------------------------
pub async fn create_access_request(
SessionAuthorization(session): SessionAuthorization,
Path(id): Path<String>,
@@ -572,10 +556,6 @@ pub async fn resolve_access_request(
Ok(StatusCode::NO_CONTENT)
}
// ---------------------------------------------------------------------------
// WebSocket handler
// ---------------------------------------------------------------------------
pub async fn ws_handler(
ws: WebSocketUpgrade,
State(state): State<Arc<AppState>>,

View File

@@ -1,11 +1,7 @@
use chrono::NaiveDateTime;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
// ---------------------------------------------------------------------------
// Map Role / Permission
// ---------------------------------------------------------------------------
#[derive(Serialize, Deserialize, sqlx::Type, Clone, Debug, PartialEq, Eq)]
#[sqlx(type_name = "text", rename_all = "lowercase")]
#[serde(rename_all = "lowercase")]
@@ -36,10 +32,6 @@ pub struct PermissionWithUser {
pub role: MapRole,
}
// ---------------------------------------------------------------------------
// Grid Map
// ---------------------------------------------------------------------------
/// Core map record as stored/returned by create, get, and update endpoints.
#[derive(Serialize, Deserialize, sqlx::FromRow, Clone, Debug)]
pub struct GridMap {
@@ -49,8 +41,8 @@ pub struct GridMap {
pub public_access: String,
pub owner_id: Uuid,
pub colors: Vec<String>,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
/// Extended map record returned by the list endpoint.
@@ -64,8 +56,8 @@ pub struct ListedMap {
pub owner_id: Uuid,
pub owner_username: String,
pub colors: Vec<String>,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
/// The authenticated caller's role on this map, or NULL if they only have it
/// via a favorite (no explicit permission).
pub user_role: Option<MapRole>,
@@ -98,10 +90,6 @@ pub struct UpdatePermissionPayload {
pub role: Option<MapRole>,
}
// ---------------------------------------------------------------------------
// Map Access Requests
// ---------------------------------------------------------------------------
/// An access-request row joined with the requesting user's username.
#[derive(Serialize, sqlx::FromRow, Clone, Debug)]
pub struct AccessRequestWithUser {
@@ -111,8 +99,8 @@ pub struct AccessRequestWithUser {
pub username: String,
pub requested_role: MapRole,
pub status: String,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Deserialize, Clone, Debug)]
@@ -126,10 +114,6 @@ pub struct ResolveAccessRequestPayload {
pub action: String,
}
// ---------------------------------------------------------------------------
// Grid Cell (no id column — composite PK in DB)
// ---------------------------------------------------------------------------
#[derive(Serialize, Deserialize, sqlx::FromRow, Clone, Debug)]
pub struct GridCell {
pub map_id: String,
@@ -146,10 +130,6 @@ pub struct CellPatch {
pub color: String,
}
// ---------------------------------------------------------------------------
// Grid Token
// ---------------------------------------------------------------------------
#[derive(Serialize, Deserialize, sqlx::FromRow, Clone, Debug)]
pub struct GridToken {
pub id: String,
@@ -160,10 +140,6 @@ pub struct GridToken {
pub color: String,
}
// ---------------------------------------------------------------------------
// Full map state (used on initial WS connect and REST GET)
// ---------------------------------------------------------------------------
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct MapState {
pub map: GridMap,
@@ -171,10 +147,6 @@ pub struct MapState {
pub tokens: Vec<GridToken>,
}
// ---------------------------------------------------------------------------
// WebSocket message types
// ---------------------------------------------------------------------------
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ClientMessage {

View File

@@ -16,16 +16,8 @@ pub struct EnvironmentConfiguration {
pub api_session_ttl: u64,
pub valkey_host: String,
pub valkey_port: u16,
pub minio_root_user: String,
pub minio_root_password: String,
pub minio_host: String,
pub minio_port: u16,
pub minio_port_internal: u16,
pub data_dir_path: Option<String>,
pub force_register: bool,
pub default_api_key: String,
pub default_server: Option<String>,
pub default_user: Option<String>,
pub force_command_register: bool,
}
impl EnvironmentConfiguration {
@@ -57,25 +49,11 @@ impl EnvironmentConfiguration {
.unwrap_or_else(|_| "6379".to_string())
.parse()
.unwrap_or(6379),
minio_root_user: env::var("MINIO_ROOT_USER")?,
minio_root_password: env::var("MINIO_ROOT_PASSWORD")?,
minio_host: env::var("MINIO_HOST").unwrap_or_else(|_| "localhost".to_string()),
minio_port: env::var("MINIO_PORT")
.unwrap_or_else(|_| "9000".to_string())
.parse()
.unwrap_or(9000),
minio_port_internal: env::var("MINIO_PORT_INTERNAL")
.unwrap_or_else(|_| "9001".to_string())
.parse()
.unwrap_or(9001),
data_dir_path: env::var("DATA_DIR_PATH").ok().filter(|s| !s.is_empty()),
force_register: env::var("FORCE_REGISTER")
force_command_register: env::var("FORCE_COMMAND_REGISTER")
.ok()
.map(|v| v.to_lowercase() == "true")
.unwrap_or(false),
default_api_key: env::var("DEFAULT_API_KEY").unwrap_or_default(),
default_server: env::var("DEFAULT_SERVER").ok().filter(|s| !s.is_empty()),
default_user: env::var("DEFAULT_USER").ok().filter(|s| !s.is_empty()),
})
}
}

View File

@@ -1,3 +0,0 @@
mod model;
pub use model::*;

View File

@@ -1,74 +0,0 @@
use crate::error::Result;
use serde::{Deserialize, Serialize};
const TABLE_NAME: &str = "messages";
#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageCache {
pub id: String,
pub guild_id: i64,
pub channel_id: i64,
pub author_id: i64,
pub created: i64,
pub model: String,
pub request: String,
pub response: String,
pub request_tags: Vec<String>,
pub response_tags: Vec<String>,
}
impl MessageCache {
pub async fn insert(&self) -> Result<()> {
let pool = crate::data::pool();
sqlx::query(&format!(
"INSERT INTO {} (
id,
guild_id,
channel_id,
author_id,
created,
model,
request,
response,
request_tags,
response_tags
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10
)",
TABLE_NAME
))
.bind(&self.id)
.bind(self.guild_id)
.bind(self.channel_id)
.bind(self.author_id)
.bind(self.created)
.bind(&self.model)
.bind(&self.request)
.bind(&self.response)
.bind(&self.request_tags)
.bind(&self.response_tags)
.execute(pool)
.await?;
Ok(())
}
pub async fn find(
guild_id: i64,
channel_id: i64,
author_id: i64,
limit: i64,
) -> Result<Vec<MessageCache>> {
let pool = crate::data::pool();
let messages = sqlx::query_as::<_, MessageCache>(&format!(
"SELECT * FROM {} WHERE guild_id = $1 AND channel_id = $2 AND author_id = $3 ORDER BY created ASC LIMIT $4",
TABLE_NAME
))
.bind(guild_id)
.bind(channel_id)
.bind(author_id)
.bind(limit)
.fetch_all(pool)
.await?;
Ok(messages)
}
}

View File

@@ -9,7 +9,6 @@ pub mod events;
mod executable_query;
pub mod guilds;
pub mod insert;
pub mod messages;
pub mod query;
pub mod update;
use crate::config::EnvironmentConfiguration;

View File

@@ -21,7 +21,7 @@ async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
let config = EnvironmentConfiguration::load()?;
siren_core::data::initialize(&config).await?;
let handler = BotHandler::new(config.force_register);
let handler = BotHandler::new(config.force_command_register);
let songbird = Songbird::serenity();
let intents: GatewayIntents = GatewayIntents::all();