Compare commits

...

4 Commits

Author SHA1 Message Date
Jason Rhinelander 26851becfd
Merge pull request #29 from jagerman/no-default-main
Don't create default rooms
2021-10-05 19:41:02 -03:00
Jason Rhinelander 734ee32897
Merge pull request #28 from jagerman/no-ghost-rooms
Check for room token in main table before opening db
2021-10-05 19:40:46 -03:00
Jason Rhinelander ecc6212f5d Don't create default rooms
This is obnoxious because it is *impossible* to get rid of the room
without it getting recreated at every restart.

Note: this breaks file server mode, but that's okay, the DB refactor
completely breaks it anyway, and current version will work fine for the
global file server.
2021-10-05 19:38:58 -03:00
Jason Rhinelander 56fda143fb Check for room token in main table before opening db
This was allowing old (deleted) room databases to persist and even be
recreated if clients were still polling them.  Worse, they would grow
forever because files and old tokens are only cleaned up for rooms
listed in the main db.
2021-09-29 23:57:30 -03:00
6 changed files with 51 additions and 40 deletions

4
Cargo.lock generated
View File

@ -1,7 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.14.1"
@ -1747,7 +1745,7 @@ dependencies = [
[[package]]
name = "session-open-group-server"
version = "0.1.8"
version = "0.1.10"
dependencies = [
"aes-gcm",
"base64",

View File

@ -1,7 +1,7 @@
[package]
name = "session-open-group-server"
version = "0.1.9"
authors = ["Niels Andriesse <niels@oxen.io>"]
version = "0.1.10"
authors = ["The Oxen Project <team@oxen.io>"]
edition = "2018"
description = "The Session open group server. Use this to run a custom open group."
license = "MIT"

View File

@ -746,7 +746,7 @@ pub async fn add_moderator_public(
body: models::ChangeModeratorRequestBody, auth_token: &str,
) -> Result<Response, Rejection> {
let room_id = storage::RoomId::new(&body.room_id).ok_or(Error::ValidationFailed)?;
let pool = storage::pool_by_room_id(&room_id);
let pool = storage::pool_by_room_id(&room_id)?;
let (has_authorization_level, _) =
has_authorization_level(auth_token, AuthorizationLevel::Moderator, &pool)?;
if !has_authorization_level {
@ -762,7 +762,7 @@ pub async fn add_moderator(
// Get a database connection
let pool = storage::pool_by_room_id(
&storage::RoomId::new(&body.room_id).ok_or(Error::ValidationFailed)?,
);
)?;
let conn = pool.get().map_err(|_| Error::DatabaseFailedInternally)?;
// Insert the moderator
let stmt = "INSERT INTO moderators (public_key) VALUES (?1)";
@ -784,7 +784,7 @@ pub async fn delete_moderator_public(
) -> Result<Response, Rejection> {
let pool = storage::pool_by_room_id(
&storage::RoomId::new(&body.room_id).ok_or(Error::ValidationFailed)?,
);
)?;
let (has_authorization_level, _) =
has_authorization_level(auth_token, AuthorizationLevel::Moderator, &pool)?;
if !has_authorization_level {
@ -800,7 +800,7 @@ pub async fn delete_moderator(
// Get a database connection
let pool = storage::pool_by_room_id(
&storage::RoomId::new(&body.room_id).ok_or(Error::ValidationFailed)?,
);
)?;
let conn = pool.get().map_err(|_| Error::DatabaseFailedInternally)?;
// Insert the moderator
let stmt = "DELETE FROM moderators WHERE public_key = (?1)";
@ -1034,7 +1034,7 @@ pub fn compact_poll(
// Get the database connection pool
let pool = storage::pool_by_room_id(
&storage::RoomId::new(&room_id).ok_or(Error::ValidationFailed)?,
);
)?;
// Get the new messages
let mut get_messages_query_params: HashMap<String, String> = HashMap::new();
if let Some(from_message_server_id) = from_message_server_id {
@ -1158,7 +1158,7 @@ pub async fn get_stats_for_room(
let lowerbound = upperbound - window;
let pool =
storage::pool_by_room_id(&storage::RoomId::new(&room_id).ok_or(Error::ValidationFailed)?);
storage::pool_by_room_id(&storage::RoomId::new(&room_id).ok_or(Error::ValidationFailed)?)?;
let conn = pool.get().map_err(|_| Error::DatabaseFailedInternally)?;
let raw_query_users =

View File

@ -68,8 +68,6 @@ async fn main() {
// Create required folders
fs::create_dir_all("./rooms").unwrap();
fs::create_dir_all("./files").unwrap();
// Create default rooms
create_default_rooms().await;
// Perform migration
storage::perform_migration();
// Set up pruning jobs
@ -170,13 +168,3 @@ fn get_url() -> String {
hex_public_key
);
}
async fn create_default_rooms() {
let info: Vec<(&str, &str)> = vec![("main", "Main")];
for info in info {
let id = info.0.to_string();
let name = info.1.to_string();
let room = models::Room { id, name };
handlers::create_room(room).await.unwrap();
}
}

View File

@ -409,9 +409,9 @@ async fn handle_delete_request(
fn get_pool_for_room(rpc_call: &RpcCall) -> Result<storage::DatabaseConnectionPool, Rejection> {
let room_id = get_room_id(&rpc_call).ok_or(Error::ValidationFailed)?;
return Ok(storage::pool_by_room_id(
return storage::pool_by_room_id(
&storage::RoomId::new(&room_id).ok_or(Error::ValidationFailed)?,
));
).map_err(|e| e.into());
}
fn get_auth_token(rpc_call: &RpcCall) -> Option<String> {

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use std::path::Path;
use std::sync::Mutex;
use log::{error, info};
use log::{error, warn, info};
use r2d2_sqlite::SqliteConnectionManager;
use rusqlite::params;
use rusqlite_migration::{Migrations, M};
@ -74,23 +74,41 @@ lazy_static::lazy_static! {
static ref POOLS: Mutex<HashMap<String, DatabaseConnectionPool>> = Mutex::new(HashMap::new());
}
pub fn pool_by_room_id(room_id: &RoomId) -> DatabaseConnectionPool {
pub fn pool_by_room_id(room_id: &RoomId) -> Result<DatabaseConnectionPool, Error> {
let mut pools = POOLS.lock().unwrap();
if let Some(pool) = pools.get(room_id.get_id()) {
return pool.clone();
return Ok(pool.clone());
} else {
let raw_path = format!("rooms/{}.db", room_id.get_id());
let path = Path::new(&raw_path);
let db_manager = r2d2_sqlite::SqliteConnectionManager::file(path);
let pool = r2d2::Pool::new(db_manager).unwrap();
pools.insert(room_id.get_id().to_string(), pool);
return pools[room_id.get_id()].clone();
let pool = &MAIN_POOL;
if let Ok(conn) = pool.get() {
if let Ok(count) = conn.query_row("SELECT COUNT(*) FROM main WHERE id = ?", params![room_id.get_id()],
|row| row.get::<_, i64>(0)) {
if count == 0 {
warn!("Cannot access room database: room {} does not exist", room_id.get_id());
return Err(Error::NoSuchRoom);
}
let raw_path = format!("rooms/{}.db", room_id.get_id());
let path = Path::new(&raw_path);
let db_manager = r2d2_sqlite::SqliteConnectionManager::file(path);
let pool = match r2d2::Pool::new(db_manager) {
Ok(p) => p,
Err(e) => {
error!("Unable to access {} database: {}", room_id.get_id(), e);
return Err(Error::DatabaseFailedInternally);
}
};
pools.insert(room_id.get_id().to_string(), pool);
return Ok(pools[room_id.get_id()].clone());
}
}
error!("Failed to query main database for room {} existence", room_id.get_id());
return Err(Error::DatabaseFailedInternally);
}
}
pub fn create_database_if_needed(room_id: &RoomId) {
let pool = pool_by_room_id(room_id);
let conn = pool.get().unwrap();
let conn = pool.unwrap().get().unwrap();
create_room_tables_if_needed(&conn);
}
@ -194,7 +212,10 @@ async fn prune_tokens() {
Err(_) => return,
};
for room in rooms {
let pool = pool_by_room_id(&room);
let pool = match pool_by_room_id(&room) {
Ok(p) => p,
Err(_) => return
};
// It's not catastrophic if we fail to prune the database for a given room
let conn = match pool.get() {
Ok(conn) => conn,
@ -217,7 +238,10 @@ async fn prune_pending_tokens() {
Err(_) => return,
};
for room in rooms {
let pool = pool_by_room_id(&room);
let pool = match pool_by_room_id(&room) {
Ok(p) => p,
Err(_) => return
};
// It's not catastrophic if we fail to prune the database for a given room
let conn = match pool.get() {
Ok(conn) => conn,
@ -330,8 +354,9 @@ pub async fn prune_files(file_expiration: i64) {
};
let futs = rooms.into_iter().map(|room| async move {
let pool = pool_by_room_id(&room);
prune_files_for_room(&pool, &room, file_expiration).await;
if let Ok(pool) = pool_by_room_id(&room) {
prune_files_for_room(&pool, &room, file_expiration).await;
}
});
futures::future::join_all(futs).await;
@ -356,7 +381,7 @@ pub fn perform_migration() {
for room in rooms {
create_database_if_needed(&room);
let pool = pool_by_room_id(&room);
let mut conn = pool.get().unwrap();
let mut conn = pool.unwrap().get().unwrap();
migrations.to_latest(&mut conn).unwrap();
}
}