Skip to content

Commit

Permalink
add user permissions flags in settings
Browse files Browse the repository at this point in the history
  • Loading branch information
hgzimmerman committed Nov 18, 2019
1 parent 5a01d97 commit 6182f8e
Show file tree
Hide file tree
Showing 13 changed files with 432 additions and 130 deletions.
2 changes: 1 addition & 1 deletion backend/db/src/bucket_user_relation/db_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ pub struct BucketUserPermissionsChangeset {
pub grant_permissions_permission: Option<bool>,
}

// TODO, maybe remove this structure.

/// Structure that just contains the permissions for a user-bucket relation.
#[derive(Clone, Copy, Queryable, Debug, Serialize, Deserialize)]
Expand All @@ -89,3 +88,4 @@ pub struct BucketUserPermissions {
/// Can the user kick other users.
pub kick_permission: bool,
}

19 changes: 19 additions & 0 deletions backend/db/src/bucket_user_relation/fake_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,23 @@ impl BucketUserRelationRepository for Arc<Mutex<FakeDatabase>> {

Ok(users)
}

fn get_permissions_all_users_in_bucket(&self, bucket_uuid: Uuid) -> Result<Vec<(BucketUserPermissions, User)>, Error> {
let db = self.lock().unwrap();
let users = self.get_users_in_bucket(bucket_uuid)?;

// unlock
drop(db);

let permissions: Vec<BucketUserPermissions> = users
.iter()
.map(|user| {
self.get_permissions(user.uuid, bucket_uuid)
})
.collect::<Result<Vec<BucketUserPermissions>, Error>>()?;

Ok(permissions.into_iter().zip(users).collect())


}
}
3 changes: 3 additions & 0 deletions backend/db/src/bucket_user_relation/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,7 @@ pub trait BucketUserRelationRepository {
fn get_buckets_user_is_a_part_of(&self, user_uuid: Uuid) -> QueryResult<Vec<Bucket>>;
/// Gets the users in a given bucket.
fn get_users_in_bucket(&self, bucket_uuid: Uuid) -> QueryResult<Vec<User>>;

/// Gets the users in a given bucket, as well as their relation
fn get_permissions_all_users_in_bucket(&self, bucket_uuid: Uuid) -> QueryResult<Vec<(BucketUserPermissions, User)>>;
}
19 changes: 19 additions & 0 deletions backend/db/src/bucket_user_relation/pg_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,23 @@ where
.select(bq_user::all_columns)
.get_results(self.as_conn())
}

fn get_permissions_all_users_in_bucket(&self, bucket_uuid: Uuid) -> Result<Vec<(BucketUserPermissions, User)>, Error> {
bucket_user_relation::table
.filter(
bucket_user_relation::bucket_uuid.eq(bucket_uuid)
)
.inner_join(bq_user::table)
.order_by(bucket_user_relation::created_at)
.select((
(
bucket_user_relation::set_public_permission,
bucket_user_relation::set_drawing_permission,
bucket_user_relation::set_exclusive_permission,
bucket_user_relation::kick_permission,
bucket_user_relation::grant_permissions_permission,
)
, bq_user::all_columns))
.get_results(self.as_conn())
}
}
16 changes: 13 additions & 3 deletions backend/db/src/conversions/bucket_user_relation.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! Bucket-User relation conversions
use crate::bucket_user_relation::db_types::{
BucketUserPermissionsChangeset, BucketUserRelation, NewBucketUserRelation,
};
use crate::bucket_user_relation::db_types::{BucketUserPermissionsChangeset, BucketUserRelation, NewBucketUserRelation, BucketUserPermissions};
use wire;

impl Into<wire::bucket_user_relation::BucketUserRelation> for BucketUserRelation {
Expand Down Expand Up @@ -96,3 +94,15 @@ impl From<wire::bucket_user_relation::BucketUserPermissionsChangeset>
}
}
}

impl Into<wire::bucket_user_relation::BucketUserPermissions> for BucketUserPermissions {
fn into(self) -> wire::bucket_user_relation::BucketUserPermissions {
wire::bucket_user_relation::BucketUserPermissions {
set_public_permission: self.set_public_permission,
set_drawing_permission: self.set_drawing_permission,
set_exclusive_permission: self.set_exclusive_permission,
grant_permissions_permission: self.grant_permissions_permission,
kick_permission: self.kick_permission
}
}
}
29 changes: 29 additions & 0 deletions backend/server/src/api/bucket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use warp::{filters::BoxedFilter, path, Filter, Reply};
pub const BUCKET_PATH: &str = "bucket";

use wire::bucket::{ChangeBucketFlagsRequest, UserUuidQueryParam, SetPermissionsRequest, NewBucketRequest};
use wire::bucket_user_relation::UserAndPermissions;

pub fn bucket_api(state: &State) -> BoxedFilter<(impl Reply,)> {
//impl Filter<Extract=(impl Reply,), Error=Rejection> + Clone{
Expand Down Expand Up @@ -121,6 +122,14 @@ pub fn bucket_api(state: &State) -> BoxedFilter<(impl Reply,)> {
.map(get_users_in_bucket_handler)
.and_then(json_or_reject);


let get_users_and_permissions_in_bucket = path!(Uuid / "all_user_permissions")
.and(warp::path::end())
.and(warp::get2())
.and(state.db())
.map(get_all_user_permissions_for_bucket_handler)
.and_then(json_or_reject);

path(BUCKET_PATH)
.and(
create_bucket
Expand All @@ -133,6 +142,7 @@ pub fn bucket_api(state: &State) -> BoxedFilter<(impl Reply,)> {
.or(set_permissions)
.or(set_bucket_flags)
.or(get_users_in_bucket)
.or(get_users_and_permissions_in_bucket)
.or(get_bucket),
)
.boxed()
Expand Down Expand Up @@ -289,6 +299,25 @@ fn get_users_in_bucket_handler(
conn.get_users_in_bucket(bucket_uuid).map_err(Error::from)
}

fn get_all_user_permissions_for_bucket_handler(
bucket_uuid: Uuid,
conn: BoxedRepository
) -> Result<Vec<UserAndPermissions>, Error> {
info!("get_all_user_permissions_for_bucket_handler");
conn.get_permissions_all_users_in_bucket(bucket_uuid)
.map(|list| {
list.into_iter()
.map(|(permissions, user)|{
UserAndPermissions {
user: user.into(),
permissions: permissions.into()
}
})
.collect()
} )
.map_err(Error::from)
}

fn set_permissions_handler(
bucket_uuid: Uuid,
permissions_request: SetPermissionsRequest,
Expand Down
9 changes: 9 additions & 0 deletions wire/src/bucket_user_relation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use serde::{Serialize, Deserialize};
use uuid::Uuid;
use chrono::NaiveDateTime;
use crate::user::User;

#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct BucketUserRelation {
Expand Down Expand Up @@ -74,3 +75,11 @@ pub struct BucketUserPermissions {
/// Can the user kick other users.
pub kick_permission: bool,
}

#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct UserAndPermissions {
/// The user
pub user: User,
/// The associated permissions
pub permissions: BucketUserPermissions
}
7 changes: 6 additions & 1 deletion yew_frontend/app_style.sass
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,9 @@ html
margin: 8px

.margin_20
margin: 20px
margin: 20px

.horiz_flex_wrap
display: flex
flex-direction: row
flex-wrap: wrap
48 changes: 25 additions & 23 deletions yew_frontend/src/pages/bucket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::AppRoute;
use yew_router::agent::RouteRequest;
use wire::bucket_user_relation::BucketUserPermissions;

// TODO break this component across a data-wiring, view and update modules. @ 500 lines, this is getting hard to follow.
pub struct BucketPage {
props: Props,
link: ComponentLink<BucketPage>,
Expand Down Expand Up @@ -139,7 +140,6 @@ impl Component for BucketPage {
}
Msg::DiscardQuestion => {
// The question won't be able to be drawn from the bucket again.

let mut should_clear_active_question = false;

let retval = if let FetchState::Success(Some(question)) = &self.active_question {
Expand Down Expand Up @@ -241,32 +241,20 @@ impl Component for BucketPage {
}

fn view(&self) -> Html<Self> {
let modal = if let FetchState::Success(bucket) = &self.bucket {
if self.props.is_settings_open {
html!{
<SettingsModal bucket= bucket.clone() />
}
} else {
html!{}
}
} else {
html!{}
};

html! {
<>
{modal}
<div class= "has-background-primary full_height_scrollable">
<div class = "full_width">
<div class = "columns is-centered no_margin">
<div class="column is-two-thirds-tablet is-half-desktop is-centered">
{self.render_title()}
{self.render_q_and_a_card()}
{self.render_new_question_card()}
{self.modal()}
<div class= "has-background-primary full_height_scrollable">
<div class = "full_width">
<div class = "columns is-centered no_margin">
<div class="column is-two-thirds-tablet is-half-desktop is-centered">
{self.render_title()}
{self.render_q_and_a_card()}
{self.render_new_question_card()}
</div>
</div>
</div>
</div>
</div>
</>
}
}
Expand All @@ -286,6 +274,20 @@ impl BucketPage {
}
}

fn modal(&self) -> Html<Self> {
if let (FetchState::Success(bucket), FetchState::Success(permissions) )= (&self.bucket, &self.permissions) {
if self.props.is_settings_open {
return html!{
<SettingsModal bucket= bucket.clone() permissions = permissions.clone()/>
}
} else {
return html!{}
}
} else {
return html!{}
}
}

fn render_title(&self) -> Html<Self> {
let settings_link = if self.should_show_settings() {
html! {
Expand All @@ -304,7 +306,7 @@ impl BucketPage {

let num_questions_in_bucket = if let FetchState::Success(count) = self.questions_in_bucket_count {
html! {
<span class= "" style = "padding-top: .75rem; padding-bottom: .75rem; padding-right: .25rem"> // TODO, find a better class for this
<span class= "" style = "padding-top: .75rem; padding-bottom: .75rem; padding-right: .25rem">
{format!("Q: {}", count)}
</span>
}
Expand Down
Loading

0 comments on commit 6182f8e

Please sign in to comment.