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.

119 lines
3.5 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::{cookie::SameSite, middleware, web, App, HttpServer};
  18. use actix_web::{middleware::Logger, web::ServiceConfig};
  19. use rand::Rng;
  20. use serde::Deserialize;
  21. use std::io;
  22. use types::DbPool;
  23. build_info::build_info!(pub fn get_build_info);
  24. #[derive(Deserialize, Debug, Clone)]
  25. pub struct EnvConfig {
  26. pub database_url: String,
  27. pub http_host: String,
  28. #[serde(default = "default_hash_cost")]
  29. pub hash_cost: u8,
  30. }
  31. #[derive(Deserialize, Debug, Clone)]
  32. pub struct AppConfig {
  33. pub hash_cost: u8,
  34. }
  35. #[derive(Clone)]
  36. pub struct AppData {
  37. pub config: AppConfig,
  38. pub pool: DbPool,
  39. }
  40. pub fn default_hash_cost() -> u8 {
  41. 8
  42. }
  43. pub fn configure_app(app_data: AppData) -> Box<dyn Fn(&mut ServiceConfig)> {
  44. Box::new(move |cfg: &mut ServiceConfig| {
  45. cfg.data(app_data.clone())
  46. .service(
  47. web::scope("/api")
  48. .service(
  49. web::scope("/users")
  50. .route(
  51. "",
  52. web::get().to(routes::users::get_all_users),
  53. )
  54. .route(
  55. "/{user_id}",
  56. web::get().to(routes::users::get_user),
  57. ),
  58. )
  59. .route(
  60. "/build-info",
  61. web::get().to(routes::misc::build_info_req),
  62. ),
  63. )
  64. // .route("/api/users/get", web::get().to(user_controller.get_user.into()))
  65. .service(web::scope("/api/public")) // public endpoint - not implemented yet
  66. .service(routes::auth::login)
  67. .service(routes::auth::logout)
  68. .service(routes::auth::index)
  69. .service(routes::users::add_user)
  70. .service(fs::Files::new("/", "./static"));
  71. })
  72. }
  73. //TODO: capture the panic in this method
  74. pub fn id_service(
  75. private_key: &[u8],
  76. ) -> actix_identity::IdentityService<CookieIdentityPolicy> {
  77. IdentityService::new(
  78. CookieIdentityPolicy::new(&private_key)
  79. .name("my-app-auth")
  80. .secure(false)
  81. .same_site(SameSite::Lax),
  82. )
  83. }
  84. pub fn app_logger() -> Logger {
  85. middleware::Logger::default()
  86. }
  87. pub async fn run(addr: String, app_data: AppData) -> io::Result<()> {
  88. let bi = get_build_info();
  89. log::info!("Starting {} {}", bi.crate_info.name, bi.crate_info.version);
  90. println!(
  91. r#"
  92. __ .__ .___
  93. _____ _____/ |_|__|__ ___ __| _/____ _____ ____
  94. \__ \ _/ ___\ __\ \ \/ / ______ / __ |/ __ \ / \ / _ \
  95. / __ \\ \___| | | |> < /_____/ / /_/ \ ___/| Y Y ( <_> )
  96. (____ /\___ >__| |__/__/\_ \ \____ |\___ >__|_| /\____/
  97. \/ \/ \/ \/ \/ \/
  98. "#
  99. );
  100. let private_key = rand::thread_rng().gen::<[u8; 32]>();
  101. let app = move || {
  102. App::new()
  103. .configure(configure_app(app_data.clone()))
  104. .wrap(id_service(&private_key))
  105. .wrap(app_logger())
  106. };
  107. HttpServer::new(app).bind(addr)?.run().await
  108. }