commit 4d50014e355d806c6b13ef349899ad1546db0982
parent ed97725c8b389b4b760d84130bcbac283126bf70
Author: Miroslav Prasil <miroslav@prasil.info>
Date: Wed, 30 May 2018 13:28:31 +0100
Implement request guards for organization
Diffstat:
2 files changed, 108 insertions(+), 18 deletions(-)
diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs
@@ -6,7 +6,7 @@ use db::DbConn;
use db::models::*;
use api::{PasswordData, JsonResult, EmptyResult, NumberOrString};
-use auth::Headers;
+use auth::{Headers, AdminHeaders, OwnerHeaders};
#[derive(Deserialize)]
@@ -82,11 +82,7 @@ fn delete_organization(org_id: String, data: Json<PasswordData>, headers: Header
}
#[get("/organizations/<org_id>")]
-fn get_organization(org_id: String, headers: Headers, conn: DbConn) -> JsonResult {
- if UserOrganization::find_by_user_and_org( &headers.user.uuid, &org_id, &conn).is_none() {
- err!("User not in Organization or Organization doesn't exist")
- }
-
+fn get_organization(org_id: String, headers: OwnerHeaders, conn: DbConn) -> JsonResult {
match Organization::find_by_uuid(&org_id, &conn) {
Some(organization) => Ok(Json(organization.to_json())),
None => err!("Can't find organization details")
@@ -132,7 +128,7 @@ fn get_user_collections(headers: Headers, conn: DbConn) -> JsonResult {
}
#[get("/organizations/<org_id>/collections")]
-fn get_org_collections(org_id: String, headers: Headers, conn: DbConn) -> JsonResult {
+fn get_org_collections(org_id: String, headers: AdminHeaders, conn: DbConn) -> JsonResult {
Ok(Json(json!({
"Data":
Collection::find_by_organization(&org_id, &conn)
@@ -226,7 +222,7 @@ fn post_organization_collection_delete(org_id: String, col_id: String, headers:
}
#[get("/organizations/<org_id>/collections/<coll_id>/details")]
-fn get_org_collection_detail(org_id: String, coll_id: String, headers: Headers, conn: DbConn) -> JsonResult {
+fn get_org_collection_detail(org_id: String, coll_id: String, headers: AdminHeaders, conn: DbConn) -> JsonResult {
match Collection::find_by_uuid_and_user(&coll_id, &headers.user.uuid, &conn) {
None => err!("Collection not found"),
Some(collection) => Ok(Json(collection.to_json()))
@@ -234,7 +230,7 @@ fn get_org_collection_detail(org_id: String, coll_id: String, headers: Headers,
}
#[get("/organizations/<org_id>/collections/<coll_id>/users")]
-fn get_collection_users(org_id: String, coll_id: String, headers: Headers, conn: DbConn) -> JsonResult {
+fn get_collection_users(org_id: String, coll_id: String, headers: AdminHeaders, conn: DbConn) -> JsonResult {
// Get org and collection, check that collection is from org
// Get the users from collection
@@ -278,7 +274,7 @@ fn get_org_details(data: OrgIdData, headers: Headers, conn: DbConn) -> JsonResul
}
#[get("/organizations/<org_id>/users")]
-fn get_org_users(org_id: String, headers: Headers, conn: DbConn) -> JsonResult {
+fn get_org_users(org_id: String, headers: AdminHeaders, conn: DbConn) -> JsonResult {
match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &conn) {
Some(_) => (),
None => err!("User isn't member of organization")
@@ -408,13 +404,7 @@ fn confirm_invite(org_id: String, user_id: String, data: Json<Value>, headers: H
}
#[get("/organizations/<org_id>/users/<user_id>")]
-fn get_user(org_id: String, user_id: String, headers: Headers, conn: DbConn) -> JsonResult {
- let current_user = match UserOrganization::find_by_user_and_org(
- &headers.user.uuid, &org_id, &conn) {
- Some(user) => user,
- None => err!("The current user isn't member of the organization")
- };
-
+fn get_user(org_id: String, user_id: String, headers: AdminHeaders, conn: DbConn) -> JsonResult {
let user = match UserOrganization::find_by_uuid(&user_id, &conn) {
Some(user) => user,
None => err!("The specified user isn't member of the organization")
diff --git a/src/auth.rs b/src/auth.rs
@@ -94,7 +94,7 @@ use rocket::Outcome;
use rocket::request::{self, Request, FromRequest};
use db::DbConn;
-use db::models::{User, Device};
+use db::models::{User, UserOrganization, UserOrgType, Device};
pub struct Headers {
pub host: String,
@@ -155,4 +155,104 @@ impl<'a, 'r> FromRequest<'a, 'r> for Headers {
Outcome::Success(Headers { host, device, user })
}
+}
+
+pub struct OrgHeaders {
+ pub host: String,
+ pub device: Device,
+ pub user: User,
+ pub org_user_type: i32,
+}
+
+impl<'a, 'r> FromRequest<'a, 'r> for OrgHeaders {
+ type Error = &'static str;
+
+ fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
+ match request.guard::<Headers>() {
+ Outcome::Forward(f) => Outcome::Forward(f),
+ Outcome::Failure(f) => Outcome::Failure(f),
+ Outcome::Success(headers) => {
+ // org_id is expected to be the first dynamic param
+ match request.get_param::<String>(0) {
+ Err(_) => err_handler!("Error getting the organization id"),
+ Ok(org_id) => {
+ let conn = match request.guard::<DbConn>() {
+ Outcome::Success(conn) => conn,
+ _ => err_handler!("Error getting DB")
+ };
+
+ let org_user = match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &conn) {
+ Some(user) => user,
+ None => err_handler!("The current user isn't member of the organization")
+ };
+
+ Outcome::Success(Self{
+ host: headers.host,
+ device: headers.device,
+ user: headers.user,
+ org_user_type: org_user.type_,
+ })
+ }
+ }
+ }
+ }
+ }
+}
+
+pub struct AdminHeaders {
+ pub host: String,
+ pub device: Device,
+ pub user: User,
+ pub org_user_type: i32,
+}
+
+impl<'a, 'r> FromRequest<'a, 'r> for AdminHeaders {
+ type Error = &'static str;
+
+ fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
+ match request.guard::<OrgHeaders>() {
+ Outcome::Forward(f) => Outcome::Forward(f),
+ Outcome::Failure(f) => Outcome::Failure(f),
+ Outcome::Success(headers) => {
+ if headers.org_user_type > UserOrgType::Admin as i32 {
+ err_handler!("You need to be Admin or Owner to call this endpoint")
+ } else {
+ Outcome::Success(Self{
+ host: headers.host,
+ device: headers.device,
+ user: headers.user,
+ org_user_type: headers.org_user_type,
+ })
+ }
+ }
+ }
+ }
+}
+
+pub struct OwnerHeaders {
+ pub host: String,
+ pub device: Device,
+ pub user: User,
+}
+
+impl<'a, 'r> FromRequest<'a, 'r> for OwnerHeaders {
+ type Error = &'static str;
+
+ fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
+ match request.guard::<OrgHeaders>() {
+ Outcome::Forward(f) => Outcome::Forward(f),
+ Outcome::Failure(f) => Outcome::Failure(f),
+ Outcome::Success(headers) => {
+ if headers.org_user_type > UserOrgType::Owner as i32 {
+ err_handler!("You need to be Owner to call this endpoint")
+ } else {
+ Outcome::Success(Self{
+ host: headers.host,
+ device: headers.device,
+ user: headers.user,
+ })
+ }
+ }
+ }
+ }
}
\ No newline at end of file