124 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
/*
 | 
						|
 * asklyphe-auth-frontend main.rs
 | 
						|
 * - entrypoint for the asklyphe authentication frontend
 | 
						|
 *
 | 
						|
 * Copyright (C) 2025 Real Microsoft, LLC
 | 
						|
 *
 | 
						|
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
						|
*/
 | 
						|
 | 
						|
mod register;
 | 
						|
mod verify;
 | 
						|
mod login;
 | 
						|
 | 
						|
use std::{env, process};
 | 
						|
use std::collections::HashMap;
 | 
						|
use std::net::{SocketAddr, ToSocketAddrs};
 | 
						|
use std::ops::Deref;
 | 
						|
use std::sync::Arc;
 | 
						|
use std::sync::atomic::{AtomicU64, Ordering};
 | 
						|
use std::time::Duration;
 | 
						|
use argon2::{Argon2, PasswordHasher};
 | 
						|
use argon2::password_hash::rand_core::OsRng;
 | 
						|
use argon2::password_hash::SaltString;
 | 
						|
use askama::Template;
 | 
						|
use asklyphe_common::nats;
 | 
						|
use asklyphe_common::nats::authservice::{AuthServiceQuery, AuthServiceRequest, AuthServiceResponse, EmailError, PasswordError, RegisterError, RegisterRequest, RegisterResponse, UsernameError};
 | 
						|
use asklyphe_common::nats::comms;
 | 
						|
use asklyphe_common::nats::comms::ServiceResponse;
 | 
						|
use async_nats::jetstream;
 | 
						|
use axum::{Extension, Form, Router};
 | 
						|
use axum::extract::Query;
 | 
						|
use axum::response::IntoResponse;
 | 
						|
use axum::routing::get;
 | 
						|
use serde::Deserialize;
 | 
						|
use tokio::sync::Mutex;
 | 
						|
use tracing::error;
 | 
						|
use tracing_loki::url::Url;
 | 
						|
use tracing_subscriber::layer::SubscriberExt;
 | 
						|
use tracing_subscriber::util::SubscriberInitExt;
 | 
						|
use crate::login::{login_get, login_post};
 | 
						|
use crate::register::{register_get, register_post};
 | 
						|
use crate::verify::verify_get;
 | 
						|
 | 
						|
const VERSION: &str = env!("CARGO_PKG_VERSION");
 | 
						|
const GIT_COMMIT: &str = env!("GIT_COMMIT");
 | 
						|
const BUILT_ON: &str = env!("BUILT_ON");
 | 
						|
const YEAR: &str = env!("YEAR");
 | 
						|
 | 
						|
#[derive(Clone)]
 | 
						|
struct Opts {
 | 
						|
    bind_addr: SocketAddr,
 | 
						|
    nats_addr: SocketAddr,
 | 
						|
    nats_cert: String,
 | 
						|
    nats_key: String,
 | 
						|
    asklyphe_url: String,
 | 
						|
    loki_addr: Option<Url>,
 | 
						|
    datacenter_id: i64,
 | 
						|
}
 | 
						|
 | 
						|
#[tokio::main]
 | 
						|
async fn main() {
 | 
						|
    env_logger::init();
 | 
						|
    let opts = Opts {
 | 
						|
        bind_addr: env::var("BIND_ADDR").unwrap_or("0.0.0.0:5843".to_string()).parse().expect("Badly formed BIND_ADDR (Needs to be SocketAddr)"),
 | 
						|
        nats_addr: env::var("NATS_ADDR").unwrap_or("127.0.0.1:4222".to_string()).to_socket_addrs().expect("Badly formed NATS_ADDR (Needs to be SocketAddr)").nth(0).unwrap(),
 | 
						|
        nats_cert: env::var("NATS_CERT").expect("NATS_CERT needs to be set"),
 | 
						|
        nats_key: env::var("NATS_KEY").expect("NATS_KEY needs to be set"),
 | 
						|
        asklyphe_url: env::var("ASKLYPHE_URL").unwrap_or("https://asklyphe.com".to_string()),
 | 
						|
        loki_addr: match env::var("LOKI_ADDR") {
 | 
						|
            Ok(url) => {
 | 
						|
                Some(Url::parse(&url).expect("Badly formed LOKI_ADDR (Needs to be Url)"))
 | 
						|
            }
 | 
						|
            Err(_) => {
 | 
						|
                None
 | 
						|
            }
 | 
						|
        },
 | 
						|
        datacenter_id: env::var("DATACENTER_ID").unwrap_or("1".to_string()).parse().expect("Badly formed DATACENTER_ID (Need to be i64)"),
 | 
						|
    };
 | 
						|
 | 
						|
    //if opts.loki_addr.is_some() {
 | 
						|
    //    let (layer, task) = tracing_loki::builder()
 | 
						|
    //        .label("environment", "dev").unwrap()
 | 
						|
    //        .extra_field("pid", process::id().to_string()).unwrap()
 | 
						|
    //        .extra_field("run_id", snowflake_factory.generate().to_string()).unwrap()
 | 
						|
    //        .build_url(opts.loki_addr.clone().unwrap()).unwrap();
 | 
						|
 | 
						|
    //    // Register Loki layer
 | 
						|
    //    tracing_subscriber::registry()
 | 
						|
    //        .with(layer)
 | 
						|
    //        .init();
 | 
						|
 | 
						|
    //    // Spawn Loki background task
 | 
						|
    //    tokio::spawn(task);
 | 
						|
    //} else {
 | 
						|
    //    tracing_subscriber::fmt::init()
 | 
						|
    //}
 | 
						|
 | 
						|
    let nats = async_nats::ConnectOptions::new()
 | 
						|
        .add_client_certificate(opts.nats_cert.as_str().into(), opts.nats_key.as_str().into())
 | 
						|
        .connect(opts.nats_addr.to_string())
 | 
						|
        .await;
 | 
						|
    if let Err(e) = nats {
 | 
						|
        eprintln!("FATAL ERROR, COULDN'T CONNECT TO NATS: {}", e);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    let nats = nats.unwrap();
 | 
						|
    let nats = jetstream::new(nats);
 | 
						|
    let nats = Arc::new(Mutex::new(nats));
 | 
						|
 | 
						|
    let app = Router::new()
 | 
						|
        .route("/register", get(register_get).post(register_post))
 | 
						|
        .route("/login", get(login_get).post(login_post))
 | 
						|
        .route("/verify", get(verify_get))
 | 
						|
        .layer(Extension(nats.clone()))
 | 
						|
        .layer(Extension(opts.clone()));
 | 
						|
 | 
						|
    let listener = tokio::net::TcpListener::bind(opts.bind_addr).await.expect("Failed to get listener");
 | 
						|
    axum::serve(listener, app).await.expect("Failed to serve");
 | 
						|
}
 | 
						|
 |