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.

135 lines
3.9 KiB

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