Spiegel von
https://github.com/dani-garcia/vaultwarden.git
synchronisiert 2025-01-07 11:45:40 +01:00
use newtype pattern for org_id
Dieser Commit ist enthalten in:
Ursprung
0b9e3bafd3
Commit
40a788084b
24 geänderte Dateien mit 557 neuen und 326 gelöschten Zeilen
12
Cargo.lock
generiert
12
Cargo.lock
generiert
|
@ -778,6 +778,17 @@ dependencies = [
|
|||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel-derive-newtype"
|
||||
version = "2.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5adf688c584fe33726ce0e2898f608a2a92578ac94a4a92fcecf73214fe0716"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_derives"
|
||||
version = "2.2.3"
|
||||
|
@ -3960,6 +3971,7 @@ dependencies = [
|
|||
"data-encoding",
|
||||
"data-url",
|
||||
"diesel",
|
||||
"diesel-derive-newtype",
|
||||
"diesel_logger",
|
||||
"diesel_migrations",
|
||||
"dotenvy",
|
||||
|
|
|
@ -77,6 +77,7 @@ serde_json = "1.0.133"
|
|||
diesel = { version = "2.2.6", features = ["chrono", "r2d2", "numeric"] }
|
||||
diesel_migrations = "2.2.0"
|
||||
diesel_logger = { version = "0.4.0", optional = true }
|
||||
diesel-derive-newtype = "2.1.2"
|
||||
|
||||
# Bundled/Static SQLite
|
||||
libsqlite3-sys = { version = "0.30.1", features = ["bundled"], optional = true }
|
||||
|
|
|
@ -488,7 +488,7 @@ async fn resend_user_invite(uuid: &str, _token: AdminToken, mut conn: DbConn) ->
|
|||
struct MembershipTypeData {
|
||||
user_type: NumberOrString,
|
||||
user_uuid: String,
|
||||
org_uuid: String,
|
||||
org_uuid: OrganizationId,
|
||||
}
|
||||
|
||||
#[post("/users/org_type", data = "<data>")]
|
||||
|
@ -570,9 +570,9 @@ async fn organizations_overview(_token: AdminToken, mut conn: DbConn) -> ApiResu
|
|||
Ok(Html(text))
|
||||
}
|
||||
|
||||
#[post("/organizations/<uuid>/delete")]
|
||||
async fn delete_organization(uuid: &str, _token: AdminToken, mut conn: DbConn) -> EmptyResult {
|
||||
let org = Organization::find_by_uuid(uuid, &mut conn).await.map_res("Organization doesn't exist")?;
|
||||
#[post("/organizations/<org_uuid>/delete")]
|
||||
async fn delete_organization(org_uuid: OrganizationId, _token: AdminToken, mut conn: DbConn) -> EmptyResult {
|
||||
let org = Organization::find_by_uuid(&org_uuid, &mut conn).await.map_res("Organization doesn't exist")?;
|
||||
org.delete(&mut conn).await
|
||||
}
|
||||
|
||||
|
|
|
@ -459,7 +459,7 @@ struct UpdateEmergencyAccessData {
|
|||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct UpdateResetPasswordData {
|
||||
organization_id: String,
|
||||
organization_id: OrganizationId,
|
||||
reset_password_key: String,
|
||||
}
|
||||
|
||||
|
@ -516,9 +516,10 @@ fn validate_keydata(
|
|||
}
|
||||
|
||||
// Check that we're correctly rotating all the user's reset password keys
|
||||
let existing_reset_password_ids = existing_memberships.iter().map(|m| m.org_uuid.as_str()).collect::<HashSet<_>>();
|
||||
let existing_reset_password_ids =
|
||||
existing_memberships.iter().map(|m| &m.org_uuid).collect::<HashSet<&OrganizationId>>();
|
||||
let provided_reset_password_ids =
|
||||
data.reset_password_keys.iter().map(|rp| rp.organization_id.as_str()).collect::<HashSet<_>>();
|
||||
data.reset_password_keys.iter().map(|rp| &rp.organization_id).collect::<HashSet<&OrganizationId>>();
|
||||
if !provided_reset_password_ids.is_superset(&existing_reset_password_ids) {
|
||||
err!("All existing reset password keys must be included in the rotation")
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ pub struct CipherData {
|
|||
pub folder_id: Option<String>,
|
||||
// TODO: Some of these might appear all the time, no need for Option
|
||||
#[serde(alias = "organizationID")]
|
||||
pub organization_id: Option<String>,
|
||||
pub organization_id: Option<OrganizationId>,
|
||||
|
||||
key: Option<String>,
|
||||
|
||||
|
@ -1572,14 +1572,14 @@ async fn move_cipher_selected_put(
|
|||
}
|
||||
|
||||
#[derive(FromForm)]
|
||||
struct OrganizationId {
|
||||
struct OrganizationIdData {
|
||||
#[field(name = "organizationId")]
|
||||
org_id: String,
|
||||
org_id: OrganizationId,
|
||||
}
|
||||
|
||||
#[post("/ciphers/purge?<organization..>", data = "<data>")]
|
||||
async fn delete_all(
|
||||
organization: Option<OrganizationId>,
|
||||
organization: Option<OrganizationIdData>,
|
||||
data: Json<PasswordOrOtpData>,
|
||||
headers: Headers,
|
||||
mut conn: DbConn,
|
||||
|
@ -1835,10 +1835,10 @@ pub struct CipherSyncData {
|
|||
pub cipher_folders: HashMap<String, String>,
|
||||
pub cipher_favorites: HashSet<String>,
|
||||
pub cipher_collections: HashMap<String, Vec<String>>,
|
||||
pub members: HashMap<String, Membership>,
|
||||
pub members: HashMap<OrganizationId, Membership>,
|
||||
pub user_collections: HashMap<String, CollectionUser>,
|
||||
pub user_collections_groups: HashMap<String, CollectionGroup>,
|
||||
pub user_group_full_access_for_organizations: HashSet<String>,
|
||||
pub user_group_full_access_for_organizations: HashSet<OrganizationId>,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
|
@ -1885,7 +1885,7 @@ impl CipherSyncData {
|
|||
}
|
||||
|
||||
// Generate a HashMap with the Organization UUID as key and the Membership record
|
||||
let members: HashMap<String, Membership> =
|
||||
let members: HashMap<OrganizationId, Membership> =
|
||||
Membership::find_by_user(user_uuid, conn).await.into_iter().map(|m| (m.org_uuid.clone(), m)).collect();
|
||||
|
||||
// Generate a HashMap with the User_Collections UUID as key and the CollectionUser record
|
||||
|
@ -1907,7 +1907,7 @@ impl CipherSyncData {
|
|||
};
|
||||
|
||||
// Get all organizations that the given user has full access to via group assignment
|
||||
let user_group_full_access_for_organizations: HashSet<String> = if CONFIG.org_groups_enabled() {
|
||||
let user_group_full_access_for_organizations: HashSet<OrganizationId> = if CONFIG.org_groups_enabled() {
|
||||
Group::get_orgs_by_user_with_full_access(user_uuid, conn).await.into_iter().collect()
|
||||
} else {
|
||||
HashSet::new()
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
api::{EmptyResult, JsonResult},
|
||||
auth::{AdminHeaders, Headers},
|
||||
db::{
|
||||
models::{Cipher, Event, Membership},
|
||||
models::{Cipher, Event, Membership, OrganizationId},
|
||||
DbConn, DbPool,
|
||||
},
|
||||
util::parse_date,
|
||||
|
@ -153,7 +153,7 @@ struct EventCollection {
|
|||
|
||||
// Optional
|
||||
cipher_id: Option<String>,
|
||||
organization_id: Option<String>,
|
||||
organization_id: Option<OrganizationId>,
|
||||
}
|
||||
|
||||
// Upstream:
|
||||
|
@ -261,7 +261,7 @@ async fn _log_user_event(
|
|||
pub async fn log_event(
|
||||
event_type: i32,
|
||||
source_uuid: &str,
|
||||
org_uuid: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
act_user_uuid: &str,
|
||||
device_type: i32,
|
||||
ip: &IpAddr,
|
||||
|
@ -277,7 +277,7 @@ pub async fn log_event(
|
|||
async fn _log_event(
|
||||
event_type: i32,
|
||||
source_uuid: &str,
|
||||
org_uuid: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
act_user_uuid: &str,
|
||||
device_type: i32,
|
||||
event_date: Option<NaiveDateTime>,
|
||||
|
@ -313,7 +313,7 @@ async fn _log_event(
|
|||
_ => {}
|
||||
}
|
||||
|
||||
event.org_uuid = Some(String::from(org_uuid));
|
||||
event.org_uuid = Some(org_uuid.clone());
|
||||
event.act_user_uuid = Some(String::from(act_user_uuid));
|
||||
event.device_type = Some(device_type);
|
||||
event.ip_address = Some(ip.to_string());
|
||||
|
|
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
|
@ -179,7 +179,7 @@ async fn ldap_import(data: Json<OrgImportData>, token: PublicToken, mut conn: Db
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub struct PublicToken(String);
|
||||
pub struct PublicToken(OrganizationId);
|
||||
|
||||
#[rocket::async_trait]
|
||||
impl<'r> FromRequest<'r> for PublicToken {
|
||||
|
@ -222,7 +222,8 @@ impl<'r> FromRequest<'r> for PublicToken {
|
|||
let Some(org_uuid) = claims.client_id.strip_prefix("organization.") else {
|
||||
err_handler!("Malformed client_id")
|
||||
};
|
||||
let Some(org_api_key) = OrganizationApiKey::find_by_org_uuid(org_uuid, &conn).await else {
|
||||
let org_uuid: OrganizationId = org_uuid.to_string().into();
|
||||
let Some(org_api_key) = OrganizationApiKey::find_by_org_uuid(&org_uuid, &conn).await else {
|
||||
err_handler!("Invalid client_id")
|
||||
};
|
||||
if org_api_key.org_uuid != claims.client_sub {
|
||||
|
|
|
@ -208,7 +208,7 @@ pub async fn enforce_2fa_policy(
|
|||
}
|
||||
|
||||
pub async fn enforce_2fa_policy_for_org(
|
||||
org_uuid: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
act_uuid: &str,
|
||||
device_type: i32,
|
||||
ip: &std::net::IpAddr,
|
||||
|
|
|
@ -472,7 +472,8 @@ async fn _organization_api_key_login(data: ConnectData, conn: &mut DbConn, ip: &
|
|||
let Some(org_uuid) = client_id.strip_prefix("organization.") else {
|
||||
err!("Malformed client_id", format!("IP: {}.", ip.ip))
|
||||
};
|
||||
let Some(org_api_key) = OrganizationApiKey::find_by_org_uuid(org_uuid, conn).await else {
|
||||
let org_uuid: OrganizationId = org_uuid.to_string().into();
|
||||
let Some(org_api_key) = OrganizationApiKey::find_by_org_uuid(&org_uuid, conn).await else {
|
||||
err!("Invalid client_id", format!("IP: {}.", ip.ip))
|
||||
};
|
||||
|
||||
|
|
|
@ -422,7 +422,7 @@ impl WebSocketUsers {
|
|||
if *NOTIFICATIONS_DISABLED {
|
||||
return;
|
||||
}
|
||||
let org_uuid = convert_option(cipher.organization_uuid.clone());
|
||||
let org_uuid = convert_option(cipher.organization_uuid.as_deref());
|
||||
// Depending if there are collections provided or not, we need to have different values for the following variables.
|
||||
// The user_uuid should be `null`, and the revision date should be set to now, else the clients won't sync the collection change.
|
||||
let (user_uuid, collection_uuids, revision_date) = if let Some(collection_uuids) = collection_uuids {
|
||||
|
|
19
src/auth.rs
19
src/auth.rs
|
@ -14,6 +14,7 @@ use std::{
|
|||
net::IpAddr,
|
||||
};
|
||||
|
||||
use crate::db::models::OrganizationId;
|
||||
use crate::{error::Error, CONFIG};
|
||||
|
||||
const JWT_ALGORITHM: Algorithm = Algorithm::RS256;
|
||||
|
@ -190,7 +191,7 @@ pub struct InviteJwtClaims {
|
|||
pub sub: String,
|
||||
|
||||
pub email: String,
|
||||
pub org_id: Option<String>,
|
||||
pub org_id: Option<OrganizationId>,
|
||||
pub member_id: Option<String>,
|
||||
pub invited_by_email: Option<String>,
|
||||
}
|
||||
|
@ -198,7 +199,7 @@ pub struct InviteJwtClaims {
|
|||
pub fn generate_invite_claims(
|
||||
uuid: String,
|
||||
email: String,
|
||||
org_id: Option<String>,
|
||||
org_id: Option<OrganizationId>,
|
||||
member_id: Option<String>,
|
||||
invited_by_email: Option<String>,
|
||||
) -> InviteJwtClaims {
|
||||
|
@ -266,18 +267,18 @@ pub struct OrgApiKeyLoginJwtClaims {
|
|||
pub sub: String,
|
||||
|
||||
pub client_id: String,
|
||||
pub client_sub: String,
|
||||
pub client_sub: OrganizationId,
|
||||
pub scope: Vec<String>,
|
||||
}
|
||||
|
||||
pub fn generate_organization_api_key_login_claims(uuid: String, org_id: String) -> OrgApiKeyLoginJwtClaims {
|
||||
pub fn generate_organization_api_key_login_claims(uuid: String, org_id: OrganizationId) -> OrgApiKeyLoginJwtClaims {
|
||||
let time_now = Utc::now();
|
||||
OrgApiKeyLoginJwtClaims {
|
||||
nbf: time_now.timestamp(),
|
||||
exp: (time_now + TimeDelta::try_hours(1).unwrap()).timestamp(),
|
||||
iss: JWT_ORG_API_KEY_ISSUER.to_string(),
|
||||
sub: uuid,
|
||||
client_id: format!("organization.{org_id}"),
|
||||
client_id: format!("organization.{}", org_id),
|
||||
client_sub: org_id,
|
||||
scope: vec!["api.organization".into()],
|
||||
}
|
||||
|
@ -549,17 +550,17 @@ impl<'r> FromRequest<'r> for OrgHeaders {
|
|||
// org_id is usually the second path param ("/organizations/<org_id>"),
|
||||
// but there are cases where it is a query value.
|
||||
// First check the path, if this is not a valid uuid, try the query values.
|
||||
let url_org_id: Option<&str> = {
|
||||
let url_org_id: Option<OrganizationId> = {
|
||||
let mut url_org_id = None;
|
||||
if let Some(Ok(org_id)) = request.param::<&str>(1) {
|
||||
if uuid::Uuid::parse_str(org_id).is_ok() {
|
||||
url_org_id = Some(org_id);
|
||||
url_org_id = Some(org_id.to_string().into());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(Ok(org_id)) = request.query_value::<&str>("organizationId") {
|
||||
if uuid::Uuid::parse_str(org_id).is_ok() {
|
||||
url_org_id = Some(org_id);
|
||||
url_org_id = Some(org_id.to_string().into());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -574,7 +575,7 @@ impl<'r> FromRequest<'r> for OrgHeaders {
|
|||
};
|
||||
|
||||
let user = headers.user;
|
||||
let membership = match Membership::find_by_user_and_org(&user.uuid, org_id, &mut conn).await {
|
||||
let membership = match Membership::find_by_user_and_org(&user.uuid, &org_id, &mut conn).await {
|
||||
Some(member) => {
|
||||
if member.status == MembershipStatus::Confirmed as i32 {
|
||||
member
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::io::ErrorKind;
|
|||
use bigdecimal::{BigDecimal, ToPrimitive};
|
||||
use serde_json::Value;
|
||||
|
||||
use super::OrganizationId;
|
||||
use crate::CONFIG;
|
||||
|
||||
db_object! {
|
||||
|
@ -172,7 +173,7 @@ impl Attachment {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn size_by_org(org_uuid: &str, conn: &mut DbConn) -> i64 {
|
||||
pub async fn size_by_org(org_uuid: &OrganizationId, conn: &mut DbConn) -> i64 {
|
||||
db_run! { conn: {
|
||||
let result: Option<BigDecimal> = attachments::table
|
||||
.left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid)))
|
||||
|
@ -189,7 +190,7 @@ impl Attachment {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn count_by_org(org_uuid: &str, conn: &mut DbConn) -> i64 {
|
||||
pub async fn count_by_org(org_uuid: &OrganizationId, conn: &mut DbConn) -> i64 {
|
||||
db_run! { conn: {
|
||||
attachments::table
|
||||
.left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid)))
|
||||
|
@ -203,7 +204,11 @@ impl Attachment {
|
|||
// This will return all attachments linked to the user or org
|
||||
// There is no filtering done here if the user actually has access!
|
||||
// It is used to speed up the sync process, and the matching is done in a different part.
|
||||
pub async fn find_all_by_user_and_orgs(user_uuid: &str, org_uuids: &Vec<String>, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_all_by_user_and_orgs(
|
||||
user_uuid: &str,
|
||||
org_uuids: &Vec<OrganizationId>,
|
||||
conn: &mut DbConn,
|
||||
) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
attachments::table
|
||||
.left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid)))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use super::OrganizationId;
|
||||
use crate::crypto::ct_eq;
|
||||
use chrono::{NaiveDateTime, Utc};
|
||||
|
||||
|
@ -9,7 +10,7 @@ db_object! {
|
|||
pub struct AuthRequest {
|
||||
pub uuid: String,
|
||||
pub user_uuid: String,
|
||||
pub organization_uuid: Option<String>,
|
||||
pub organization_uuid: Option<OrganizationId>,
|
||||
|
||||
pub request_device_identifier: String,
|
||||
pub device_type: i32, // https://github.com/bitwarden/server/blob/master/src/Core/Enums/DeviceType.cs
|
||||
|
|
|
@ -4,7 +4,8 @@ use chrono::{NaiveDateTime, TimeDelta, Utc};
|
|||
use serde_json::Value;
|
||||
|
||||
use super::{
|
||||
Attachment, CollectionCipher, Favorite, FolderCipher, Group, Membership, MembershipStatus, MembershipType, User,
|
||||
Attachment, CollectionCipher, Favorite, FolderCipher, Group, Membership, MembershipStatus, MembershipType,
|
||||
OrganizationId, User,
|
||||
};
|
||||
|
||||
use crate::api::core::{CipherData, CipherSyncData, CipherSyncType};
|
||||
|
@ -22,7 +23,7 @@ db_object! {
|
|||
pub updated_at: NaiveDateTime,
|
||||
|
||||
pub user_uuid: Option<String>,
|
||||
pub organization_uuid: Option<String>,
|
||||
pub organization_uuid: Option<OrganizationId>,
|
||||
|
||||
pub key: Option<String>,
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use serde_json::Value;
|
||||
|
||||
use super::{CollectionGroup, GroupUser, Membership, MembershipStatus, MembershipType, User};
|
||||
use super::{CollectionGroup, GroupUser, Membership, MembershipStatus, MembershipType, OrganizationId, User};
|
||||
use crate::CONFIG;
|
||||
|
||||
db_object! {
|
||||
|
@ -9,7 +9,7 @@ db_object! {
|
|||
#[diesel(primary_key(uuid))]
|
||||
pub struct Collection {
|
||||
pub uuid: String,
|
||||
pub org_uuid: String,
|
||||
pub org_uuid: OrganizationId,
|
||||
pub name: String,
|
||||
pub external_id: Option<String>,
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ db_object! {
|
|||
|
||||
/// Local methods
|
||||
impl Collection {
|
||||
pub fn new(org_uuid: String, name: String, external_id: Option<String>) -> Self {
|
||||
pub fn new(org_uuid: OrganizationId, name: String, external_id: Option<String>) -> Self {
|
||||
let mut new_model = Self {
|
||||
uuid: crate::util::get_uuid(),
|
||||
org_uuid,
|
||||
|
@ -185,7 +185,7 @@ impl Collection {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn delete_all_by_organization(org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
|
||||
pub async fn delete_all_by_organization(org_uuid: &OrganizationId, conn: &mut DbConn) -> EmptyResult {
|
||||
for collection in Self::find_by_organization(org_uuid, conn).await {
|
||||
collection.delete(conn).await?;
|
||||
}
|
||||
|
@ -279,15 +279,19 @@ impl Collection {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn find_by_organization_and_user_uuid(org_uuid: &str, user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_organization_and_user_uuid(
|
||||
org_uuid: &OrganizationId,
|
||||
user_uuid: &str,
|
||||
conn: &mut DbConn,
|
||||
) -> Vec<Self> {
|
||||
Self::find_by_user_uuid(user_uuid.to_owned(), conn)
|
||||
.await
|
||||
.into_iter()
|
||||
.filter(|c| c.org_uuid == org_uuid)
|
||||
.filter(|c| &c.org_uuid == org_uuid)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub async fn find_by_organization(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_organization(org_uuid: &OrganizationId, conn: &mut DbConn) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
collections::table
|
||||
.filter(collections::org_uuid.eq(org_uuid))
|
||||
|
@ -297,7 +301,7 @@ impl Collection {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn count_by_org(org_uuid: &str, conn: &mut DbConn) -> i64 {
|
||||
pub async fn count_by_org(org_uuid: &OrganizationId, conn: &mut DbConn) -> i64 {
|
||||
db_run! { conn: {
|
||||
collections::table
|
||||
.filter(collections::org_uuid.eq(org_uuid))
|
||||
|
@ -308,7 +312,7 @@ impl Collection {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
|
||||
pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &OrganizationId, conn: &mut DbConn) -> Option<Self> {
|
||||
db_run! { conn: {
|
||||
collections::table
|
||||
.filter(collections::uuid.eq(uuid))
|
||||
|
@ -498,7 +502,11 @@ impl Collection {
|
|||
|
||||
/// Database methods
|
||||
impl CollectionUser {
|
||||
pub async fn find_by_organization_and_user_uuid(org_uuid: &str, user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_organization_and_user_uuid(
|
||||
org_uuid: &OrganizationId,
|
||||
user_uuid: &str,
|
||||
conn: &mut DbConn,
|
||||
) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
users_collections::table
|
||||
.filter(users_collections::user_uuid.eq(user_uuid))
|
||||
|
@ -511,7 +519,7 @@ impl CollectionUser {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_organization(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_organization(org_uuid: &OrganizationId, conn: &mut DbConn) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
users_collections::table
|
||||
.inner_join(collections::table.on(collections::uuid.eq(users_collections::collection_uuid)))
|
||||
|
@ -661,7 +669,11 @@ impl CollectionUser {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn delete_all_by_user_and_org(user_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
|
||||
pub async fn delete_all_by_user_and_org(
|
||||
user_uuid: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
conn: &mut DbConn,
|
||||
) -> EmptyResult {
|
||||
let collectionusers = Self::find_by_organization_and_user_uuid(org_uuid, user_uuid, conn).await;
|
||||
|
||||
db_run! { conn: {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::db::DbConn;
|
||||
use serde_json::Value;
|
||||
|
||||
use super::OrganizationId;
|
||||
use crate::{api::EmptyResult, error::MapResult, CONFIG};
|
||||
|
||||
use chrono::{NaiveDateTime, TimeDelta, Utc};
|
||||
|
@ -18,7 +19,7 @@ db_object! {
|
|||
pub uuid: String,
|
||||
pub event_type: i32, // EventType
|
||||
pub user_uuid: Option<String>,
|
||||
pub org_uuid: Option<String>,
|
||||
pub org_uuid: Option<OrganizationId>,
|
||||
pub cipher_uuid: Option<String>,
|
||||
pub collection_uuid: Option<String>,
|
||||
pub group_uuid: Option<String>,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{Membership, User};
|
||||
use super::{Membership, OrganizationId, User};
|
||||
use crate::api::EmptyResult;
|
||||
use crate::db::DbConn;
|
||||
use crate::error::MapResult;
|
||||
|
@ -11,7 +11,7 @@ db_object! {
|
|||
#[diesel(primary_key(uuid))]
|
||||
pub struct Group {
|
||||
pub uuid: String,
|
||||
pub organizations_uuid: String,
|
||||
pub organizations_uuid: OrganizationId,
|
||||
pub name: String,
|
||||
pub access_all: bool,
|
||||
pub external_id: Option<String>,
|
||||
|
@ -40,7 +40,12 @@ db_object! {
|
|||
|
||||
/// Local methods
|
||||
impl Group {
|
||||
pub fn new(organizations_uuid: String, name: String, access_all: bool, external_id: Option<String>) -> Self {
|
||||
pub fn new(
|
||||
organizations_uuid: OrganizationId,
|
||||
name: String,
|
||||
access_all: bool,
|
||||
external_id: Option<String>,
|
||||
) -> Self {
|
||||
let now = Utc::now().naive_utc();
|
||||
|
||||
let mut new_model = Self {
|
||||
|
@ -163,27 +168,27 @@ impl Group {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn delete_all_by_organization(org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
|
||||
pub async fn delete_all_by_organization(org_uuid: &OrganizationId, conn: &mut DbConn) -> EmptyResult {
|
||||
for group in Self::find_by_organization(org_uuid, conn).await {
|
||||
group.delete(conn).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn find_by_organization(organizations_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_organization(org_uuid: &OrganizationId, conn: &mut DbConn) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
groups::table
|
||||
.filter(groups::organizations_uuid.eq(organizations_uuid))
|
||||
.filter(groups::organizations_uuid.eq(org_uuid))
|
||||
.load::<GroupDb>(conn)
|
||||
.expect("Error loading groups")
|
||||
.from_db()
|
||||
}}
|
||||
}
|
||||
|
||||
pub async fn count_by_org(organizations_uuid: &str, conn: &mut DbConn) -> i64 {
|
||||
pub async fn count_by_org(org_uuid: &OrganizationId, conn: &mut DbConn) -> i64 {
|
||||
db_run! { conn: {
|
||||
groups::table
|
||||
.filter(groups::organizations_uuid.eq(organizations_uuid))
|
||||
.filter(groups::organizations_uuid.eq(org_uuid))
|
||||
.count()
|
||||
.first::<i64>(conn)
|
||||
.ok()
|
||||
|
@ -191,7 +196,7 @@ impl Group {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
|
||||
pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &OrganizationId, conn: &mut DbConn) -> Option<Self> {
|
||||
db_run! { conn: {
|
||||
groups::table
|
||||
.filter(groups::uuid.eq(uuid))
|
||||
|
@ -202,7 +207,11 @@ impl Group {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_external_id_and_org(external_id: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
|
||||
pub async fn find_by_external_id_and_org(
|
||||
external_id: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
conn: &mut DbConn,
|
||||
) -> Option<Self> {
|
||||
db_run! { conn: {
|
||||
groups::table
|
||||
.filter(groups::external_id.eq(external_id))
|
||||
|
@ -213,7 +222,7 @@ impl Group {
|
|||
}}
|
||||
}
|
||||
//Returns all organizations the user has full access to
|
||||
pub async fn get_orgs_by_user_with_full_access(user_uuid: &str, conn: &mut DbConn) -> Vec<String> {
|
||||
pub async fn get_orgs_by_user_with_full_access(user_uuid: &str, conn: &mut DbConn) -> Vec<OrganizationId> {
|
||||
db_run! { conn: {
|
||||
groups_users::table
|
||||
.inner_join(users_organizations::table.on(
|
||||
|
@ -226,12 +235,12 @@ impl Group {
|
|||
.filter(groups::access_all.eq(true))
|
||||
.select(groups::organizations_uuid)
|
||||
.distinct()
|
||||
.load::<String>(conn)
|
||||
.load::<OrganizationId>(conn)
|
||||
.expect("Error loading organization group full access information for user")
|
||||
}}
|
||||
}
|
||||
|
||||
pub async fn is_in_full_access_group(user_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> bool {
|
||||
pub async fn is_in_full_access_group(user_uuid: &str, org_uuid: &OrganizationId, conn: &mut DbConn) -> bool {
|
||||
db_run! { conn: {
|
||||
groups::table
|
||||
.inner_join(groups_users::table.on(
|
||||
|
@ -504,7 +513,7 @@ impl GroupUser {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn has_full_access_by_member(org_uuid: &str, member_uuid: &str, conn: &mut DbConn) -> bool {
|
||||
pub async fn has_full_access_by_member(org_uuid: &OrganizationId, member_uuid: &str, conn: &mut DbConn) -> bool {
|
||||
db_run! { conn: {
|
||||
groups_users::table
|
||||
.inner_join(groups::table.on(
|
||||
|
|
|
@ -27,7 +27,9 @@ pub use self::favorite::Favorite;
|
|||
pub use self::folder::{Folder, FolderCipher};
|
||||
pub use self::group::{CollectionGroup, Group, GroupUser};
|
||||
pub use self::org_policy::{OrgPolicy, OrgPolicyErr, OrgPolicyType};
|
||||
pub use self::organization::{Membership, MembershipStatus, MembershipType, Organization, OrganizationApiKey};
|
||||
pub use self::organization::{
|
||||
Membership, MembershipStatus, MembershipType, Organization, OrganizationApiKey, OrganizationId,
|
||||
};
|
||||
pub use self::send::{Send, SendType};
|
||||
pub use self::two_factor::{TwoFactor, TwoFactorType};
|
||||
pub use self::two_factor_duo_context::TwoFactorDuoContext;
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::api::EmptyResult;
|
|||
use crate::db::DbConn;
|
||||
use crate::error::MapResult;
|
||||
|
||||
use super::{Membership, MembershipStatus, MembershipType, TwoFactor};
|
||||
use super::{Membership, MembershipStatus, MembershipType, OrganizationId, TwoFactor};
|
||||
|
||||
db_object! {
|
||||
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
|
||||
|
@ -13,7 +13,7 @@ db_object! {
|
|||
#[diesel(primary_key(uuid))]
|
||||
pub struct OrgPolicy {
|
||||
pub uuid: String,
|
||||
pub org_uuid: String,
|
||||
pub org_uuid: OrganizationId,
|
||||
pub atype: i32,
|
||||
pub enabled: bool,
|
||||
pub data: String,
|
||||
|
@ -62,7 +62,7 @@ pub enum OrgPolicyErr {
|
|||
|
||||
/// Local methods
|
||||
impl OrgPolicy {
|
||||
pub fn new(org_uuid: String, atype: OrgPolicyType, data: String) -> Self {
|
||||
pub fn new(org_uuid: OrganizationId, atype: OrgPolicyType, data: String) -> Self {
|
||||
Self {
|
||||
uuid: crate::util::get_uuid(),
|
||||
org_uuid,
|
||||
|
@ -142,7 +142,7 @@ impl OrgPolicy {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_org(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_org(org_uuid: &OrganizationId, conn: &mut DbConn) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
org_policies::table
|
||||
.filter(org_policies::org_uuid.eq(org_uuid))
|
||||
|
@ -170,7 +170,11 @@ impl OrgPolicy {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_org_and_type(org_uuid: &str, policy_type: OrgPolicyType, conn: &mut DbConn) -> Option<Self> {
|
||||
pub async fn find_by_org_and_type(
|
||||
org_uuid: &OrganizationId,
|
||||
policy_type: OrgPolicyType,
|
||||
conn: &mut DbConn,
|
||||
) -> Option<Self> {
|
||||
db_run! { conn: {
|
||||
org_policies::table
|
||||
.filter(org_policies::org_uuid.eq(org_uuid))
|
||||
|
@ -181,7 +185,7 @@ impl OrgPolicy {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn delete_all_by_organization(org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
|
||||
pub async fn delete_all_by_organization(org_uuid: &OrganizationId, conn: &mut DbConn) -> EmptyResult {
|
||||
db_run! { conn: {
|
||||
diesel::delete(org_policies::table.filter(org_policies::org_uuid.eq(org_uuid)))
|
||||
.execute(conn)
|
||||
|
@ -246,14 +250,14 @@ impl OrgPolicy {
|
|||
pub async fn is_applicable_to_user(
|
||||
user_uuid: &str,
|
||||
policy_type: OrgPolicyType,
|
||||
exclude_org_uuid: Option<&str>,
|
||||
exclude_org_uuid: Option<&OrganizationId>,
|
||||
conn: &mut DbConn,
|
||||
) -> bool {
|
||||
for policy in
|
||||
OrgPolicy::find_accepted_and_confirmed_by_user_and_active_policy(user_uuid, policy_type, conn).await
|
||||
{
|
||||
// Check if we need to skip this organization.
|
||||
if exclude_org_uuid.is_some() && exclude_org_uuid.unwrap() == policy.org_uuid {
|
||||
if exclude_org_uuid.is_some() && *exclude_org_uuid.unwrap() == policy.org_uuid {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -268,7 +272,7 @@ impl OrgPolicy {
|
|||
|
||||
pub async fn is_user_allowed(
|
||||
user_uuid: &str,
|
||||
org_uuid: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
exclude_current_org: bool,
|
||||
conn: &mut DbConn,
|
||||
) -> OrgPolicyResult {
|
||||
|
@ -296,7 +300,7 @@ impl OrgPolicy {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn org_is_reset_password_auto_enroll(org_uuid: &str, conn: &mut DbConn) -> bool {
|
||||
pub async fn org_is_reset_password_auto_enroll(org_uuid: &OrganizationId, conn: &mut DbConn) -> bool {
|
||||
match OrgPolicy::find_by_org_and_type(org_uuid, OrgPolicyType::ResetPassword, conn).await {
|
||||
Some(policy) => match serde_json::from_str::<ResetPasswordDataModel>(&policy.data) {
|
||||
Ok(opts) => {
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
use chrono::{NaiveDateTime, Utc};
|
||||
use num_traits::FromPrimitive;
|
||||
use rocket::request::FromParam;
|
||||
use serde_json::Value;
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
cmp::Ordering,
|
||||
collections::{HashMap, HashSet},
|
||||
fmt::{Display, Formatter},
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
use super::{CollectionUser, Group, GroupUser, OrgPolicy, OrgPolicyType, TwoFactor, User};
|
||||
|
@ -15,7 +19,7 @@ db_object! {
|
|||
#[diesel(table_name = organizations)]
|
||||
#[diesel(primary_key(uuid))]
|
||||
pub struct Organization {
|
||||
pub uuid: String,
|
||||
pub uuid: OrganizationId,
|
||||
pub name: String,
|
||||
pub billing_email: String,
|
||||
pub private_key: Option<String>,
|
||||
|
@ -28,7 +32,7 @@ db_object! {
|
|||
pub struct Membership {
|
||||
pub uuid: String,
|
||||
pub user_uuid: String,
|
||||
pub org_uuid: String,
|
||||
pub org_uuid: OrganizationId,
|
||||
|
||||
pub access_all: bool,
|
||||
pub akey: String,
|
||||
|
@ -43,7 +47,7 @@ db_object! {
|
|||
#[diesel(primary_key(uuid, org_uuid))]
|
||||
pub struct OrganizationApiKey {
|
||||
pub uuid: String,
|
||||
pub org_uuid: String,
|
||||
pub org_uuid: OrganizationId,
|
||||
pub atype: i32,
|
||||
pub api_key: String,
|
||||
pub revision_date: NaiveDateTime,
|
||||
|
@ -147,7 +151,7 @@ impl PartialOrd<MembershipType> for i32 {
|
|||
impl Organization {
|
||||
pub fn new(name: String, billing_email: String, private_key: Option<String>, public_key: Option<String>) -> Self {
|
||||
Self {
|
||||
uuid: crate::util::get_uuid(),
|
||||
uuid: OrganizationId(crate::util::get_uuid()),
|
||||
name,
|
||||
billing_email,
|
||||
private_key,
|
||||
|
@ -200,7 +204,7 @@ impl Organization {
|
|||
static ACTIVATE_REVOKE_DIFF: i32 = 128;
|
||||
|
||||
impl Membership {
|
||||
pub fn new(user_uuid: String, org_uuid: String) -> Self {
|
||||
pub fn new(user_uuid: String, org_uuid: OrganizationId) -> Self {
|
||||
Self {
|
||||
uuid: crate::util::get_uuid(),
|
||||
|
||||
|
@ -255,7 +259,7 @@ impl Membership {
|
|||
}
|
||||
|
||||
impl OrganizationApiKey {
|
||||
pub fn new(org_uuid: String, api_key: String) -> Self {
|
||||
pub fn new(org_uuid: OrganizationId, api_key: String) -> Self {
|
||||
Self {
|
||||
uuid: crate::util::get_uuid(),
|
||||
|
||||
|
@ -336,7 +340,7 @@ impl Organization {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
|
||||
pub async fn find_by_uuid(uuid: &OrganizationId, conn: &mut DbConn) -> Option<Self> {
|
||||
db_run! { conn: {
|
||||
organizations::table
|
||||
.filter(organizations::uuid.eq(uuid))
|
||||
|
@ -655,7 +659,7 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn delete_all_by_organization(org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
|
||||
pub async fn delete_all_by_organization(org_uuid: &OrganizationId, conn: &mut DbConn) -> EmptyResult {
|
||||
for member in Self::find_by_org(org_uuid, conn).await {
|
||||
member.delete(conn).await?;
|
||||
}
|
||||
|
@ -669,9 +673,13 @@ impl Membership {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn find_by_email_and_org(email: &str, org_id: &str, conn: &mut DbConn) -> Option<Membership> {
|
||||
pub async fn find_by_email_and_org(
|
||||
email: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
conn: &mut DbConn,
|
||||
) -> Option<Membership> {
|
||||
if let Some(user) = User::find_by_mail(email, conn).await {
|
||||
if let Some(member) = Membership::find_by_user_and_org(&user.uuid, org_id, conn).await {
|
||||
if let Some(member) = Membership::find_by_user_and_org(&user.uuid, org_uuid, conn).await {
|
||||
return Some(member);
|
||||
}
|
||||
}
|
||||
|
@ -700,7 +708,7 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
|
||||
pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &OrganizationId, conn: &mut DbConn) -> Option<Self> {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::uuid.eq(uuid))
|
||||
|
@ -750,7 +758,7 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_org(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_org(org_uuid: &OrganizationId, conn: &mut DbConn) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::org_uuid.eq(org_uuid))
|
||||
|
@ -759,7 +767,7 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_confirmed_by_org(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_confirmed_by_org(org_uuid: &OrganizationId, conn: &mut DbConn) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::org_uuid.eq(org_uuid))
|
||||
|
@ -769,7 +777,7 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn count_by_org(org_uuid: &str, conn: &mut DbConn) -> i64 {
|
||||
pub async fn count_by_org(org_uuid: &OrganizationId, conn: &mut DbConn) -> i64 {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::org_uuid.eq(org_uuid))
|
||||
|
@ -780,7 +788,11 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_org_and_type(org_uuid: &str, atype: MembershipType, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_org_and_type(
|
||||
org_uuid: &OrganizationId,
|
||||
atype: MembershipType,
|
||||
conn: &mut DbConn,
|
||||
) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::org_uuid.eq(org_uuid))
|
||||
|
@ -790,7 +802,11 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn count_confirmed_by_org_and_type(org_uuid: &str, atype: MembershipType, conn: &mut DbConn) -> i64 {
|
||||
pub async fn count_confirmed_by_org_and_type(
|
||||
org_uuid: &OrganizationId,
|
||||
atype: MembershipType,
|
||||
conn: &mut DbConn,
|
||||
) -> i64 {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::org_uuid.eq(org_uuid))
|
||||
|
@ -802,7 +818,7 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_user_and_org(user_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
|
||||
pub async fn find_by_user_and_org(user_uuid: &str, org_uuid: &OrganizationId, conn: &mut DbConn) -> Option<Self> {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::user_uuid.eq(user_uuid))
|
||||
|
@ -812,7 +828,11 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_confirmed_by_user_and_org(user_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
|
||||
pub async fn find_confirmed_by_user_and_org(
|
||||
user_uuid: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
conn: &mut DbConn,
|
||||
) -> Option<Self> {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::user_uuid.eq(user_uuid))
|
||||
|
@ -834,12 +854,12 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn get_orgs_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<String> {
|
||||
pub async fn get_orgs_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<OrganizationId> {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::user_uuid.eq(user_uuid))
|
||||
.select(users_organizations::org_uuid)
|
||||
.load::<String>(conn)
|
||||
.load::<OrganizationId>(conn)
|
||||
.unwrap_or_default()
|
||||
}}
|
||||
}
|
||||
|
@ -863,7 +883,7 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_cipher_and_org(cipher_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_cipher_and_org(cipher_uuid: &str, org_uuid: &OrganizationId, conn: &mut DbConn) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::org_uuid.eq(org_uuid))
|
||||
|
@ -886,7 +906,11 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_cipher_and_org_with_group(cipher_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_cipher_and_org_with_group(
|
||||
cipher_uuid: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
conn: &mut DbConn,
|
||||
) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::org_uuid.eq(org_uuid))
|
||||
|
@ -924,7 +948,11 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_collection_and_org(collection_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_collection_and_org(
|
||||
collection_uuid: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
conn: &mut DbConn,
|
||||
) -> Vec<Self> {
|
||||
db_run! { conn: {
|
||||
users_organizations::table
|
||||
.filter(users_organizations::org_uuid.eq(org_uuid))
|
||||
|
@ -941,7 +969,11 @@ impl Membership {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn find_by_external_id_and_org(ext_id: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
|
||||
pub async fn find_by_external_id_and_org(
|
||||
ext_id: &str,
|
||||
org_uuid: &OrganizationId,
|
||||
conn: &mut DbConn,
|
||||
) -> Option<Self> {
|
||||
db_run! {conn: {
|
||||
users_organizations::table
|
||||
.filter(
|
||||
|
@ -987,7 +1019,7 @@ impl OrganizationApiKey {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn find_by_org_uuid(org_uuid: &str, conn: &DbConn) -> Option<Self> {
|
||||
pub async fn find_by_org_uuid(org_uuid: &OrganizationId, conn: &DbConn) -> Option<Self> {
|
||||
db_run! { conn: {
|
||||
organization_api_key::table
|
||||
.filter(organization_api_key::org_uuid.eq(org_uuid))
|
||||
|
@ -996,7 +1028,7 @@ impl OrganizationApiKey {
|
|||
}}
|
||||
}
|
||||
|
||||
pub async fn delete_all_by_organization(org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
|
||||
pub async fn delete_all_by_organization(org_uuid: &OrganizationId, conn: &mut DbConn) -> EmptyResult {
|
||||
db_run! { conn: {
|
||||
diesel::delete(organization_api_key::table.filter(organization_api_key::org_uuid.eq(org_uuid)))
|
||||
.execute(conn)
|
||||
|
@ -1005,6 +1037,57 @@ impl OrganizationApiKey {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(DieselNewType, FromForm, Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct OrganizationId(String);
|
||||
|
||||
impl AsRef<str> for OrganizationId {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for OrganizationId {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for OrganizationId {
|
||||
fn borrow(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for OrganizationId {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for OrganizationId {
|
||||
fn from(raw: String) -> Self {
|
||||
Self(raw)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> FromParam<'r> for OrganizationId {
|
||||
type Error = ();
|
||||
|
||||
#[inline(always)]
|
||||
fn from_param(param: &'r str) -> Result<Self, Self::Error> {
|
||||
if param.chars().all(|c| matches!(c, 'a'..='z' | 'A'..='Z' |'0'..='9' | '-')) {
|
||||
Ok(OrganizationId(param.to_string()))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DieselNewType, Clone, Debug, Hash, PartialEq, Eq, Serialize)]
|
||||
pub struct MembershipId(String);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -3,7 +3,7 @@ use serde_json::Value;
|
|||
|
||||
use crate::util::LowerCase;
|
||||
|
||||
use super::User;
|
||||
use super::{OrganizationId, User};
|
||||
|
||||
db_object! {
|
||||
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
|
||||
|
@ -14,8 +14,7 @@ db_object! {
|
|||
pub uuid: String,
|
||||
|
||||
pub user_uuid: Option<String>,
|
||||
pub organization_uuid: Option<String>,
|
||||
|
||||
pub organization_uuid: Option<OrganizationId>,
|
||||
|
||||
pub name: String,
|
||||
pub notes: Option<String>,
|
||||
|
@ -332,7 +331,7 @@ impl Send {
|
|||
Some(total)
|
||||
}
|
||||
|
||||
pub async fn find_by_org(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
||||
pub async fn find_by_org(org_uuid: &OrganizationId, conn: &mut DbConn) -> Vec<Self> {
|
||||
db_run! {conn: {
|
||||
sends::table
|
||||
.filter(sends::organization_uuid.eq(org_uuid))
|
||||
|
|
|
@ -17,7 +17,7 @@ use crate::{
|
|||
encode_jwt, generate_delete_claims, generate_emergency_access_invite_claims, generate_invite_claims,
|
||||
generate_verify_email_claims,
|
||||
},
|
||||
db::models::{Device, DeviceType, User},
|
||||
db::models::{Device, DeviceType, OrganizationId, User},
|
||||
error::Error,
|
||||
CONFIG,
|
||||
};
|
||||
|
@ -259,7 +259,7 @@ pub async fn send_single_org_removed_from_org(address: &str, org_name: &str) ->
|
|||
|
||||
pub async fn send_invite(
|
||||
user: &User,
|
||||
org_id: Option<String>,
|
||||
org_id: Option<OrganizationId>,
|
||||
member_id: Option<String>,
|
||||
org_name: &str,
|
||||
invited_by_email: Option<String>,
|
||||
|
|
|
@ -24,6 +24,8 @@ extern crate log;
|
|||
extern crate diesel;
|
||||
#[macro_use]
|
||||
extern crate diesel_migrations;
|
||||
#[macro_use]
|
||||
extern crate diesel_derive_newtype;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
|
|
Laden …
In neuem Issue referenzieren