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.

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