use super::request::{configured, request}; use dever_runtime::{ auth::{Error, Identity}, authorization::{self, Failure}, database::{Context as DatabaseContext, Registry, Sql}, task::Runtime, }; struct Directory(std::path::PathBuf); impl Drop for Directory { fn drop(&mut self) { std::fs::remove_dir_all(&self.0).unwrap(); } } #[test] fn entry_namespace_requires_role_authorization_and_ignores_request_coordinates() { let service = configured(Some("https://unit.test"), "user.account.verify").unwrap(); let cookie = super::request::cookie(&service); let request = request( "POST", &[ ("Host", "unit.test"), ("Origin", "https://unit.test"), ("Cookie", &cookie), ("X-Component", "forged"), ("X-Domain", "forged"), ], ); let (mut context, _) = service.prepare("admin", &request, false, 100).unwrap(); assert_eq!(context.entry_namespace().unwrap_err(), Error::Forbidden); context .establish(Identity { id: "user".into(), user_id: Some(7), tenant_id: None, }) .unwrap(); assert_eq!(context.entry_namespace().unwrap_err(), Error::Forbidden); let unique = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); let name = format!("dever-entry-{}-{unique}", std::process::id()); let executable = std::env::current_exe().unwrap(); let directory = Directory(executable.parent().unwrap().join(&name)); std::fs::create_dir(&directory.0).unwrap(); let settings = directory.0.join("setting.json"); std::fs::write(&settings, serde_json::json!({"database":{"default":{"type":"sqlite","path":format!("{name}/entry.db"),"max_connections":1}}}).to_string()).unwrap(); Runtime::new(Default::default()).unwrap().run(async |scope| { let registry = Registry::load(&settings, &authorization::schema::BINDINGS, scope).await.unwrap(); let mut database = DatabaseContext::new(registry); let executor = database.on(1, scope).await.unwrap(); executor.execute(scope, Sql::same("INSERT INTO _dever_permission(key,component,domain,site,action,method,kind,active) VALUES ('news.article.admin.create','news','article','admin','create','POST','http',1)"), vec![]).await.unwrap(); assert!(matches!(authorization::authorize_entry(&mut database, 1, scope, &mut context, "news", "article", "create").await, Err(Failure::Access(403)))); assert_eq!(context.entry_namespace().unwrap_err(), Error::Forbidden); authorization::owner(database.on(1, scope).await.unwrap(), scope, "admin", 7).await.unwrap(); let transaction = database.enter(); authorization::authorize_entry(&mut database, 1, scope, &mut context, "news", "article", "create").await.unwrap(); assert_eq!(authorization::permissions(&mut database, 1, scope, &context, true).await.unwrap().len(), 1); database.finish(scope, transaction, true).await.unwrap(); assert_eq!(context.entry_namespace().unwrap(), ("news", "article")); assert_eq!(context.site(), "admin"); database.on(1, scope).await.unwrap().execute(scope, "UPDATE _dever_permission SET active=0", vec![]).await.unwrap(); assert!(authorization::permissions(&mut database, 1, scope, &context, true).await.unwrap().is_empty()); assert!(matches!(authorization::authorize_key(&mut database, 1, scope, &context, "news.article.admin.create").await, Err(Failure::Access(403)))); }).unwrap(); }