feat(relays): layed the foundations for the relay runtime manager
This commit is contained in:
parent
4acdee0c18
commit
1d1f4896a4
|
@ -6,9 +6,10 @@ use log::info;
|
|||
mod endpoints;
|
||||
|
||||
pub async fn start(config: &Config, backend: Backend) -> Result<()> {
|
||||
let data = web::Data::new(backend);
|
||||
let server = HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::Data::new(backend.clone()))
|
||||
.app_data(data.clone())
|
||||
.service(endpoints::account::register)
|
||||
.service(endpoints::account::auth)
|
||||
.service(endpoints::account::invite::new)
|
||||
|
|
|
@ -16,3 +16,15 @@ pub struct UsersRow {
|
|||
pub password: String,
|
||||
pub permissions: u16,
|
||||
}
|
||||
|
||||
pub struct RelaysRow {
|
||||
pub id: String,
|
||||
pub secret: String,
|
||||
}
|
||||
|
||||
pub struct RelayIndexRow {
|
||||
pub public_id: String,
|
||||
pub public_key: [u8; 32],
|
||||
pub auth: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@ pub enum Error {
|
|||
#[error("Permission denied: {0}")]
|
||||
PermissionDenied(&'static str),
|
||||
|
||||
#[error("The given relay id cannot be mapped to a relay")]
|
||||
RelayNotFound,
|
||||
|
||||
#[error("The given token is expired")]
|
||||
TokenExpired,
|
||||
|
||||
|
@ -37,6 +40,7 @@ impl Into<HttpResponse> for Error {
|
|||
Error::AuthenticationFailure => HttpResponse::Unauthorized().json(body),
|
||||
Error::InvalidToken => HttpResponse::Unauthorized().json(body),
|
||||
Error::PermissionDenied(_) => HttpResponse::Forbidden().json(body),
|
||||
Error::RelayNotFound => HttpResponse::NotFound().json(body),
|
||||
Error::TokenExpired => HttpResponse::Gone().json(body),
|
||||
Error::UserNotFound => HttpResponse::NotFound().json(body),
|
||||
}
|
||||
|
|
|
@ -5,14 +5,17 @@ mod relay;
|
|||
mod tokens;
|
||||
mod user;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::{backend::relay::Relay, config::Config};
|
||||
use anyhow::Result;
|
||||
use log::info;
|
||||
use sqlx::MySqlPool;
|
||||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug)]
|
||||
pub struct Backend {
|
||||
pub pool: MySqlPool,
|
||||
pub relays: HashMap<Uuid, Relay>,
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
|
@ -59,6 +62,9 @@ impl Backend {
|
|||
|
||||
info!("Backend initialized");
|
||||
|
||||
Ok(Self { pool })
|
||||
Ok(Self {
|
||||
pool,
|
||||
relays: HashMap::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,37 @@
|
|||
use crate::backend::{error::Error, user::IntoUser, Backend};
|
||||
use crate::backend::{
|
||||
db_structures::{RelayIndexRow, RelaysRow},
|
||||
error::Error,
|
||||
user::IntoUser,
|
||||
Backend,
|
||||
};
|
||||
use anyhow::{bail, Result};
|
||||
use argon2::{
|
||||
password_hash::{rand_core::OsRng, PasswordHasher, SaltString},
|
||||
Argon2,
|
||||
};
|
||||
use rand::distributions::DistString;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct EncryptedMessage {
|
||||
sender: Uuid,
|
||||
body: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct UserIndex {
|
||||
public_key: [u8; 32],
|
||||
name: String,
|
||||
messages: VecDeque<EncryptedMessage>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Relay {
|
||||
user_index: HashMap<Uuid, UserIndex>,
|
||||
user_map: HashMap<Uuid, Uuid>,
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
/// Creates the structures for a new relay
|
||||
pub async fn create_relay(
|
||||
|
@ -38,7 +64,7 @@ impl Backend {
|
|||
sqlx::query(&format!(
|
||||
"CREATE TABLE RelayIndex_{} (
|
||||
public_id UUID NOT NULL PRIMARY KEY,
|
||||
public_key BLOB(4096) NOT NULL,
|
||||
public_key BINARY(32) NOT NULL,
|
||||
auth VARCHAR(128) NOT NULL,
|
||||
name VARCHAR(32)
|
||||
);",
|
||||
|
@ -49,4 +75,36 @@ impl Backend {
|
|||
|
||||
Ok(Ok((relay_id, secret)))
|
||||
}
|
||||
|
||||
pub async fn get_relay(&mut self, relay_id: Uuid) -> Result<Result<&Relay, Error>> {
|
||||
// can't use early return pattern, because of the borrow checker :/
|
||||
if self.relays.get(&relay_id).is_none() {
|
||||
match sqlx::query_as!(
|
||||
RelaysRow,
|
||||
r#"SELECT * FROM Relays WHERE id = ? LIMIT 1;"#,
|
||||
relay_id.as_bytes().as_slice()
|
||||
)
|
||||
.fetch_one(&self.pool)
|
||||
.await
|
||||
{
|
||||
Err(sqlx::Error::RowNotFound) => return Ok(Err(Error::RelayNotFound)),
|
||||
Err(e) => return Err(e.into()),
|
||||
Ok(_) => {
|
||||
// the hashmaps will be filled, as soon, as clients subscribe to the relay
|
||||
let relay = Relay {
|
||||
user_index: HashMap::new(),
|
||||
user_map: HashMap::new(),
|
||||
};
|
||||
|
||||
self.relays.insert(relay_id, relay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(relay) = self.relays.get(&relay_id) {
|
||||
Ok(Ok(relay))
|
||||
} else {
|
||||
bail!("!!! This should never happen !!! relay not found in runtime manager, even tho it was there before.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue