feat: got sqlx working
This commit is contained in:
parent
6e99dc3d70
commit
8695685eb3
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@
|
|||||||
zig-out
|
zig-out
|
||||||
.zig-cache
|
.zig-cache
|
||||||
freebsd.txt
|
freebsd.txt
|
||||||
|
/sparse-server/db.sqlite*
|
||||||
|
|||||||
746
Cargo.lock
generated
746
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
31
flake.nix
31
flake.nix
@ -71,8 +71,9 @@
|
|||||||
dart-sass
|
dart-sass
|
||||||
binaryen
|
binaryen
|
||||||
];
|
];
|
||||||
freebsd = [ pkgsCross.x86_64-freebsd.buildPackages.clang ];
|
freebsd = buildTools.linux
|
||||||
windows = [
|
++ [ pkgsCross.x86_64-freebsd.buildPackages.clang ];
|
||||||
|
windows = buildTools.linux ++ [
|
||||||
pkgsCross.mingwW64.stdenv.cc
|
pkgsCross.mingwW64.stdenv.cc
|
||||||
pkgsCross.mingwW64.windows.pthreads
|
pkgsCross.mingwW64.windows.pthreads
|
||||||
];
|
];
|
||||||
@ -88,6 +89,9 @@
|
|||||||
# Cargo lint tools
|
# Cargo lint tools
|
||||||
taplo
|
taplo
|
||||||
cargo-deny
|
cargo-deny
|
||||||
|
|
||||||
|
# Web server tools
|
||||||
|
sqlx-cli
|
||||||
];
|
];
|
||||||
|
|
||||||
craneLib = (crane.mkLib pkgs).overrideToolchain (p:
|
craneLib = (crane.mkLib pkgs).overrideToolchain (p:
|
||||||
@ -143,7 +147,7 @@
|
|||||||
default = craneLib.devShell (buildEnvironment // {
|
default = craneLib.devShell (buildEnvironment // {
|
||||||
name = "sparse-default";
|
name = "sparse-default";
|
||||||
|
|
||||||
packages = buildTools.all ++ devShellTools
|
packages = buildTools.linux ++ devShellTools
|
||||||
++ [ setup-zig-freebsd setup-dev-environment ];
|
++ [ setup-zig-freebsd setup-dev-environment ];
|
||||||
|
|
||||||
# Added to make development easier
|
# Added to make development easier
|
||||||
@ -157,6 +161,27 @@
|
|||||||
"../../target/x86_64-unknown-freebsd/debug/sparse-unix-beacon";
|
"../../target/x86_64-unknown-freebsd/debug/sparse-unix-beacon";
|
||||||
SPARSE_BEACON_WINDOWS =
|
SPARSE_BEACON_WINDOWS =
|
||||||
"../../target/x86_64-pc-windows-gnu/debug/sparse-windows-beacon.exe";
|
"../../target/x86_64-pc-windows-gnu/debug/sparse-windows-beacon.exe";
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
export DATABASE_URL="sqlite://$(${pkgs.git}/bin/git rev-parse --show-toplevel)/sparse-server/db.sqlite"
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
|
||||||
|
windows = craneLib.devShell (buildEnvironment // {
|
||||||
|
name = "sparse-default";
|
||||||
|
|
||||||
|
packages = buildTools.windows ++ devShellTools
|
||||||
|
++ [ setup-zig-freebsd setup-dev-environment ];
|
||||||
|
|
||||||
|
# No point adding above environment variables, since web server can't
|
||||||
|
# be built with windows tools available
|
||||||
|
});
|
||||||
|
|
||||||
|
freebsd = craneLib.devShell (buildEnvironment // {
|
||||||
|
name = "sparse-default";
|
||||||
|
|
||||||
|
packages = buildTools.freebsd ++ devShellTools
|
||||||
|
++ [ setup-zig-freebsd setup-dev-environment ];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
26
sparse-server/.sqlx/query-86f197e514e8d55b95a71ab52b5901e939ee2c9e832ed1fae2661ad770d3ad60.json
generated
Normal file
26
sparse-server/.sqlx/query-86f197e514e8d55b95a71ab52b5901e939ee2c9e832ed1fae2661ad770d3ad60.json
generated
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "SELECT user_id, user_name FROM users;",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "user_id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "user_name",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "86f197e514e8d55b95a71ab52b5901e939ee2c9e832ed1fae2661ad770d3ad60"
|
||||||
|
}
|
||||||
@ -28,8 +28,14 @@ tokio-stream = { version = "0.1", optional = true }
|
|||||||
futures-util = { version = "0.3", optional = true }
|
futures-util = { version = "0.3", optional = true }
|
||||||
tracing = { version = "0.1", optional = true }
|
tracing = { version = "0.1", optional = true }
|
||||||
web-sys = { version = "0.3", features = ["WebSocket"] }
|
web-sys = { version = "0.3", features = ["WebSocket"] }
|
||||||
leptos-use = { version = "0.15", default_features = false, features = ["use_websocket"] }
|
leptos-use = { version = "0.15", default-features = false, features = ["use_websocket"] }
|
||||||
codee = "0.2"
|
codee = "0.2"
|
||||||
|
sqlx = { version = "0.8", default-features = false, features = ["chrono", "macros", "migrate", "runtime-tokio", "sqlite", "sqlx-sqlite"], optional = true }
|
||||||
|
chrono = "0.4"
|
||||||
|
rpassword = { version = "7.3", optional = true }
|
||||||
|
pbkdf2 = { version = "0.12", features = ["simple", "sha2"], optional = true }
|
||||||
|
sha2 = { version = "0.10", optional = true }
|
||||||
|
hex = { version = "0.4", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
hydrate = ["leptos/hydrate"]
|
hydrate = ["leptos/hydrate"]
|
||||||
@ -45,6 +51,11 @@ ssr = [
|
|||||||
"dep:tokio-stream",
|
"dep:tokio-stream",
|
||||||
"dep:futures-util",
|
"dep:futures-util",
|
||||||
"dep:tracing",
|
"dep:tracing",
|
||||||
|
"dep:sqlx",
|
||||||
|
"dep:rpassword",
|
||||||
|
"dep:pbkdf2",
|
||||||
|
"dep:sha2",
|
||||||
|
"dep:hex",
|
||||||
"leptos/ssr",
|
"leptos/ssr",
|
||||||
"leptos_meta/ssr",
|
"leptos_meta/ssr",
|
||||||
"leptos_router/ssr",
|
"leptos_router/ssr",
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
// generated by `sqlx migrate build-script`
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// trigger recompilation when a new migration is added
|
||||||
include!("../build_common.rs");
|
include!("../build_common.rs");
|
||||||
|
println!("cargo:rerun-if-changed=migrations");
|
||||||
}
|
}
|
||||||
|
|||||||
16
sparse-server/migrations/20250124053720_users.sql
Normal file
16
sparse-server/migrations/20250124053720_users.sql
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
-- Add migration script here
|
||||||
|
CREATE TABLE users (
|
||||||
|
user_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
user_name varchar(255) NOT NULL,
|
||||||
|
password_salt char(64) NOT NULL,
|
||||||
|
password_hash char(64) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE sessions (
|
||||||
|
session_id char(64) NOT NULL,
|
||||||
|
user_id int NOT NULL,
|
||||||
|
expires int NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (session_id),
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users
|
||||||
|
);
|
||||||
@ -53,6 +53,7 @@ pub fn App() -> impl IntoView {
|
|||||||
<main>
|
<main>
|
||||||
<Routes fallback=|| "Page not found.".into_view()>
|
<Routes fallback=|| "Page not found.".into_view()>
|
||||||
<Route path=StaticSegment("") view=HomePage/>
|
<Route path=StaticSegment("") view=HomePage/>
|
||||||
|
<Route path=StaticSegment("/users") view=crate::users::UserView/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</main>
|
</main>
|
||||||
</Router>
|
</Router>
|
||||||
|
|||||||
@ -1,9 +1,22 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
pub mod user;
|
||||||
|
|
||||||
#[derive(StructOpt, Debug, Clone)]
|
#[derive(StructOpt, Debug, Clone)]
|
||||||
#[structopt(name = "sparse-server")]
|
#[structopt(name = "sparse-server")]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
|
/// The location of the database to use. If not present,
|
||||||
|
/// sparse will read the DATABASE_URL environment variable
|
||||||
|
#[structopt(short = "d")]
|
||||||
|
pub db_location: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// During the startup of the program, sparse will produce an error
|
||||||
|
/// if the database doesn't exist. Use this flag to instead create a new
|
||||||
|
/// database
|
||||||
|
#[structopt(short = "i")]
|
||||||
|
pub init_ok: bool,
|
||||||
|
|
||||||
#[structopt(subcommand)]
|
#[structopt(subcommand)]
|
||||||
pub command: Option<Command>,
|
pub command: Option<Command>,
|
||||||
}
|
}
|
||||||
@ -11,6 +24,34 @@ pub struct Options {
|
|||||||
#[derive(StructOpt, Debug, Clone)]
|
#[derive(StructOpt, Debug, Clone)]
|
||||||
#[structopt()]
|
#[structopt()]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
|
/// Run the web and API server
|
||||||
Serve {},
|
Serve {},
|
||||||
Init {},
|
|
||||||
|
/// Extract the public key and print it to standard out
|
||||||
|
ExtractPubKey {},
|
||||||
|
|
||||||
|
/// Perform user management
|
||||||
|
User {
|
||||||
|
#[structopt(subcommand)]
|
||||||
|
command: UserCommand,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(StructOpt, Debug, Clone)]
|
||||||
|
#[structopt()]
|
||||||
|
pub enum UserCommand {
|
||||||
|
/// List available users to sign in as
|
||||||
|
List {},
|
||||||
|
|
||||||
|
/// Create a new user
|
||||||
|
Create {
|
||||||
|
#[structopt(short = "n")]
|
||||||
|
user_name: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Reset the password for a user who forgot their password
|
||||||
|
ResetPassword {
|
||||||
|
#[structopt(short = "I")]
|
||||||
|
user_id: i16,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
75
sparse-server/src/cli/user.rs
Normal file
75
sparse-server/src/cli/user.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use std::process::ExitCode;
|
||||||
|
|
||||||
|
use futures_util::StreamExt;
|
||||||
|
use sqlx::{Database, query, sqlite::SqlitePool};
|
||||||
|
|
||||||
|
use crate::cli::UserCommand as UC;
|
||||||
|
|
||||||
|
pub async fn handle_user_command(user_command: UC, db: SqlitePool) -> anyhow::Result<ExitCode> {
|
||||||
|
match user_command {
|
||||||
|
UC::List {} => list_users(db).await,
|
||||||
|
UC::Create { user_name } => create_user(db, user_name).await,
|
||||||
|
UC::ResetPassword { user_id } => reset_password(&db, user_id).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_users(db: SqlitePool) -> anyhow::Result<ExitCode> {
|
||||||
|
println!("\n\nListing users:");
|
||||||
|
|
||||||
|
let mut results = query!("SELECT user_id, user_name FROM users;").fetch(&db);
|
||||||
|
while let Some(Ok(user)) = results.next().await {
|
||||||
|
println!("\t{:?}: {}", user.user_id, user.user_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ExitCode::SUCCESS)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_user(db: SqlitePool, name: String) -> anyhow::Result<ExitCode> {
|
||||||
|
let mut tx = db.begin().await?;
|
||||||
|
|
||||||
|
let previous_user_check = sqlx::query_scalar!(
|
||||||
|
"SELECT COUNT(*) FROM users WHERE user_name = ?",
|
||||||
|
name
|
||||||
|
)
|
||||||
|
.fetch_one(&mut *tx)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if previous_user_check > 0 {
|
||||||
|
eprintln!("Error! User already exists!");
|
||||||
|
return Ok(ExitCode::FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_id = query!(
|
||||||
|
r#"INSERT INTO users (user_name, password_salt, password_hash) VALUES (?, "", "")"#,
|
||||||
|
name
|
||||||
|
)
|
||||||
|
.execute(&mut *tx)
|
||||||
|
.await?
|
||||||
|
.last_insert_rowid();
|
||||||
|
|
||||||
|
reset_password(&mut *tx, new_id as i16).await?;
|
||||||
|
|
||||||
|
tx.commit().await?;
|
||||||
|
|
||||||
|
println!("User successfully created!");
|
||||||
|
|
||||||
|
Ok(ExitCode::SUCCESS)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn reset_password<'a, E>(db: E, id: i16) -> anyhow::Result<ExitCode>
|
||||||
|
where
|
||||||
|
E: sqlx::Executor<'a, Database = sqlx::Sqlite>
|
||||||
|
{
|
||||||
|
let password1 = rpassword::prompt_password("Enter new password: ")?;
|
||||||
|
let password2 = rpassword::prompt_password("Enter password again: ")?;
|
||||||
|
|
||||||
|
if password1 != password2 {
|
||||||
|
Err(anyhow::anyhow!("Passwords do not match!"))?
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::db::user::reset_password(db, id, password1).await?;
|
||||||
|
|
||||||
|
println!("Password set successfully!");
|
||||||
|
|
||||||
|
Ok(ExitCode::SUCCESS)
|
||||||
|
}
|
||||||
@ -1,2 +1,15 @@
|
|||||||
mod beacons;
|
#[cfg(feature = "ssr")]
|
||||||
mod users;
|
pub mod user;
|
||||||
|
|
||||||
|
pub struct User {
|
||||||
|
pub user_id: i16,
|
||||||
|
pub user_name: String,
|
||||||
|
pub password_salt: String,
|
||||||
|
pub password_hash: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Sessions {
|
||||||
|
pub session_id: String,
|
||||||
|
pub user_id: i16,
|
||||||
|
pub expires: chrono::DateTime<chrono::offset::Local>,
|
||||||
|
}
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
|
|
||||||
35
sparse-server/src/db/user.rs
Normal file
35
sparse-server/src/db/user.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use sqlx::{sqlite::SqlitePool, Database};
|
||||||
|
use pbkdf2::{pbkdf2_hmac_array, password_hash::{rand_core::OsRng, SaltString}};
|
||||||
|
use sha2::Sha256;
|
||||||
|
|
||||||
|
const PASSWORD_ITERATIONS: u32 = 100_000;
|
||||||
|
|
||||||
|
pub async fn reset_password<'a, E>(pool: E, id: i16, password: String) -> anyhow::Result<()>
|
||||||
|
where
|
||||||
|
E: sqlx::Executor<'a, Database = sqlx::Sqlite>
|
||||||
|
{
|
||||||
|
let salt = SaltString::generate(&mut OsRng);
|
||||||
|
|
||||||
|
let key = pbkdf2_hmac_array::<Sha256, 20>(
|
||||||
|
password.as_bytes(),
|
||||||
|
salt.as_str().as_bytes(),
|
||||||
|
PASSWORD_ITERATIONS
|
||||||
|
);
|
||||||
|
|
||||||
|
let salt_string = hex::encode(salt.as_str().as_bytes());
|
||||||
|
let password_string = hex::encode(&key[..]);
|
||||||
|
|
||||||
|
tracing::debug!("New password hash: {password_string}");
|
||||||
|
tracing::debug!("New password salt: {salt_string}");
|
||||||
|
|
||||||
|
sqlx::query!(
|
||||||
|
"UPDATE users SET password_hash = ?, password_salt = ? WHERE user_id = ?",
|
||||||
|
password_string,
|
||||||
|
salt_string,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
.execute(pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
|
|
||||||
@ -1,5 +1,7 @@
|
|||||||
pub mod app;
|
pub mod app;
|
||||||
|
|
||||||
|
pub mod users;
|
||||||
|
|
||||||
#[cfg(feature = "hydrate")]
|
#[cfg(feature = "hydrate")]
|
||||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||||
pub fn hydrate() {
|
pub fn hydrate() {
|
||||||
|
|||||||
@ -15,28 +15,82 @@ mod cli;
|
|||||||
mod webserver;
|
mod webserver;
|
||||||
|
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
mod db;
|
pub mod users;
|
||||||
|
|
||||||
|
pub mod db;
|
||||||
|
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<std::process::ExitCode> {
|
||||||
|
use std::{path::PathBuf, process::ExitCode, str::FromStr};
|
||||||
|
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
use sqlx::sqlite::{SqlitePool, SqliteConnectOptions};
|
||||||
|
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(
|
||||||
|
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||||
|
.unwrap_or_else(|_| format!("{}=debug", env!("CARGO_CRATE_NAME")).into()),
|
||||||
|
)
|
||||||
|
.with(tracing_subscriber::fmt::layer())
|
||||||
|
.init();
|
||||||
|
|
||||||
let options = cli::Options::from_args();
|
let options = cli::Options::from_args();
|
||||||
|
|
||||||
|
let db_location = options.db_location.clone()
|
||||||
|
.or(std::env::var("DATABASE_URL")
|
||||||
|
.map(|p| p.replace("sqlite://", ""))
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.ok())
|
||||||
|
.unwrap_or(PathBuf::from("./db.sqlite"));
|
||||||
|
|
||||||
|
tracing::info!("Using database {}", db_location.display());
|
||||||
|
|
||||||
|
let db_exists = std::fs::metadata(&db_location);
|
||||||
|
|
||||||
|
let run_init = if let Err(e) = db_exists {
|
||||||
|
if !options.init_ok {
|
||||||
|
tracing::error!("Database doesn't exist, and initialization not allowed!");
|
||||||
|
tracing::error!("{:?}", e);
|
||||||
|
return Ok(ExitCode::FAILURE)
|
||||||
|
}
|
||||||
|
|
||||||
|
tracing::info!("Database doesn't exist, readying initialization");
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
let pool = SqlitePool::connect_with(
|
||||||
|
SqliteConnectOptions::from_str(&format!("sqlite://{}", db_location.to_string_lossy()))?
|
||||||
|
.create_if_missing(options.init_ok)
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
tracing::info!("Running database migrations...");
|
||||||
|
|
||||||
|
sqlx::migrate!()
|
||||||
|
.run(&pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
tracing::info!("Done running database migrations!");
|
||||||
|
|
||||||
match options.command.clone() {
|
match options.command.clone() {
|
||||||
Some(cli::Command::Serve { }) => {
|
Some(cli::Command::Serve { }) => {
|
||||||
webserver::serve_web(options).await?;
|
tracing::info!("Performing requested action, acting as web server");
|
||||||
|
webserver::serve_web(options, pool).await
|
||||||
}
|
}
|
||||||
Some(cli::Command::Init { }) => {
|
Some(cli::Command::ExtractPubKey { }) => {
|
||||||
|
Ok(ExitCode::SUCCESS)
|
||||||
|
}
|
||||||
|
Some(cli::Command::User { command }) => {
|
||||||
|
cli::user::handle_user_command(command, pool).await
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
webserver::serve_web(options).await?;
|
tracing::info!("Performing default action of acting as web server");
|
||||||
|
webserver::serve_web(options, pool).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "ssr"))]
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
|||||||
8
sparse-server/src/users.rs
Normal file
8
sparse-server/src/users.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn UserView() -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<p>"User view"</p>
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,13 @@
|
|||||||
|
use std::process::ExitCode;
|
||||||
|
|
||||||
|
use sqlx::sqlite::SqlitePool;
|
||||||
|
use axum::Router;
|
||||||
|
use leptos::logging::log;
|
||||||
|
use leptos::prelude::*;
|
||||||
|
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||||
|
use sparse_server::app::*;
|
||||||
|
|
||||||
|
|
||||||
pub async fn websocket(ws: axum::extract::ws::WebSocketUpgrade) -> axum::response::Response {
|
pub async fn websocket(ws: axum::extract::ws::WebSocketUpgrade) -> axum::response::Response {
|
||||||
ws.on_upgrade(handle_websocket)
|
ws.on_upgrade(handle_websocket)
|
||||||
}
|
}
|
||||||
@ -32,22 +42,7 @@ async fn handle_websocket(mut socket: axum::extract::ws::WebSocket) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn serve_web(options: crate::cli::Options) -> anyhow::Result<()> {
|
pub async fn serve_web(options: crate::cli::Options, db: SqlitePool) -> anyhow::Result<ExitCode> {
|
||||||
use axum::Router;
|
|
||||||
use leptos::logging::log;
|
|
||||||
use leptos::prelude::*;
|
|
||||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
|
||||||
use sparse_server::app::*;
|
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
|
||||||
|
|
||||||
tracing_subscriber::registry()
|
|
||||||
.with(
|
|
||||||
tracing_subscriber::EnvFilter::try_from_default_env()
|
|
||||||
.unwrap_or_else(|_| format!("{}=debug", env!("CARGO_CRATE_NAME")).into()),
|
|
||||||
)
|
|
||||||
.with(tracing_subscriber::fmt::layer())
|
|
||||||
.init();
|
|
||||||
|
|
||||||
let conf = get_configuration(None).unwrap();
|
let conf = get_configuration(None).unwrap();
|
||||||
let addr = conf.leptos_options.site_addr;
|
let addr = conf.leptos_options.site_addr;
|
||||||
let leptos_options = conf.leptos_options;
|
let leptos_options = conf.leptos_options;
|
||||||
@ -69,5 +64,5 @@ pub async fn serve_web(options: crate::cli::Options) -> anyhow::Result<()> {
|
|||||||
let listener = tokio::net::TcpListener::bind(&addr).await?;
|
let listener = tokio::net::TcpListener::bind(&addr).await?;
|
||||||
axum::serve(listener, app.into_make_service()).await?;
|
axum::serve(listener, app.into_make_service()).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(ExitCode::SUCCESS)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,9 @@ typedef struct Parameters {
|
|||||||
unsigned short privkey_size;
|
unsigned short privkey_size;
|
||||||
unsigned short privkey_cert_size;
|
unsigned short privkey_cert_size;
|
||||||
unsigned short beacon_name_length;
|
unsigned short beacon_name_length;
|
||||||
|
unsigned short domain_name_length;
|
||||||
char pubkey_cert[1024];
|
char pubkey_cert[1024];
|
||||||
char beacon_identifier[64];
|
char beacon_identifier[64];
|
||||||
char beacon_name[128];
|
char beacon_name[128];
|
||||||
|
char domain_name[128];
|
||||||
} Parameters_t;
|
} Parameters_t;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user