Skip to content
This repository has been archived by the owner on Aug 1, 2022. It is now read-only.

Commit

Permalink
feat(proxy): list all orgs by member (#309)
Browse files Browse the repository at this point in the history
* List all orgs the given user is a member of
* Resolve some local clippy complaints
* Allow clippy::indexing_slicing in org tests

Co-authored-by: Alexander Simmerl <a.simmerl@gmail.com>
  • Loading branch information
Merle Breitkreuz and xla committed Apr 28, 2020
1 parent 730e31b commit a10676c
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 45 deletions.
4 changes: 2 additions & 2 deletions proxy/src/http/identity.rs
Expand Up @@ -17,7 +17,7 @@ pub fn filters(
get_filter().or(create_filter(store))
}

/// POST /identities
/// `POST /identities`
fn create_filter(
store: Arc<RwLock<kv::Store>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand All @@ -42,7 +42,7 @@ fn create_filter(
.and_then(handler::create)
}

/// GET /identities/<id>
/// `GET /identities/<id>`
fn get_filter() -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
path("identities")
.and(document::param::<String>("id", "Unique ID of the Identity"))
Expand Down
6 changes: 3 additions & 3 deletions proxy/src/http/notification.rs
Expand Up @@ -14,7 +14,7 @@ pub fn filters(
.or(stream_filter(subscriptions))
}

/// GET /notifications
/// `GET /notifications`
fn stream_filter(
subscriptions: Subscriptions,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand All @@ -35,7 +35,7 @@ fn stream_filter(
.and_then(handler::stream)
}

/// GET /notifications/test/index.html
/// `GET /notifications/test/index.html`
fn test_html_filter() -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
path!("notifications" / "test" / "index.html")
.and(warp::get())
Expand All @@ -48,7 +48,7 @@ fn test_html_filter() -> impl Filter<Extract = impl Reply, Error = Rejection> +
})
}

/// GET /notifications/test/index.js
/// `GET /notifications/test/index.js`
fn test_js_filter() -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
path!("notifications" / "test" / "index.js")
.and(warp::get())
Expand Down
33 changes: 13 additions & 20 deletions proxy/src/http/org.rs
Expand Up @@ -16,11 +16,10 @@ pub fn filters(
registry: Arc<RwLock<registry::Registry>>,
subscriptions: notification::Subscriptions,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
get_filter(Arc::<RwLock<registry::Registry>>::clone(&registry))
.or(register_filter(registry, subscriptions))
get_filter(Arc::clone(&registry)).or(register_filter(registry, subscriptions))
}

/// POST /orgs
/// `POST /orgs`
fn register_filter(
registry: Arc<RwLock<registry::Registry>>,
subscriptions: notification::Subscriptions,
Expand All @@ -47,7 +46,7 @@ fn register_filter(
.and_then(handler::register)
}

/// GET /orgs/<id>
/// `GET /orgs/<id>`
fn get_filter(
registry: Arc<RwLock<registry::Registry>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand Down Expand Up @@ -189,10 +188,7 @@ mod test {
)));
let subscriptions = notification::Subscriptions::default();

let api = super::filters(
Arc::<RwLock<registry::Registry>>::clone(&registry),
subscriptions,
);
let api = super::filters(Arc::clone(&registry), subscriptions);

let res = request()
.method("POST")
Expand Down Expand Up @@ -223,20 +219,17 @@ mod test {
radicle_registry_client::Client::new_emulator(),
)));
let subscriptions = notification::Subscriptions::default();
let api = super::filters(
Arc::<RwLock<registry::Registry>>::clone(&registry),
subscriptions,
);
let api = super::filters(Arc::clone(&registry), subscriptions);

// Register the org
request()
.method("POST")
.path("/orgs")
.json(&super::RegisterInput {
id: "monadic".into(),
})
.reply(&api)
.await;
let alice = radicle_registry_client::ed25519::Pair::from_legacy_string("//Alice", None);
let fee: radicle_registry_client::Balance = 100;
registry
.write()
.await
.register_org(&alice, "monadic".to_string(), fee)
.await
.unwrap();

let res = request()
.method("GET")
Expand Down
8 changes: 4 additions & 4 deletions proxy/src/http/project.rs
Expand Up @@ -26,7 +26,7 @@ pub fn filters(
.or(register_filter(registry, subscriptions))
}

/// POST /projects
/// `POST /projects`
fn create_filter(
paths: Arc<RwLock<Paths>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand All @@ -51,7 +51,7 @@ fn create_filter(
.and_then(handler::create)
}

/// GET /projects/<id>
/// `GET /projects/<id>`
fn get_filter(
paths: Arc<RwLock<Paths>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand Down Expand Up @@ -80,7 +80,7 @@ fn get_filter(
.and_then(handler::get)
}

/// GET /projects
/// `GET /projects`
fn list_filter(
paths: Arc<RwLock<Paths>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand All @@ -102,7 +102,7 @@ fn list_filter(
.and_then(handler::list)
}

/// POST /projects/register
/// `POST /projects/register`
fn register_filter(
registry: Arc<RwLock<registry::Registry>>,
subscriptions: notification::Subscriptions,
Expand Down
2 changes: 1 addition & 1 deletion proxy/src/http/session.rs
Expand Up @@ -10,7 +10,7 @@ use warp::{path, Filter, Rejection, Reply};
use crate::identity;
use crate::session;

/// GET /
/// `GET /`
pub fn get_filter(
store: Arc<RwLock<kv::Store>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand Down
14 changes: 7 additions & 7 deletions proxy/src/http/source.rs
Expand Up @@ -40,7 +40,7 @@ fn filters(
.or(tree_filter(paths))
}

/// GET /blob/<project_id>/<revision>/<path...>
/// `GET /blob/<project_id>/<revision>/<path...>`
fn blob_filter(
paths: Arc<RwLock<Paths>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand Down Expand Up @@ -71,7 +71,7 @@ fn blob_filter(
.and_then(handler::blob)
}

/// GET /branches/<project_id>
/// `GET /branches/<project_id>`
fn branches_filter(
paths: Arc<RwLock<Paths>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand All @@ -97,7 +97,7 @@ fn branches_filter(
.and_then(handler::branches)
}

/// GET /commit/<project_id>/<sha1>
/// `GET /commit/<project_id>/<sha1>`
fn commit_filter(
paths: Arc<RwLock<Paths>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand All @@ -121,7 +121,7 @@ fn commit_filter(
.and_then(handler::commit)
}

/// GET /branches/<project_id>
/// `GET /branches/<project_id>`
fn local_branches_filter() -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
path("local-branches")
.and(warp::get())
Expand All @@ -146,7 +146,7 @@ fn local_branches_filter() -> impl Filter<Extract = impl Reply, Error = Rejectio
.and_then(handler::local_branches)
}

/// GET /revisions/<project_id>
/// `GET /revisions/<project_id>`
fn revisions_filter(
paths: Arc<RwLock<Paths>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand Down Expand Up @@ -174,7 +174,7 @@ fn revisions_filter(
.and_then(handler::revisions)
}

/// GET /tags/<project_id>
/// `GET /tags/<project_id>`
fn tags_filter(
paths: Arc<RwLock<Paths>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand All @@ -198,7 +198,7 @@ fn tags_filter(
.and_then(handler::tags)
}

/// GET /tree/<project_id>/<revision>/<prefix>
/// `GET /tree/<project_id>/<revision>/<prefix>`
fn tree_filter(
paths: Arc<RwLock<Paths>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand Down
2 changes: 1 addition & 1 deletion proxy/src/http/transaction.rs
Expand Up @@ -18,7 +18,7 @@ pub fn filters(
list_filter(registry)
}

/// POST /transactions
/// `POST /transactions`
fn list_filter(
registry: Arc<RwLock<registry::Registry>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand Down
94 changes: 90 additions & 4 deletions proxy/src/http/user.rs
Expand Up @@ -16,8 +16,11 @@ pub fn routes(
registry: Arc<RwLock<registry::Registry>>,
subscriptions: notification::Subscriptions,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
path("users")
.and(register_filter(Arc::clone(&registry), subscriptions).or(get_filter(registry)))
path("users").and(
register_filter(Arc::clone(&registry), subscriptions)
.or(list_orgs_filter(Arc::clone(&registry)))
.or(get_filter(registry)),
)
}

/// Combination of all user filters.
Expand All @@ -26,7 +29,9 @@ fn filters(
registry: Arc<RwLock<registry::Registry>>,
subscriptions: notification::Subscriptions,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
get_filter(Arc::clone(&registry)).or(register_filter(registry, subscriptions))
list_orgs_filter(Arc::clone(&registry))
.or(get_filter(Arc::clone(&registry)))
.or(register_filter(registry, subscriptions))
}

/// GET /<handle>
Expand All @@ -37,7 +42,7 @@ fn get_filter(
.and(super::with_registry(registry))
.and(document::param::<String>(
"handle",
"ID fo the user to query for",
"ID of the user to query for",
))
.and(document::document(document::description("Fetch a User")))
.and(document::document(document::tag("User")))
Expand Down Expand Up @@ -74,6 +79,31 @@ fn register_filter(
.and_then(handler::register)
}

/// `GET /<handle>/orgs`
fn list_orgs_filter(
registry: Arc<RwLock<registry::Registry>>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::get()
.and(super::with_registry(registry))
.and(document::param::<String>(
"handle",
"ID of the user to query for",
))
.and(path("orgs"))
.and(document::document(document::description(
"List all orgs the user is a member of",
)))
.and(document::document(document::tag("User")))
.and(document::document(
document::response(
200,
document::body(document::array(registry::Org::document())).mime("application/json"),
)
.description("Successful retrieval"),
))
.and_then(handler::list_orgs)
}

/// User handlers for conversion between core domain and http request fullfilment.
mod handler {
use radicle_registry_client::Balance;
Expand Down Expand Up @@ -116,6 +146,17 @@ mod handler {

Ok(reply::with_status(reply::json(&tx), StatusCode::CREATED))
}

/// List the orgs the user is a member of.
pub async fn list_orgs(
registry: Arc<RwLock<registry::Registry>>,
handle: String,
) -> Result<impl Reply, Rejection> {
let reg = registry.read().await;
let orgs = reg.list_orgs(handle).await?;

Ok(reply::json(&orgs))
}
}

impl Serialize for registry::User {
Expand Down Expand Up @@ -196,6 +237,7 @@ mod test {
use warp::http::StatusCode;
use warp::test::request;

use crate::avatar;
use crate::notification;
use crate::registry;

Expand Down Expand Up @@ -262,4 +304,48 @@ mod test {
assert_eq!(res.status(), StatusCode::CREATED);
assert_eq!(have, json!(tx));
}

#[tokio::test]
async fn list_orgs() {
let registry = Arc::new(RwLock::new(registry::Registry::new(
radicle_registry_client::Client::new_emulator(),
)));
let subscriptions = notification::Subscriptions::default();
let api = super::filters(Arc::clone(&registry), subscriptions);

// Register the user
let alice = radicle_registry_client::ed25519::Pair::from_legacy_string("//Alice", None);
registry
.write()
.await
.register_user(&alice, "alice".into(), Some("123abcd.git".into()), 100)
.await
.unwrap();

// Register the org
let fee: radicle_registry_client::Balance = 100;
registry
.write()
.await
.register_org(&alice, "monadic".to_string(), fee)
.await
.unwrap();

let res = request()
.method("GET")
.path("/alice/orgs")
.reply(&api)
.await;

let have: Value = serde_json::from_slice(res.body()).unwrap();

assert_eq!(res.status(), StatusCode::OK);
assert_eq!(
have,
json!([registry::Org {
id: "monadic".to_string(),
avatar_fallback: avatar::Avatar::from("monadic", avatar::Usage::Org),
}])
);
}
}

0 comments on commit a10676c

Please sign in to comment.