Merge pull request #1493 from jjlin/send
Add support for the Disable Send policy
This commit is contained in:
commit
b987ba506d
|
@ -285,19 +285,10 @@ fn enforce_personal_ownership_policy(
|
||||||
) -> EmptyResult {
|
) -> EmptyResult {
|
||||||
if data.OrganizationId.is_none() {
|
if data.OrganizationId.is_none() {
|
||||||
let user_uuid = &headers.user.uuid;
|
let user_uuid = &headers.user.uuid;
|
||||||
for policy in OrgPolicy::find_by_user(user_uuid, conn) {
|
let policy_type = OrgPolicyType::PersonalOwnership;
|
||||||
if policy.enabled && policy.has_type(OrgPolicyType::PersonalOwnership) {
|
if OrgPolicy::is_applicable_to_user(user_uuid, policy_type, conn) {
|
||||||
let org_uuid = &policy.org_uuid;
|
err!("Due to an Enterprise Policy, you are restricted from \
|
||||||
match UserOrganization::find_by_user_and_org(user_uuid, org_uuid, conn) {
|
saving items to your personal vault.")
|
||||||
Some(user) =>
|
|
||||||
if user.atype < UserOrgType::Admin &&
|
|
||||||
user.has_status(UserOrgStatus::Confirmed) {
|
|
||||||
err!("Due to an Enterprise Policy, you are restricted \
|
|
||||||
from saving items to your personal vault.")
|
|
||||||
},
|
|
||||||
None => err!("Error looking up user type"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -43,6 +43,20 @@ pub struct SendData {
|
||||||
pub File: Option<Value>,
|
pub File: Option<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enforces the `Disable Send` policy. A non-owner/admin user belonging to
|
||||||
|
/// an org with this policy enabled isn't allowed to create new Sends or
|
||||||
|
/// modify existing ones, but is allowed to delete them.
|
||||||
|
///
|
||||||
|
/// Ref: https://bitwarden.com/help/article/policies/#disable-send
|
||||||
|
fn enforce_disable_send_policy(headers: &Headers,conn: &DbConn) -> EmptyResult {
|
||||||
|
let user_uuid = &headers.user.uuid;
|
||||||
|
let policy_type = OrgPolicyType::DisableSend;
|
||||||
|
if OrgPolicy::is_applicable_to_user(user_uuid, policy_type, conn) {
|
||||||
|
err!("Due to an Enterprise Policy, you are only able to delete an existing Send.")
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn create_send(data: SendData, user_uuid: String) -> ApiResult<Send> {
|
fn create_send(data: SendData, user_uuid: String) -> ApiResult<Send> {
|
||||||
let data_val = if data.Type == SendType::Text as i32 {
|
let data_val = if data.Type == SendType::Text as i32 {
|
||||||
data.Text
|
data.Text
|
||||||
|
@ -80,6 +94,8 @@ fn create_send(data: SendData, user_uuid: String) -> ApiResult<Send> {
|
||||||
|
|
||||||
#[post("/sends", data = "<data>")]
|
#[post("/sends", data = "<data>")]
|
||||||
fn post_send(data: JsonUpcase<SendData>, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult {
|
fn post_send(data: JsonUpcase<SendData>, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult {
|
||||||
|
enforce_disable_send_policy(&headers, &conn)?;
|
||||||
|
|
||||||
let data: SendData = data.into_inner().data;
|
let data: SendData = data.into_inner().data;
|
||||||
|
|
||||||
if data.Type == SendType::File as i32 {
|
if data.Type == SendType::File as i32 {
|
||||||
|
@ -95,6 +111,8 @@ fn post_send(data: JsonUpcase<SendData>, headers: Headers, conn: DbConn, nt: Not
|
||||||
|
|
||||||
#[post("/sends/file", format = "multipart/form-data", data = "<data>")]
|
#[post("/sends/file", format = "multipart/form-data", data = "<data>")]
|
||||||
fn post_send_file(data: Data, content_type: &ContentType, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult {
|
fn post_send_file(data: Data, content_type: &ContentType, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult {
|
||||||
|
enforce_disable_send_policy(&headers, &conn)?;
|
||||||
|
|
||||||
let boundary = content_type.params().next().expect("No boundary provided").1;
|
let boundary = content_type.params().next().expect("No boundary provided").1;
|
||||||
|
|
||||||
let mut mpart = Multipart::with_body(data.open(), boundary);
|
let mut mpart = Multipart::with_body(data.open(), boundary);
|
||||||
|
@ -288,6 +306,8 @@ fn post_access_file(
|
||||||
|
|
||||||
#[put("/sends/<id>", data = "<data>")]
|
#[put("/sends/<id>", data = "<data>")]
|
||||||
fn put_send(id: String, data: JsonUpcase<SendData>, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult {
|
fn put_send(id: String, data: JsonUpcase<SendData>, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult {
|
||||||
|
enforce_disable_send_policy(&headers, &conn)?;
|
||||||
|
|
||||||
let data: SendData = data.into_inner().data;
|
let data: SendData = data.into_inner().data;
|
||||||
|
|
||||||
let mut send = match Send::find_by_uuid(&id, &conn) {
|
let mut send = match Send::find_by_uuid(&id, &conn) {
|
||||||
|
@ -366,6 +386,8 @@ fn delete_send(id: String, headers: Headers, conn: DbConn, nt: Notify) -> EmptyR
|
||||||
|
|
||||||
#[put("/sends/<id>/remove-password")]
|
#[put("/sends/<id>/remove-password")]
|
||||||
fn put_remove_password(id: String, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult {
|
fn put_remove_password(id: String, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult {
|
||||||
|
enforce_disable_send_policy(&headers, &conn)?;
|
||||||
|
|
||||||
let mut send = match Send::find_by_uuid(&id, &conn) {
|
let mut send = match Send::find_by_uuid(&id, &conn) {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => err!("Send not found"),
|
None => err!("Send not found"),
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::api::EmptyResult;
|
||||||
use crate::db::DbConn;
|
use crate::db::DbConn;
|
||||||
use crate::error::MapResult;
|
use crate::error::MapResult;
|
||||||
|
|
||||||
use super::{Organization, UserOrgStatus};
|
use super::{Organization, UserOrganization, UserOrgStatus, UserOrgType};
|
||||||
|
|
||||||
db_object! {
|
db_object! {
|
||||||
#[derive(Identifiable, Queryable, Insertable, Associations, AsChangeset)]
|
#[derive(Identifiable, Queryable, Insertable, Associations, AsChangeset)]
|
||||||
|
@ -20,7 +20,7 @@ db_object! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[derive(Copy, Clone)]
|
||||||
#[derive(num_derive::FromPrimitive)]
|
#[derive(num_derive::FromPrimitive)]
|
||||||
pub enum OrgPolicyType {
|
pub enum OrgPolicyType {
|
||||||
TwoFactorAuthentication = 0,
|
TwoFactorAuthentication = 0,
|
||||||
|
@ -29,6 +29,7 @@ pub enum OrgPolicyType {
|
||||||
// SingleOrg = 3, // Not currently supported.
|
// SingleOrg = 3, // Not currently supported.
|
||||||
// RequireSso = 4, // Not currently supported.
|
// RequireSso = 4, // Not currently supported.
|
||||||
PersonalOwnership = 5,
|
PersonalOwnership = 5,
|
||||||
|
DisableSend = 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Local methods
|
/// Local methods
|
||||||
|
@ -170,6 +171,23 @@ impl OrgPolicy {
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the user belongs to an org that has enabled the specified policy type,
|
||||||
|
/// and the user is not an owner or admin of that org. This is only useful for checking
|
||||||
|
/// applicability of policy types that have these particular semantics.
|
||||||
|
pub fn is_applicable_to_user(user_uuid: &str, policy_type: OrgPolicyType, conn: &DbConn) -> bool {
|
||||||
|
for policy in OrgPolicy::find_by_user(user_uuid, conn) { // Returns confirmed users only.
|
||||||
|
if policy.enabled && policy.has_type(policy_type) {
|
||||||
|
let org_uuid = &policy.org_uuid;
|
||||||
|
if let Some(user) = UserOrganization::find_by_user_and_org(user_uuid, org_uuid, conn) {
|
||||||
|
if user.atype < UserOrgType::Admin {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/*pub fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
|
/*pub fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
|
||||||
db_run! { conn: {
|
db_run! { conn: {
|
||||||
diesel::delete(twofactor::table.filter(twofactor::user_uuid.eq(user_uuid)))
|
diesel::delete(twofactor::table.filter(twofactor::user_uuid.eq(user_uuid)))
|
||||||
|
|
Loading…
Reference in New Issue