Skip to content

Commit

Permalink
(sudo) add data endpoint and transfer groups
Browse files Browse the repository at this point in the history
  • Loading branch information
fiji-flo committed Oct 22, 2020
1 parent 02e6fd2 commit 9b5cfce
Show file tree
Hide file tree
Showing 12 changed files with 389 additions and 8 deletions.
44 changes: 44 additions & 0 deletions src/api/sudo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ struct LimitOffsetQuery {
s: i64,
}

#[derive(Deserialize)]
pub struct TransferMemberShip {
group_name: String,
old_user_uuid: Uuid,
new_user_uuid: Uuid,
}

fn default_groups_list_size() -> i64 {
20
}
Expand Down Expand Up @@ -288,8 +295,44 @@ async fn delete_user(
.map_err(Into::into)
}

#[guard(Staff, Admin, Medium)]
async fn transfer_membership<T: AsyncCisClientTrait>(
pool: web::Data<Pool>,
transfer: web::Json<TransferMemberShip>,
scope_and_user: ScopeAndUser,
cis_client: web::Data<T>,
) -> Result<HttpResponse, ApiError> {
operations::members::transfer(
&pool,
&scope_and_user,
&transfer.group_name,
&User {
user_uuid: transfer.old_user_uuid,
},
&User {
user_uuid: transfer.new_user_uuid,
},
Arc::clone(&*cis_client),
)
.await
.map(|_| HttpResponse::Ok().json(""))
.map_err(Into::into)
}

#[guard(Staff, Admin, Medium)]
async fn raw_data(
pool: web::Data<Pool>,
scope_and_user: ScopeAndUser,
user_uuid: web::Path<Uuid>,
) -> Result<HttpResponse, ApiError> {
operations::raws::raw_user_data(&pool, &scope_and_user, Some(user_uuid.into_inner()))
.map(|data| HttpResponse::Ok().json(data))
.map_err(Into::into)
}

pub fn sudo_app<T: AsyncCisClientTrait + 'static>() -> impl HttpServiceFactory {
web::scope("/sudo")
.service(web::resource("/transfer").route(web::post().to(transfer_membership::<T>)))
.service(web::resource("/groups/reserve/{group_name}").route(web::post().to(reserve_group)))
.service(
web::resource("/groups/inactive/{group_name}")
Expand All @@ -304,6 +347,7 @@ pub fn sudo_app<T: AsyncCisClientTrait + 'static>() -> impl HttpServiceFactory {
.route(web::delete().to(remove_member::<T>)),
)
.service(web::resource("/member/{group_name}").route(web::post().to(add_member::<T>)))
.service(web::resource("/user/data/{user_uuid}").route(web::get().to(raw_data)))
.service(web::resource("/user/uuids/staff").route(web::get().to(all_staff_uuids)))
.service(web::resource("/user/uuids/members").route(web::get().to(all_member_uuids)))
.service(
Expand Down
40 changes: 40 additions & 0 deletions src/db/internal/member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ scoped_members_and_host_for!(users_public, hosts_public, public_scoped_members_a

membership_and_scoped_host_for!(hosts_staff, membership_and_staff_host);
membership_and_scoped_host_for!(hosts_ndaed, membership_and_ndaed_host);
membership_and_scoped_host_for!(hosts_vouched, membership_and_vouched_host);
membership_and_scoped_host_for!(hosts_authenticated, membership_and_authenticated_host);

pub fn add_member_role(
host_uuid: &Uuid,
Expand Down Expand Up @@ -430,6 +432,44 @@ pub fn add_to_group(
.map_err(Into::into)
}

pub fn transfer_membership(
connection: &PgConnection,
group_name: &str,
host: &User,
old_member: &User,
new_member: &User,
) -> Result<(), Error> {
let group = internal::group::get_group(connection, group_name)?;
let log_ctx_old = LogContext::with(group.id, host.user_uuid).with_user(old_member.user_uuid);
let log_ctx_new = LogContext::with(group.id, host.user_uuid).with_user(new_member.user_uuid);
diesel::update(
schema::memberships::table.filter(
schema::memberships::group_id
.eq(group.id)
.and(schema::memberships::user_uuid.eq(old_member.user_uuid)),
),
)
.set(schema::memberships::user_uuid.eq(new_member.user_uuid))
.execute(connection)
.map(|_| {
internal::log::db_log(
connection,
&log_ctx_old,
LogTargetType::Membership,
LogOperationType::Updated,
log_comment_body(&format!("moved to {}", new_member.user_uuid)),
);
internal::log::db_log(
connection,
&log_ctx_new,
LogTargetType::Membership,
LogOperationType::Updated,
log_comment_body(&format!("moved from {}", old_member.user_uuid)),
);
})
.map_err(Into::into)
}

pub fn renew(
host_uuid: &Uuid,
connection: &PgConnection,
Expand Down
1 change: 1 addition & 0 deletions src/db/internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod group;
pub mod invitation;
pub mod log;
pub mod member;
pub mod raw;
pub mod request;
pub mod terms;
pub mod user;
67 changes: 67 additions & 0 deletions src/db/internal/raw.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use crate::db::logs::Log;
use crate::db::model::*;
use crate::db::schema;
use crate::db::users::UserProfile;
use crate::db::users::UserProfileValue;
use diesel::prelude::*;
use failure::Error;
use std::convert::TryInto;
use uuid::Uuid;

pub fn raw_memberships_for_user(
connection: &PgConnection,
user_uuid: &Uuid,
) -> Result<Vec<Membership>, Error> {
use schema::memberships as m;

m::table
.filter(m::user_uuid.eq(user_uuid))
.get_results(connection)
.map_err(Into::into)
}

pub fn raw_invitations_for_user(
connection: &PgConnection,
user_uuid: &Uuid,
) -> Result<Vec<Invitation>, Error> {
use schema::invitations as i;

i::table
.filter(i::user_uuid.eq(user_uuid).or(i::added_by.eq(user_uuid)))
.get_results(connection)
.map_err(Into::into)
}

pub fn raw_requests_for_user(
connection: &PgConnection,
user_uuid: &Uuid,
) -> Result<Vec<Request>, Error> {
use schema::requests as r;

r::table
.filter(r::user_uuid.eq(user_uuid))
.get_results(connection)
.map_err(Into::into)
}

pub fn raw_user_for_user(
connection: &PgConnection,
user_uuid: &Uuid,
) -> Result<UserProfile, Error> {
use schema::profiles as p;

p::table
.filter(p::user_uuid.eq(user_uuid))
.get_result::<UserProfileValue>(connection)
.map_err(Error::from)
.and_then(TryInto::try_into)
}

pub fn raw_logs_for_user(connection: &PgConnection, user_uuid: &Uuid) -> Result<Vec<Log>, Error> {
use schema::logs as l;

l::table
.filter(l::user_uuid.eq(user_uuid).or(l::host_uuid.eq(user_uuid)))
.get_results(connection)
.map_err(Into::into)
}
10 changes: 7 additions & 3 deletions src/db/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub struct Role {
pub permissions: Vec<PermissionType>,
}

#[derive(Queryable, Associations, PartialEq, Debug, Insertable, AsChangeset)]
#[derive(Serialize, Queryable, Associations, PartialEq, Debug, Insertable, AsChangeset)]
#[belongs_to(Group)]
#[primary_key(group_id, user_uuid)]
pub struct Membership {
Expand All @@ -49,7 +49,9 @@ pub struct Membership {
pub added_ts: NaiveDateTime,
}

#[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Insertable, AsChangeset)]
#[derive(
Serialize, Identifiable, Queryable, Associations, PartialEq, Debug, Insertable, AsChangeset,
)]
#[belongs_to(Group)]
#[primary_key(group_id, user_uuid)]
pub struct Invitation {
Expand All @@ -68,7 +70,9 @@ pub struct Invitationtext {
pub body: String,
}

#[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Insertable, AsChangeset)]
#[derive(
Serialize, Identifiable, Queryable, Associations, PartialEq, Debug, Insertable, AsChangeset,
)]
#[belongs_to(Group)]
#[primary_key(group_id, user_uuid)]
pub struct Request {
Expand Down
43 changes: 42 additions & 1 deletion src/db/operations/members.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::mail::manager::send_emails;
use crate::mail::manager::subscribe_nda;
use crate::mail::manager::unsubscribe_nda;
use crate::mail::templates::Template;
use crate::rules::engine::ADMIN_CAN_ADD_MEMBER;
use crate::rules::engine::ONLY_ADMINS;
use crate::rules::engine::REMOVE_MEMBER;
use crate::rules::engine::RENEW_MEMBER;
Expand Down Expand Up @@ -52,6 +53,14 @@ pub fn membership_and_scoped_host(
Trust::Ndaed => {
internal::member::membership_and_ndaed_host(&connection, group.id, user.user_uuid)
}
Trust::Vouched => {
internal::member::membership_and_vouched_host(&connection, group.id, user.user_uuid)
}
Trust::Authenticated => internal::member::membership_and_authenticated_host(
&connection,
group.id,
user.user_uuid,
),
_ => Ok(None),
}
}
Expand Down Expand Up @@ -141,6 +150,37 @@ fn db_leave(
)
}

pub async fn transfer(
pool: &Pool,
scope_and_user: &ScopeAndUser,
group_name: &str,
old_user: &User,
new_user: &User,
cis_client: Arc<impl AsyncCisClientTrait>,
) -> Result<(), Error> {
let connection = pool.get()?;
let host = internal::user::user_by_id(&connection, &scope_and_user.user_id)?;
ADMIN_CAN_ADD_MEMBER.run(&RuleContext::minimal_with_member_uuid(
&pool.clone(),
scope_and_user,
&group_name,
&host.user_uuid,
&new_user.user_uuid,
))?;
internal::member::transfer_membership(&connection, &group_name, &host, &old_user, &new_user)?;
if group_name == "nda" {
let old_user_profile =
internal::user::slim_user_profile_by_uuid(&connection, &old_user.user_uuid)?;
let new_user_profile =
internal::user::slim_user_profile_by_uuid(&connection, &old_user.user_uuid)?;
unsubscribe_nda(&old_user_profile.email);
subscribe_nda(&new_user_profile.email);
}
drop(connection);
send_groups_to_cis(pool, Arc::clone(&cis_client), &old_user.user_uuid).await?;
send_groups_to_cis(pool, cis_client, &new_user.user_uuid).await
}

pub async fn add(
pool: &Pool,
scope_and_user: &ScopeAndUser,
Expand All @@ -150,11 +190,12 @@ pub async fn add(
expiration: Option<i32>,
cis_client: Arc<impl AsyncCisClientTrait>,
) -> Result<(), Error> {
ONLY_ADMINS.run(&RuleContext::minimal(
ADMIN_CAN_ADD_MEMBER.run(&RuleContext::minimal_with_member_uuid(
&pool.clone(),
scope_and_user,
&group_name,
&host.user_uuid,
&user.user_uuid,
))?;
let connection = pool.get()?;
let expiration = if expiration.is_none() {
Expand Down
1 change: 1 addition & 0 deletions src/db/operations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod invitations;
pub mod logs;
pub mod members;
pub mod models;
pub mod raws;
pub mod requests;
pub mod terms;
pub mod users;
14 changes: 14 additions & 0 deletions src/db/operations/models.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use crate::db::logs::Log;
use crate::db::model::Group;
use crate::db::model::GroupsList;
use crate::db::model::Invitation;
use crate::db::model::Membership;
use crate::db::model::Request;
use crate::db::types::*;
use crate::db::users::UserProfile;
use crate::error::PacksError;
use crate::user::User;
use crate::utils::maybe_to_utc;
Expand Down Expand Up @@ -501,6 +506,15 @@ pub struct InvitationEmail {
pub body: Option<String>,
}

#[derive(Serialize)]
pub struct RawUserData {
pub user_profile: UserProfile,
pub memberships: Vec<Membership>,
pub invitations: Vec<Invitation>,
pub requests: Vec<Request>,
pub logs: Vec<Log>,
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
33 changes: 33 additions & 0 deletions src/db/operations/raws.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::db::internal;
use crate::db::internal::raw::*;
use crate::db::operations::models::RawUserData;
use crate::db::Pool;
use dino_park_gate::scope::ScopeAndUser;
use failure::Error;
use uuid::Uuid;

pub fn raw_user_data(
pool: &Pool,
scope_and_user: &ScopeAndUser,
user_uuid: Option<Uuid>,
) -> Result<RawUserData, Error> {
let connection = pool.get()?;
let user_uuid = match user_uuid {
Some(user_uuid) => user_uuid,
_ => internal::user::user_by_id(&connection, &scope_and_user.user_id)?.user_uuid,
};

let user_profile = raw_user_for_user(&connection, &user_uuid)?;
let memberships = raw_memberships_for_user(&connection, &user_uuid)?;
let invitations = raw_invitations_for_user(&connection, &user_uuid)?;
let requests = raw_requests_for_user(&connection, &user_uuid)?;
let logs = raw_logs_for_user(&connection, &user_uuid)?;

Ok(RawUserData {
user_profile,
memberships,
invitations,
requests,
logs,
})
}
Loading

0 comments on commit 9b5cfce

Please sign in to comment.