feat: add environment configuration for database and authentication, update router setup
This commit is contained in:
@@ -3,3 +3,5 @@ PORT=3000
|
||||
DATABASE_URL="sqlite://dev.db"
|
||||
# DATABASE_URL="postgresql://postgres:postgres@localhost/clean-axum"
|
||||
PREFORK=1
|
||||
AUTH_SECRET=your_secret_key_here
|
||||
BASE_URL=http://localhost:3000
|
1
thoughts-backend/.gitignore
vendored
1
thoughts-backend/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
/target
|
||||
.env
|
@@ -25,9 +25,8 @@ pub async fn federate_thought(
|
||||
return;
|
||||
}
|
||||
|
||||
let base_url = "http://localhost:3000"; // Replace in production
|
||||
let thought_url = format!("{}/thoughts/{}", base_url, thought.id);
|
||||
let author_url = format!("{}/users/{}", base_url, author.username);
|
||||
let thought_url = format!("{}/thoughts/{}", &state.base_url, thought.id);
|
||||
let author_url = format!("{}/users/{}", &state.base_url, author.username);
|
||||
|
||||
// Construct the "Create" activity containing the "Note" object
|
||||
let activity = json!({
|
||||
@@ -59,7 +58,7 @@ pub async fn federate_thought(
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
for follower in followers {
|
||||
let inbox_url = format!("{}/users/{}/inbox", base_url, follower.username);
|
||||
let inbox_url = format!("{}/users/{}/inbox", &state.base_url, follower.username);
|
||||
tracing::info!("Federating post {} to {}", thought.id, inbox_url);
|
||||
|
||||
let res = client.post(&inbox_url).json(&activity).send().await;
|
||||
|
@@ -9,8 +9,11 @@ use app::state::AppState;
|
||||
use crate::routers::create_router;
|
||||
|
||||
// TODO: middleware, logging, authentication
|
||||
pub fn setup_router(conn: DatabaseConnection) -> Router {
|
||||
create_router(AppState { conn })
|
||||
pub fn setup_router(conn: DatabaseConnection, config: &Config) -> Router {
|
||||
create_router(AppState {
|
||||
conn,
|
||||
base_url: config.base_url.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn setup_config() -> Config {
|
||||
|
@@ -220,8 +220,7 @@ async fn get_user_by_param(
|
||||
// This is the logic from `user_actor_get`.
|
||||
match get_user_by_username(&state.conn, &username).await {
|
||||
Ok(Some(user)) => {
|
||||
let base_url = "http://localhost:3000";
|
||||
let user_url = format!("{}/users/{}", base_url, user.username);
|
||||
let user_url = format!("{}/users/{}", &state.base_url, user.username);
|
||||
let actor = json!({
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
@@ -272,13 +271,12 @@ async fn user_outbox_get(
|
||||
let thoughts = get_thoughts_by_user(&state.conn, user.id).await?;
|
||||
|
||||
// Format the outbox as an ActivityPub OrderedCollection
|
||||
let base_url = "http://localhost:3000";
|
||||
let outbox_url = format!("{}/users/{}/outbox", base_url, username);
|
||||
let outbox_url = format!("{}/users/{}/outbox", &state.base_url, username);
|
||||
let items: Vec<Value> = thoughts
|
||||
.into_iter()
|
||||
.map(|thought| {
|
||||
let thought_url = format!("{}/thoughts/{}", base_url, thought.id);
|
||||
let author_url = format!("{}/users/{}", base_url, thought.author_username);
|
||||
let thought_url = format!("{}/thoughts/{}", &state.base_url, thought.id);
|
||||
let author_url = format!("{}/users/{}", &state.base_url, thought.author_username);
|
||||
json!({
|
||||
"id": format!("{}/activity", thought_url),
|
||||
"type": "Create",
|
||||
|
@@ -45,8 +45,7 @@ pub async fn webfinger(
|
||||
_ => return Err((axum::http::StatusCode::NOT_FOUND, "User not found")),
|
||||
};
|
||||
|
||||
let base_url = "http://localhost:3000";
|
||||
let user_url = Url::parse(&format!("{}/users/{}", base_url, user.username)).unwrap();
|
||||
let user_url = Url::parse(&format!("{}/users/{}", &state.base_url, user.username)).unwrap();
|
||||
|
||||
let response = WebFingerResponse {
|
||||
subject: query.resource,
|
||||
|
@@ -4,6 +4,7 @@ pub struct Config {
|
||||
pub port: u32,
|
||||
pub prefork: bool,
|
||||
pub auth_secret: String,
|
||||
pub base_url: String,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -16,7 +17,8 @@ impl Config {
|
||||
.parse()
|
||||
.expect("PORT is not a number"),
|
||||
prefork: std::env::var("PREFORK").is_ok_and(|v| v == "1"),
|
||||
auth_secret: std::env::var("AUTH_SECRET").unwrap_or_else(|_| "secret".into()),
|
||||
auth_secret: std::env::var("AUTH_SECRET").expect("AUTH_SECRET is not set in .env file"),
|
||||
base_url: std::env::var("BASE_URL").expect("BASE_URL is not set in .env file"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,4 +3,5 @@ use sea_orm::DatabaseConnection;
|
||||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
pub conn: DatabaseConnection,
|
||||
pub base_url: String,
|
||||
}
|
||||
|
@@ -11,7 +11,9 @@ async fn worker(child_num: u32, db_url: &str, prefork: bool, listener: std::net:
|
||||
migrate(&conn).await.expect("Migration failed!");
|
||||
}
|
||||
|
||||
let router = setup_router(conn).attach_doc();
|
||||
let config = setup_config();
|
||||
|
||||
let router = setup_router(conn, &config).attach_doc();
|
||||
|
||||
let listener = tokio::net::TcpListener::from_std(listener).expect("bind to port");
|
||||
axum::serve(listener, router).await.expect("start server");
|
||||
|
@@ -13,10 +13,17 @@ pub struct TestApp {
|
||||
}
|
||||
|
||||
pub async fn setup() -> TestApp {
|
||||
std::env::set_var("DATABASE_URL", "sqlite::memory:");
|
||||
std::env::set_var("AUTH_SECRET", "test_secret");
|
||||
std::env::set_var("BASE_URL", "http://localhost:3000");
|
||||
std::env::set_var("HOST", "localhost");
|
||||
std::env::set_var("PORT", "3000");
|
||||
std::env::set_var("LOG_LEVEL", "debug");
|
||||
|
||||
let db = setup_test_db("sqlite::memory:")
|
||||
.await
|
||||
.expect("Failed to set up test db");
|
||||
let router = setup_router(db.clone());
|
||||
let router = setup_router(db.clone(), &app::config::Config::from_env());
|
||||
TestApp { router, db }
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user