mirror of
				https://github.com/meilisearch/meilisearch.git
				synced 2025-10-31 07:56:28 +00:00 
			
		
		
		
	split data and api keys
This commit is contained in:
		| @@ -1,8 +1,6 @@ | ||||
| use std::ops::Deref; | ||||
| use std::sync::Arc; | ||||
|  | ||||
| use sha2::Digest; | ||||
|  | ||||
| use crate::index::{Checked, Settings}; | ||||
| use crate::index_controller::{ | ||||
|     error::Result, DumpInfo, IndexController, IndexMetadata, IndexStats, Stats, | ||||
| @@ -27,32 +25,7 @@ impl Deref for Data { | ||||
|  | ||||
| pub struct DataInner { | ||||
|     pub index_controller: IndexController, | ||||
|     pub api_keys: ApiKeys, | ||||
|     options: Opt, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct ApiKeys { | ||||
|     pub public: Option<String>, | ||||
|     pub private: Option<String>, | ||||
|     pub master: Option<String>, | ||||
| } | ||||
|  | ||||
| impl ApiKeys { | ||||
|     pub fn generate_missing_api_keys(&mut self) { | ||||
|         if let Some(master_key) = &self.master { | ||||
|             if self.private.is_none() { | ||||
|                 let key = format!("{}-private", master_key); | ||||
|                 let sha = sha2::Sha256::digest(key.as_bytes()); | ||||
|                 self.private = Some(format!("{:x}", sha)); | ||||
|             } | ||||
|             if self.public.is_none() { | ||||
|                 let key = format!("{}-public", master_key); | ||||
|                 let sha = sha2::Sha256::digest(key.as_bytes()); | ||||
|                 self.public = Some(format!("{:x}", sha)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     //pub api_keys: ApiKeys, | ||||
| } | ||||
|  | ||||
| impl Data { | ||||
| @@ -61,18 +34,8 @@ impl Data { | ||||
|  | ||||
|         let index_controller = IndexController::new(&path, &options)?; | ||||
|  | ||||
|         let mut api_keys = ApiKeys { | ||||
|             master: options.clone().master_key, | ||||
|             private: None, | ||||
|             public: None, | ||||
|         }; | ||||
|  | ||||
|         api_keys.generate_missing_api_keys(); | ||||
|  | ||||
|         let inner = DataInner { | ||||
|             index_controller, | ||||
|             api_keys, | ||||
|             options, | ||||
|         }; | ||||
|         let inner = Arc::new(inner); | ||||
|  | ||||
| @@ -120,14 +83,4 @@ impl Data { | ||||
|     pub async fn dump_status(&self, uid: String) -> Result<DumpInfo> { | ||||
|         Ok(self.index_controller.dump_info(uid).await?) | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     pub fn http_payload_size_limit(&self) -> usize { | ||||
|         self.options.http_payload_size_limit.get_bytes() as usize | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     pub fn api_keys(&self) -> &ApiKeys { | ||||
|         &self.api_keys | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -58,11 +58,41 @@ use actix_web::web; | ||||
|  | ||||
| use extractors::authentication::policies::*; | ||||
| use extractors::payload::PayloadConfig; | ||||
| use sha2::Digest; | ||||
|  | ||||
| pub fn configure_data(config: &mut web::ServiceConfig, data: Data) { | ||||
|     let http_payload_size_limit = data.http_payload_size_limit(); | ||||
| #[derive(Clone)] | ||||
| pub struct ApiKeys { | ||||
|     pub public: Option<String>, | ||||
|     pub private: Option<String>, | ||||
|     pub master: Option<String>, | ||||
| } | ||||
|  | ||||
| impl ApiKeys { | ||||
|     pub fn generate_missing_api_keys(&mut self) { | ||||
|         if let Some(master_key) = &self.master { | ||||
|             if self.private.is_none() { | ||||
|                 let key = format!("{}-private", master_key); | ||||
|                 let sha = sha2::Sha256::digest(key.as_bytes()); | ||||
|                 self.private = Some(format!("{:x}", sha)); | ||||
|             } | ||||
|             if self.public.is_none() { | ||||
|                 let key = format!("{}-public", master_key); | ||||
|                 let sha = sha2::Sha256::digest(key.as_bytes()); | ||||
|                 self.public = Some(format!("{:x}", sha)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub fn configure_data( | ||||
|     config: &mut web::ServiceConfig, | ||||
|     data: Data, | ||||
|     opt: &Opt, | ||||
|     ) { | ||||
|     let http_payload_size_limit = opt.http_payload_size_limit.get_bytes() as usize; | ||||
|     config | ||||
|         .app_data(web::Data::new(data.clone())) | ||||
|         // TODO!: Why are we passing the data with two different things? | ||||
|         .app_data(data) | ||||
|         .app_data( | ||||
|             web::JsonConfig::default() | ||||
| @@ -77,8 +107,15 @@ pub fn configure_data(config: &mut web::ServiceConfig, data: Data) { | ||||
|         ); | ||||
| } | ||||
|  | ||||
| pub fn configure_auth(config: &mut web::ServiceConfig, data: &Data) { | ||||
|     let keys = data.api_keys(); | ||||
| pub fn configure_auth(config: &mut web::ServiceConfig, opts: &Opt) { | ||||
|     let mut keys = ApiKeys { | ||||
|         master: opts.master_key.clone(), | ||||
|         private: None, | ||||
|         public: None, | ||||
|         }; | ||||
|  | ||||
|         keys.generate_missing_api_keys(); | ||||
|  | ||||
|     let auth_config = if let Some(ref master_key) = keys.master { | ||||
|         let private_key = keys.private.as_ref().unwrap(); | ||||
|         let public_key = keys.public.as_ref().unwrap(); | ||||
| @@ -94,7 +131,8 @@ pub fn configure_auth(config: &mut web::ServiceConfig, data: &Data) { | ||||
|         AuthConfig::NoAuth | ||||
|     }; | ||||
|  | ||||
|     config.app_data(auth_config); | ||||
|     config.app_data(auth_config) | ||||
|             .app_data(keys); | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "mini-dashboard")] | ||||
| @@ -138,7 +176,7 @@ pub fn dashboard(config: &mut web::ServiceConfig, _enable_frontend: bool) { | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! create_app { | ||||
|     ($data:expr, $enable_frontend:expr) => {{ | ||||
|     ($data:expr, $enable_frontend:expr, $opt:expr) => {{ | ||||
|         use actix_cors::Cors; | ||||
|         use actix_web::middleware::TrailingSlash; | ||||
|         use actix_web::App; | ||||
| @@ -147,8 +185,8 @@ macro_rules! create_app { | ||||
|         use meilisearch_http::{configure_auth, configure_data, dashboard}; | ||||
|  | ||||
|         App::new() | ||||
|             .configure(|s| configure_data(s, $data.clone())) | ||||
|             .configure(|s| configure_auth(s, &$data)) | ||||
|             .configure(|s| configure_data(s, $data.clone(), &$opt)) | ||||
|             .configure(|s| configure_auth(s, &$opt)) | ||||
|             .configure(routes::configure) | ||||
|             .configure(|s| dashboard(s, $enable_frontend)) | ||||
|             .wrap( | ||||
|   | ||||
| @@ -64,7 +64,7 @@ async fn main() -> anyhow::Result<()> { | ||||
|         tokio::task::spawn(analytics::analytics_sender(analytics_data, analytics_opt)); | ||||
|     } | ||||
|  | ||||
|     print_launch_resume(&opt, &data); | ||||
|     print_launch_resume(&opt); | ||||
|  | ||||
|     run_http(data, opt).await?; | ||||
|  | ||||
| @@ -73,7 +73,8 @@ async fn main() -> anyhow::Result<()> { | ||||
|  | ||||
| async fn run_http(data: Data, opt: Opt) -> anyhow::Result<()> { | ||||
|     let _enable_dashboard = &opt.env == "development"; | ||||
|     let http_server = HttpServer::new(move || create_app!(data, _enable_dashboard)) | ||||
|     let opt_clone = opt.clone(); | ||||
|     let http_server = HttpServer::new(move || create_app!(data, _enable_dashboard, opt_clone)) | ||||
|         // Disable signals allows the server to terminate immediately when a user enter CTRL-C | ||||
|         .disable_signals(); | ||||
|  | ||||
| @@ -83,12 +84,12 @@ async fn run_http(data: Data, opt: Opt) -> anyhow::Result<()> { | ||||
|             .run() | ||||
|             .await?; | ||||
|     } else { | ||||
|         http_server.bind(opt.http_addr)?.run().await?; | ||||
|         http_server.bind(&opt.http_addr)?.run().await?; | ||||
|     } | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| pub fn print_launch_resume(opt: &Opt, data: &Data) { | ||||
| pub fn print_launch_resume(opt: &Opt) { | ||||
|     let commit_sha = option_env!("VERGEN_GIT_SHA").unwrap_or("unknown"); | ||||
|     let commit_date = option_env!("VERGEN_GIT_COMMIT_TIMESTAMP").unwrap_or("unknown"); | ||||
|  | ||||
| @@ -133,7 +134,7 @@ Anonymous telemetry:   \"Enabled\"" | ||||
|  | ||||
|     eprintln!(); | ||||
|  | ||||
|     if data.api_keys().master.is_some() { | ||||
|     if opt.master_key.is_some() { | ||||
|         eprintln!("A Master Key has been set. Requests to MeiliSearch won't be authorized unless you provide an authentication key."); | ||||
|     } else { | ||||
|         eprintln!("No master key found; The server will accept unidentified requests. \ | ||||
|   | ||||
| @@ -10,7 +10,7 @@ use crate::extractors::authentication::{policies::*, GuardedData}; | ||||
| use crate::index::{Settings, Unchecked}; | ||||
| use crate::index_controller::update_actor::RegisterUpdate; | ||||
| use crate::index_controller::{UpdateResult, UpdateStatus}; | ||||
| use crate::Data; | ||||
| use crate::{ApiKeys, Data}; | ||||
|  | ||||
| mod dump; | ||||
| mod indexes; | ||||
| @@ -262,8 +262,8 @@ struct KeysResponse { | ||||
|     public: Option<String>, | ||||
| } | ||||
|  | ||||
| pub async fn list_keys(data: GuardedData<Admin, Data>) -> HttpResponse { | ||||
|     let api_keys = data.api_keys.clone(); | ||||
| pub async fn list_keys(data: GuardedData<Admin, ApiKeys>) -> HttpResponse { | ||||
|     let api_keys = (*data).clone(); | ||||
|     HttpResponse::Ok().json(&KeysResponse { | ||||
|         private: api_keys.private, | ||||
|         public: api_keys.public, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user