You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
3.7 KiB

  1. #![forbid(unsafe_code)]
  2. #[macro_use]
  3. extern crate diesel;
  4. #[macro_use]
  5. extern crate derive_new;
  6. mod actions;
  7. mod errors;
  8. mod middlewares;
  9. pub mod models;
  10. mod routes;
  11. mod schema;
  12. mod services;
  13. mod types;
  14. mod utils;
  15. use actix_files as fs;
  16. use actix_identity::{CookieIdentityPolicy, IdentityService};
  17. use actix_web::web::ServiceConfig;
  18. use actix_web::{cookie::SameSite, web, App, HttpServer};
  19. use rand::Rng;
  20. use serde::Deserialize;
  21. use std::io;
  22. use tracing_actix_web::TracingLogger;
  23. use types::DbPool;
  24. build_info::build_info!(pub fn get_build_info);
  25. #[derive(Deserialize, Debug, Clone)]
  26. #[serde(rename_all = "lowercase")]
  27. pub enum LoggerFormat {
  28. Json,
  29. Plain,
  30. }
  31. #[derive(Deserialize, Debug, Clone)]
  32. pub struct EnvConfig {
  33. pub database_url: String,
  34. pub http_host: String,
  35. #[serde(default = "default_hash_cost")]
  36. pub hash_cost: u32,
  37. pub logger_format: LoggerFormat,
  38. }
  39. #[derive(Deserialize, Debug, Clone)]
  40. pub struct AppConfig {
  41. pub hash_cost: u32,
  42. }
  43. #[derive(Clone)]
  44. pub struct AppData {
  45. pub config: AppConfig,
  46. pub pool: DbPool,
  47. }
  48. pub fn default_hash_cost() -> u32 {
  49. 8
  50. }
  51. pub fn configure_app(app_data: AppData) -> Box<dyn Fn(&mut ServiceConfig)> {
  52. Box::new(move |cfg: &mut ServiceConfig| {
  53. cfg.data(app_data.clone())
  54. .service(
  55. web::scope("/api")
  56. .service(
  57. web::scope("/users")
  58. .route(
  59. "",
  60. web::get().to(routes::users::get_all_users),
  61. )
  62. .route(
  63. "/{user_id}",
  64. web::get().to(routes::users::get_user),
  65. )
  66. .route("", web::post().to(routes::users::add_user)),
  67. )
  68. .route(
  69. "/build-info",
  70. web::get().to(routes::misc::build_info_req),
  71. ),
  72. )
  73. // .route("/api/users/get", web::get().to(user_controller.get_user.into()))
  74. .service(web::scope("/api/public")) // public endpoint - not implemented yet
  75. .service(routes::auth::login)
  76. .service(routes::auth::logout)
  77. .service(routes::auth::index)
  78. // .service(routes::users::add_user)
  79. .service(fs::Files::new("/", "./static"));
  80. })
  81. }
  82. //TODO: capture the panic in this method
  83. pub fn id_service(
  84. private_key: &[u8],
  85. ) -> actix_identity::IdentityService<CookieIdentityPolicy> {
  86. IdentityService::new(
  87. CookieIdentityPolicy::new(&private_key)
  88. .name("my-app-auth")
  89. .secure(false)
  90. .same_site(SameSite::Lax),
  91. )
  92. }
  93. pub async fn run(addr: String, app_data: AppData) -> io::Result<()> {
  94. let bi = get_build_info();
  95. tracing::info!("Starting {} {}", bi.crate_info.name, bi.crate_info.version);
  96. println!(
  97. r#"
  98. __ .__ .___
  99. _____ _____/ |_|__|__ ___ __| _/____ _____ ____
  100. \__ \ _/ ___\ __\ \ \/ / ______ / __ |/ __ \ / \ / _ \
  101. / __ \\ \___| | | |> < /_____/ / /_/ \ ___/| Y Y ( <_> )
  102. (____ /\___ >__| |__/__/\_ \ \____ |\___ >__|_| /\____/
  103. \/ \/ \/ \/ \/ \/
  104. "#
  105. );
  106. let private_key = rand::thread_rng().gen::<[u8; 32]>();
  107. let app = move || {
  108. App::new()
  109. .configure(configure_app(app_data.clone()))
  110. .wrap(id_service(&private_key))
  111. .wrap(TracingLogger)
  112. };
  113. HttpServer::new(app).bind(addr)?.run().await
  114. }