etwin_cli 0.12.5

Command Line Interface for Eternaltwin
Documentation
use clap::Parser;
use etwin_auth_store::mem::MemAuthStore;
use etwin_core::auth::AuthStore;
use etwin_core::clock::{Clock, VirtualClock};
use etwin_core::core::Instant;
use etwin_core::dinoparc::{DinoparcClient, DinoparcStore};
use etwin_core::email::{EmailFormatter, Mailer};
use etwin_core::forum::ForumStore;
use etwin_core::hammerfest::{HammerfestClient, HammerfestStore};
use etwin_core::link::LinkStore;
use etwin_core::oauth::OauthProviderStore;
use etwin_core::password::PasswordService;
use etwin_core::token::TokenStore;
use etwin_core::twinoid::{TwinoidClient, TwinoidStore};
use etwin_core::types::AnyError;
use etwin_core::user::UserStore;
use etwin_core::uuid::{Uuid4Generator, UuidGenerator};
use etwin_dinoparc_client::http::{HttpDinoparcClient, HttpDinoparcClientEvent};
use etwin_dinoparc_store::mem::MemDinoparcStore;
use etwin_email_formatter::json::JsonEmailFormatter;
use etwin_forum_store::mem::MemForumStore;
use etwin_hammerfest_client::HttpHammerfestClient;
use etwin_hammerfest_store::mem::MemHammerfestStore;
use etwin_link_store::mem::MemLinkStore;
use etwin_log::{Logger, NoopLogger};
use etwin_mailer::mem::MemMailer;
use etwin_oauth_client::mem::MemRfcOauthClient;
use etwin_oauth_client::RfcOauthClient;
use etwin_oauth_provider_store::mem::MemOauthProviderStore;
use etwin_password::scrypt::ScryptPasswordService;
use etwin_rest::{DevApi, RouterApi};
use etwin_services::auth::AuthService;
use etwin_services::dinoparc::DinoparcService;
use etwin_services::forum::ForumService;
use etwin_services::hammerfest::HammerfestService;
use etwin_services::oauth::OauthService;
use etwin_services::twinoid::TwinoidService;
use etwin_services::user::UserService;
use etwin_token_store::mem::MemTokenStore;
use etwin_twinoid_client::http::HttpTwinoidClient;
use etwin_twinoid_store::mem::MemTwinoidStore;
use etwin_user_store::mem::MemUserStore;
use std::sync::Arc;

/// Arguments to the `rest` task.
#[derive(Debug, Parser)]
pub struct Args {}

fn create_api() -> RouterApi {
  let dev = DevApi::new();
  let clock = Arc::new(VirtualClock::new(Instant::ymd_hms(2020, 1, 1, 0, 0, 0)));
  let logger: Arc<dyn for<'r> Logger<HttpDinoparcClientEvent<'r, &'r [u8]>>> = Arc::new(NoopLogger);
  let hammerfest_client: Arc<dyn HammerfestClient> = Arc::new(HttpHammerfestClient::new(Arc::clone(&clock)).unwrap());
  let hammerfest_store: Arc<dyn HammerfestStore> = Arc::new(MemHammerfestStore::new(Arc::clone(&clock)));
  let dinoparc_client: Arc<dyn DinoparcClient> =
    Arc::new(HttpDinoparcClient::new(Arc::clone(&clock), Arc::clone(&logger)).unwrap());
  let dinoparc_store: Arc<dyn DinoparcStore> = Arc::new(MemDinoparcStore::new(Arc::clone(&clock)));
  let forum_store: Arc<dyn ForumStore> = Arc::new(MemForumStore::new(Arc::clone(&clock), Uuid4Generator));
  let link_store: Arc<dyn LinkStore> = Arc::new(MemLinkStore::new(Arc::clone(&clock)));
  let user_store: Arc<dyn UserStore> = Arc::new(MemUserStore::new(Arc::clone(&clock), Uuid4Generator));
  let auth_store: Arc<dyn AuthStore> = Arc::new(MemAuthStore::new(Arc::clone(&clock), Uuid4Generator));
  let email_formatter: Arc<dyn EmailFormatter> = Arc::new(JsonEmailFormatter);
  let mailer: Arc<dyn Mailer> = Arc::new(MemMailer::new());
  let password: Arc<dyn PasswordService> = Arc::new(ScryptPasswordService::recommended_for_tests());
  let oauth_provider_store: Arc<dyn OauthProviderStore> = Arc::new(MemOauthProviderStore::new(
    Arc::clone(&clock),
    Arc::clone(&password),
    Uuid4Generator,
  ));
  let token_store: Arc<dyn TokenStore> = Arc::new(MemTokenStore::new(Arc::clone(&clock)));
  let twinoid_client: Arc<dyn TwinoidClient> = Arc::new(HttpTwinoidClient::new(Arc::clone(&clock)).unwrap());
  let twinoid_oauth_client: Arc<dyn RfcOauthClient> = Arc::new(MemRfcOauthClient::new());
  let twinoid_store: Arc<dyn TwinoidStore> = Arc::new(MemTwinoidStore::new(Arc::clone(&clock)));
  let internal_auth_key = b"dev_secret_internal_auth".to_vec();
  let auth_secret = b"dev_secret".to_vec();

  let auth = Arc::new(AuthService::new(
    auth_store,
    Arc::clone(&clock) as Arc<dyn Clock>,
    Arc::clone(&dinoparc_client),
    Arc::clone(&dinoparc_store),
    email_formatter,
    Arc::clone(&hammerfest_client),
    Arc::clone(&hammerfest_store),
    Arc::clone(&link_store),
    mailer,
    Arc::clone(&oauth_provider_store),
    Arc::clone(&password),
    Arc::clone(&user_store),
    Arc::clone(&twinoid_client),
    Arc::clone(&twinoid_oauth_client),
    Arc::clone(&twinoid_store),
    Arc::new(Uuid4Generator) as Arc<dyn UuidGenerator>,
    internal_auth_key,
    auth_secret,
  ));

  let dinoparc = Arc::new(DinoparcService::new(
    Arc::clone(&dinoparc_client),
    Arc::clone(&dinoparc_store),
    Arc::clone(&link_store),
    Arc::clone(&token_store),
    Arc::clone(&user_store),
  ));

  let forum = Arc::new(ForumService::new(
    Arc::clone(&clock) as Arc<dyn Clock>,
    Arc::clone(&forum_store),
    Arc::clone(&user_store),
  ));

  let hammerfest = Arc::new(HammerfestService::new(
    Arc::clone(&hammerfest_client),
    Arc::clone(&hammerfest_store),
    Arc::clone(&link_store),
    Arc::clone(&token_store),
    Arc::clone(&user_store),
  ));

  let oauth = Arc::new(OauthService::new(
    Arc::clone(&oauth_provider_store),
    Arc::clone(&user_store),
  ));

  let twinoid = Arc::new(TwinoidService::new(
    Arc::clone(&link_store),
    Arc::clone(&twinoid_store),
    Arc::clone(&user_store),
  ));

  let user = Arc::new(UserService::new(
    Arc::clone(&clock) as Arc<dyn Clock>,
    dinoparc_client,
    Arc::clone(&dinoparc_store),
    Arc::clone(&hammerfest_client),
    Arc::clone(&hammerfest_store),
    Arc::clone(&link_store),
    password,
    Arc::clone(&token_store),
    twinoid_client,
    twinoid_store,
    user_store,
  ));

  RouterApi {
    dev,
    auth,
    clock: Arc::clone(&clock) as Arc<dyn Clock>,
    dinoparc,
    forum,
    hammerfest,
    oauth,
    twinoid,
    user,
  }
}

pub async fn run(_args: &Args) -> Result<(), AnyError> {
  let api = create_api();

  eprintln!("Started at http://localhost:3030");

  // run it with hyper on localhost:3000
  axum::Server::bind(&"0.0.0.0:3030".parse().unwrap())
    .serve(etwin_rest::app(api).into_make_service())
    .await
    .unwrap();

  Ok(())
}