Skip to content

Commit bd5a991

Browse files
committed
#13 add authorization test in server, make drive public by default
1 parent f0ec2b5 commit bd5a991

File tree

5 files changed

+43
-33
lines changed

5 files changed

+43
-33
lines changed

lib/src/db.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ impl Storelike for Db {
396396
.map_err(|e| format!("Failed to populate default store. {}", e))?;
397397
// This is a potentially expensive operation, but is needed to make TPF queries work with the models created in here
398398
self.build_index(true)?;
399-
crate::populate::populate_hierarchy(self)
399+
crate::populate::create_drive(self)
400400
.map_err(|e| format!("Failed to populate hierarcy. {}", e))?;
401401
crate::populate::populate_collections(self)
402402
.map_err(|e| format!("Failed to populate collections. {}", e))?;

lib/src/hierarchy.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,15 @@ pub fn check_rights(
6262
) -> AtomicResult<bool> {
6363
// Check if the resource's write rights explicitly refers to the agent or the public agent
6464
if let Ok(arr_val) = resource.get(&right.to_string()) {
65-
if arr_val.to_subjects(None)?.iter().any(|s| match s.as_str() {
66-
urls::PUBLIC_AGENT => true,
67-
for_agent => s == for_agent,
68-
}) {
69-
return Ok(true);
65+
for s in arr_val.to_subjects(None)? {
66+
match s.as_str() {
67+
urls::PUBLIC_AGENT => return Ok(true),
68+
agent => {
69+
if agent == for_agent {
70+
return Ok(true);
71+
}
72+
}
73+
};
7074
}
7175
}
7276
// Try the parents recursively

lib/src/populate.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,8 @@ pub fn populate_base_models(store: &impl Storelike) -> AtomicResult<()> {
141141
Ok(())
142142
}
143143

144-
/// Adds the hierarchy related items (Drive, default Folder) to the Store.
145-
/// Sets the home page as the top level node, and gives write rights to the default agent.
146-
/// Requires a `self_url` to be set in the store.
147-
pub fn populate_hierarchy(store: &impl Storelike) -> AtomicResult<()> {
144+
/// Creates a Drive resource at the base URL. Does not set rights. Use set_drive_rights for that.
145+
pub fn create_drive(store: &impl Storelike) -> AtomicResult<()> {
148146
let self_url = store
149147
.get_self_url()
150148
.ok_or("No self_url set, cannot populate store with Drive")?;
@@ -156,24 +154,12 @@ pub fn populate_hierarchy(store: &impl Storelike) -> AtomicResult<()> {
156154
base_url.host_str().ok_or("Can't use current base URL")?,
157155
store,
158156
)?;
159-
// The root agent does not yet exist
160-
// let root_agent = store.get_default_agent()?.subject;
161-
// drive.set_propval(
162-
// urls::READ.into(),
163-
// Value::ResourceArray(vec![root_agent.clone()]),
164-
// store,
165-
// )?;
166-
// drive.set_propval(
167-
// urls::WRITE.into(),
168-
// Value::ResourceArray(vec![root_agent]),
169-
// store,
170-
// )?;
171157
drive.save_locally(store)?;
172158
Ok(())
173159
}
174160

175161
/// Get the Drive resource (base URL), set agent as the Root user, provide write and read access to the Root user. Also, by default, makes the Root publicly visible.
176-
pub fn set_up_drive(store: &impl Storelike) -> AtomicResult<()> {
162+
pub fn set_drive_rights(store: &impl Storelike) -> AtomicResult<()> {
177163
// Now let's add the agent as the Root user and provide write access
178164
let mut drive = store.get_resource(store.get_base_url())?;
179165
let write_agents = vec![store.get_default_agent()?.subject];

server/src/appstate.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,17 @@ pub fn init(config: Config) -> AtomicServerResult<AppState> {
5252
set_default_agent(&config, &store)?;
5353
if config.initialize {
5454
log::info!("Running populate commands...");
55-
atomic_lib::populate::populate_hierarchy(&store)
55+
atomic_lib::populate::create_drive(&store)
5656
.map_err(|e| format!("Failed to populate hierarchy. {}", e))?;
57+
atomic_lib::populate::set_drive_rights(&store)
58+
.map_err(|e| format!("Failed to set drive rights. {}", e))?;
5759
atomic_lib::populate::populate_collections(&store)
5860
.map_err(|e| format!("Failed to populate collections. {}", e))?;
5961
atomic_lib::populate::populate_endpoints(&store)
6062
.map_err(|e| format!("Failed to populate endpoints. {}", e))?;
6163
set_up_initial_invite(&store)?;
6264
// This means that editing the .env does _not_ grant you the rights to edit the Drive.
6365
log::info!("Setting rights to Drive {}", store.get_base_url());
64-
atomic_lib::populate::set_up_drive(&store)?;
6566
}
6667

6768
// Initialize search constructs

server/src/tests.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ use super::*;
88
use actix_web::{
99
dev::{Body, ResponseBody},
1010
test::{self, TestRequest},
11-
web, App,
11+
web::Data,
12+
App,
1213
};
14+
use atomic_lib::urls;
1315

1416
trait BodyTest {
1517
fn as_str(&self) -> &str;
@@ -19,11 +21,11 @@ impl BodyTest for ResponseBody<Body> {
1921
fn as_str(&self) -> &str {
2022
match self {
2123
ResponseBody::Body(ref b) => match b {
22-
Body::Bytes(ref by) => std::str::from_utf8(&by).unwrap(),
24+
Body::Bytes(ref by) => std::str::from_utf8(by).unwrap(),
2325
_ => panic!(),
2426
},
2527
ResponseBody::Other(ref b) => match b {
26-
Body::Bytes(ref by) => std::str::from_utf8(&by).unwrap(),
28+
Body::Bytes(ref by) => std::str::from_utf8(by).unwrap(),
2729
_ => panic!(),
2830
},
2931
}
@@ -55,13 +57,14 @@ async fn init_server() {
5557
.map_err(|e| format!("Initialization failed: {}", e))
5658
.expect("failed init config");
5759
let appstate = crate::appstate::init(config.clone()).expect("failed init appstate");
58-
let data = web::Data::new(std::sync::Mutex::new(appstate.clone()));
60+
let data = Data::new(std::sync::Mutex::new(appstate.clone()));
5961
let mut app = test::init_service(
6062
App::new()
6163
.app_data(data)
6264
.configure(|app| crate::routes::config_routes(app, &appstate.config)),
6365
)
6466
.await;
67+
let store = &appstate.store;
6568

6669
// Does not work, unfortunately, because the server is not accessible.
6770
// let fetched =
@@ -71,17 +74,33 @@ async fn init_server() {
7174
// Get HTML page
7275
let req = build_request_authenticated("/", &appstate).header("Accept", "application/html");
7376
let mut resp = test::call_service(&mut app, req.to_request()).await;
74-
println!("response: {:?}", resp);
7577
assert!(resp.status().is_success());
7678
let body = resp.take_body();
7779
assert!(body.as_str().contains("html"), "no html in response");
7880

81+
// Should 200 (public)
82+
let req = test::TestRequest::with_uri("/properties").header("Accept", "application/ad+json");
83+
let resp = test::call_service(&mut app, req.to_request()).await;
84+
assert_eq!(resp.status().as_u16(), 200, "resource should be public");
85+
86+
// Edit the properties collection - let's make it hidedn
87+
let mut drive = store.get_resource(&appstate.config.local_base_url).unwrap();
88+
drive
89+
.set_propval(
90+
urls::READ.into(),
91+
vec![appstate.store.get_default_agent().unwrap().subject].into(),
92+
&appstate.store,
93+
)
94+
.unwrap();
95+
drive.save(store).unwrap();
96+
7997
// Should 401 (Unauthorized)
8098
let req = test::TestRequest::with_uri("/properties").header("Accept", "application/ad+json");
8199
let resp = test::call_service(&mut app, req.to_request()).await;
82-
assert!(
83-
resp.status().is_client_error(),
84-
"resource should return 401 unauthorized"
100+
assert_eq!(
101+
resp.status().as_u16(),
102+
401,
103+
"resource should not be authorized for public"
85104
);
86105

87106
// Get JSON-AD

0 commit comments

Comments
 (0)