Speed up user authorization validation queries.

This is related to the previous commit. This commit refactors the
queries in case of user tokens.
This commit is contained in:
Orne Brocaar 2023-10-18 12:11:06 +01:00
parent ce5b9fbfd0
commit c7e586a326

View File

@ -12,8 +12,7 @@ use super::error::Error;
use crate::api::auth::AuthID; use crate::api::auth::AuthID;
use crate::storage::get_db_conn; use crate::storage::get_db_conn;
use crate::storage::schema::{ use crate::storage::schema::{
api_key, application, device, device_profile, gateway, multicast_group, tenant, tenant_user, api_key, application, device, device_profile, gateway, multicast_group, tenant_user, user,
user,
}; };
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -344,7 +343,6 @@ impl Validator for ValidateApiKeysAccess {
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(tenant_user::table.left_join(tenant::table))
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -353,18 +351,27 @@ impl Validator for ValidateApiKeysAccess {
// tenant admin // tenant admin
Flag::Create => { Flag::Create => {
q = q.filter( q = q.filter(
user::dsl::is_admin.eq(true).or(tenant_user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) tenant_user::dsl::tenant_user.filter(
.and(tenant::dsl::id.eq(&tenant_id))), tenant_user::dsl::tenant_id
.eq(&tenant_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(tenant_user::dsl::is_admin.eq(true)),
),
)),
); );
} }
// admin user // admin user
// tenant user (api_key filtered by tenant_id in api) // tenant user (api_key filtered by tenant_id in api)
Flag::List => { Flag::List => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) tenant_user::dsl::tenant_user.filter(
.or(tenant::dsl::id.eq(&tenant_id)), tenant_user::dsl::tenant_id
.eq(&tenant_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
_ => { _ => {
@ -407,9 +414,6 @@ impl Validator for ValidateApiKeyAccess {
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(
tenant_user::table.left_join(tenant::table.left_join(api_key::table)),
)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -418,9 +422,19 @@ impl Validator for ValidateApiKeyAccess {
// tenant admin // tenant admin
Flag::Delete => { Flag::Delete => {
q = q.filter( q = q.filter(
user::dsl::is_admin.eq(true).or(tenant_user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) tenant_user::dsl::tenant_user
.and(api_key::dsl::id.eq(&self_id))), .inner_join(
api_key::table.on(api_key::dsl::tenant_id
.eq(tenant_user::dsl::tenant_id.nullable())),
)
.filter(
tenant_user::dsl::user_id
.eq(user::dsl::id)
.and(tenant_user::dsl::is_admin.eq(true))
.and(api_key::dsl::id.eq(&self_id)),
),
)),
); );
} }
_ => { _ => {
@ -525,7 +539,6 @@ impl Validator for ValidateTenantAccess {
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(tenant_user::table.left_join(tenant::table))
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -533,7 +546,15 @@ impl Validator for ValidateTenantAccess {
// global admin // global admin
// tenant user // tenant user
Flag::Read => { Flag::Read => {
q = q.filter(user::is_admin.eq(true).or(tenant::dsl::id.eq(&tenant_id))); q = q.filter(
user::is_admin.eq(true).or(dsl::exists(
tenant_user::dsl::tenant_user.filter(
tenant_user::dsl::user_id
.eq(user::dsl::id)
.and(tenant_user::dsl::tenant_id.eq(&tenant_id)),
),
)),
);
} }
// global admin // global admin
@ -614,7 +635,6 @@ impl Validator for ValidateTenantUsersAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(tenant_user::table.left_join(tenant::table))
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -623,18 +643,27 @@ impl Validator for ValidateTenantUsersAccess {
// tenant admin // tenant admin
Flag::Create => { Flag::Create => {
q = q.filter( q = q.filter(
user::dsl::is_admin.eq(true).or(tenant::dsl::id user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(&tenant_id) tenant_user::dsl::tenant_user.filter(
.and(tenant_user::dsl::is_admin.eq(true))), tenant_user::dsl::user_id
.eq(user::dsl::id)
.and(tenant_user::dsl::tenant_id.eq(&tenant_id))
.and(tenant_user::dsl::is_admin.eq(true)),
),
)),
); );
} }
// global admin // global admin
// tenant user // tenant user
Flag::List => { Flag::List => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) tenant_user::dsl::tenant_user.filter(
.or(tenant::dsl::id.eq(&tenant_id)), tenant_user::dsl::user_id
.eq(user::dsl::id)
.and(tenant_user::dsl::tenant_id.eq(&tenant_id)),
),
)),
); );
} }
_ => { _ => {
@ -712,7 +741,6 @@ impl Validator for ValidateTenantUserAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(tenant_user::table.left_join(tenant::table))
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -722,23 +750,32 @@ impl Validator for ValidateTenantUserAccess {
// user itself // user itself
Flag::Read => { Flag::Read => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
tenant_user::dsl::tenant_user.filter(
tenant_user::dsl::user_id
.eq(user::dsl::id)
.and(tenant_user::dsl::tenant_id.eq(&tenant_id))
.and(
tenant_user::dsl::is_admin
.eq(true) .eq(true)
.or(tenant::dsl::id .or(tenant_user::dsl::user_id.eq(&user_id)),
.eq(&tenant_id) ),
.and(tenant_user::dsl::is_admin.eq(true))) ),
.or(tenant::dsl::id )),
.eq(&tenant_id)
.and(tenant_user::dsl::user_id.eq(&user_id))),
); );
} }
// admin user // admin user
// tenant admin // tenant admin
Flag::Update | Flag::Delete => { Flag::Update | Flag::Delete => {
q = q.filter( q = q.filter(
user::dsl::is_admin.eq(true).or(tenant::dsl::id user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(&tenant_id) tenant_user::dsl::tenant_user.filter(
.and(tenant_user::dsl::is_admin.eq(true))), tenant_user::dsl::user_id
.eq(user::dsl::id)
.and(tenant_user::dsl::tenant_id.eq(&tenant_id))
.and(tenant_user::dsl::is_admin.eq(true)),
),
)),
); );
} }
_ => { _ => {
@ -810,7 +847,6 @@ impl Validator for ValidateApplicationsAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(tenant_user::table.left_join(tenant::table))
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -820,23 +856,31 @@ impl Validator for ValidateApplicationsAccess {
// tenant device admin // tenant device admin
Flag::Create => { Flag::Create => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
tenant_user::dsl::tenant_user.filter(
tenant_user::dsl::user_id
.eq(user::dsl::id)
.and(tenant_user::dsl::tenant_id.eq(&tenant_id))
.and(
tenant_user::dsl::is_admin
.eq(true) .eq(true)
.or(tenant::dsl::id .or(tenant_user::dsl::is_device_admin.eq(true)),
.eq(&tenant_id) ),
.and(tenant_user::dsl::is_admin.eq(true))) ),
.or(tenant::dsl::id )),
.eq(&tenant_id)
.and(tenant_user::dsl::is_device_admin.eq(true))),
); );
} }
// global admin // global admin
// tenant user // tenant user
Flag::List => { Flag::List => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) tenant_user::dsl::tenant_user.filter(
.or(tenant::dsl::id.eq(&tenant_id)), tenant_user::dsl::user_id
.eq(user::dsl::id)
.and(tenant_user::dsl::tenant_id.eq(&tenant_id)),
),
)),
); );
} }
_ => { _ => {
@ -920,12 +964,6 @@ impl Validator for ValidateApplicationAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(
tenant_user::table.left_join(
application::table
.on(tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id)),
),
)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -934,9 +972,17 @@ impl Validator for ValidateApplicationAccess {
// tenant user // tenant user
Flag::Read => { Flag::Read => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) application::dsl::application
.or(application::dsl::id.eq(&application_id)), .inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
application::dsl::id
.eq(&application_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
// global admin // global admin
@ -944,14 +990,22 @@ impl Validator for ValidateApplicationAccess {
// tenant device admin // tenant device admin
Flag::Update | Flag::Delete => { Flag::Update | Flag::Delete => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
application::dsl::application
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
application::dsl::id
.eq(&application_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(
tenant_user::dsl::is_admin
.eq(true) .eq(true)
.or(application::dsl::id .or(tenant_user::dsl::is_device_admin.eq(true)),
.eq(&application_id) ),
.and(tenant_user::dsl::is_admin.eq(true))) ),
.or(application::dsl::id )),
.eq(&application_id)
.and(tenant_user::dsl::is_device_admin.eq(true))),
); );
} }
_ => { _ => {
@ -1174,7 +1228,6 @@ impl Validator for ValidateDeviceProfilesAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(tenant_user::table)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -1184,23 +1237,31 @@ impl Validator for ValidateDeviceProfilesAccess {
// tenant device admin // tenant device admin
Flag::Create => { Flag::Create => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
tenant_user::dsl::tenant_user.filter(
tenant_user::dsl::user_id
.eq(user::dsl::id)
.and(tenant_user::dsl::tenant_id.eq(&tenant_id))
.and(
tenant_user::dsl::is_admin
.eq(true) .eq(true)
.or(tenant_user::dsl::tenant_id .or(tenant_user::dsl::is_device_admin.eq(true)),
.eq(&tenant_id) ),
.and(tenant_user::dsl::is_admin.eq(true))) ),
.or(tenant_user::dsl::tenant_id )),
.eq(&tenant_id)
.and(tenant_user::dsl::is_device_admin.eq(true))),
); );
} }
// global admin // global admin
// tenant user // tenant user
Flag::List => { Flag::List => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) tenant_user::dsl::tenant_user.filter(
.or(tenant_user::dsl::tenant_id.eq(&tenant_id)), tenant_user::dsl::user_id
.eq(user::dsl::id)
.and(tenant_user::dsl::tenant_id.eq(&tenant_id)),
),
)),
); );
} }
_ => { _ => {
@ -1275,12 +1336,6 @@ impl Validator for ValidateDeviceProfileAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(
tenant_user::table
.left_join(device_profile::table.on(
tenant_user::dsl::tenant_id.eq(device_profile::dsl::tenant_id),
)),
)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -1289,26 +1344,41 @@ impl Validator for ValidateDeviceProfileAccess {
// tenant user // tenant user
Flag::Read => { Flag::Read => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) device_profile::dsl::device_profile
.or(device_profile::dsl::id.eq(&device_profile_id)), .inner_join(
tenant_user::table.on(tenant_user::dsl::tenant_id
.eq(device_profile::dsl::tenant_id)),
)
.filter(
device_profile::dsl::id
.eq(&device_profile_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
// global admin // global admin
// tenant admin user // tenant admin user
// tenant device admin // tenant device admin
Flag::Update | Flag::Delete => { Flag::Update | Flag::Delete => {
q = q.filter( q =
user::dsl::is_admin q.filter(
.eq(true) user::dsl::is_admin.eq(true).or(dsl::exists(
.or(device_profile::dsl::id device_profile::dsl::device_profile
.inner_join(
tenant_user::table.on(tenant_user::dsl::tenant_id
.eq(device_profile::dsl::tenant_id)),
)
.filter(
device_profile::dsl::id
.eq(&device_profile_id) .eq(&device_profile_id)
.and(device_profile::dsl::tenant_id.is_not_null()) .and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(tenant_user::dsl::is_admin.eq(true))) .and(tenant_user::dsl::is_admin.eq(true).or(
.or(device_profile::dsl::id tenant_user::dsl::is_device_admin.eq(true),
.eq(&device_profile_id) )),
.and(device_profile::dsl::tenant_id.is_not_null()) ),
.and(tenant_user::dsl::is_device_admin.eq(true))), )),
); );
} }
_ => { _ => {
@ -1388,12 +1458,6 @@ impl Validator for ValidateDevicesAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(
tenant_user::table.left_join(
application::table
.on(tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id)),
),
)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -1403,23 +1467,39 @@ impl Validator for ValidateDevicesAccess {
// tenant device admin // tenant device admin
Flag::Create => { Flag::Create => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
application::dsl::application
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
application::dsl::id
.eq(&application_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(
tenant_user::dsl::is_admin
.eq(true) .eq(true)
.or(application::dsl::id .or(tenant_user::dsl::is_device_admin.eq(true)),
.eq(&application_id) ),
.and(tenant_user::dsl::is_admin.eq(true))) ),
.or(application::dsl::id )),
.eq(&application_id)
.and(tenant_user::dsl::is_device_admin.eq(true))),
); );
} }
// admin user // admin user
// tenant user // tenant user
Flag::List => { Flag::List => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) application::dsl::application
.or(application::dsl::id.eq(&application_id)), .inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
application::dsl::id
.eq(&application_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
_ => { _ => {
@ -1496,15 +1576,6 @@ impl Validator for ValidateDeviceAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(
tenant_user::table.left_join(
application::table
.on(tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id)),
),
)
.left_join(
device::table.on(application::dsl::id.eq(device::dsl::application_id)),
)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -1513,9 +1584,18 @@ impl Validator for ValidateDeviceAccess {
// tenant user // tenant user
Flag::Read => { Flag::Read => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) device::dsl::device
.or(device::dsl::dev_eui.eq(&dev_eui)), .inner_join(application::table)
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
device::dsl::dev_eui
.eq(&dev_eui)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
// admin user // admin user
@ -1523,14 +1603,23 @@ impl Validator for ValidateDeviceAccess {
// tenant device admin // tenant device admin
Flag::Update | Flag::Delete => { Flag::Update | Flag::Delete => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
device::dsl::device
.inner_join(application::table)
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
device::dsl::dev_eui
.eq(&dev_eui)
.and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(
tenant_user::dsl::is_admin
.eq(true) .eq(true)
.or(device::dsl::dev_eui .or(tenant_user::dsl::is_device_admin.eq(true)),
.eq(&dev_eui) ),
.and(tenant_user::dsl::is_admin.eq(true))) ),
.or(device::dsl::dev_eui )),
.eq(&dev_eui)
.and(tenant_user::dsl::is_device_admin.eq(true))),
); );
} }
_ => { _ => {
@ -1607,15 +1696,6 @@ impl Validator for ValidateDeviceQueueAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(
tenant_user::table.left_join(
application::table
.on(tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id)),
),
)
.left_join(
device::table.on(application::dsl::id.eq(device::dsl::application_id)),
)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -1624,9 +1704,18 @@ impl Validator for ValidateDeviceQueueAccess {
// tenant user // tenant user
Flag::Create | Flag::List | Flag::Delete => { Flag::Create | Flag::List | Flag::Delete => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) device::dsl::device
.or(device::dsl::dev_eui.eq(&dev_eui)), .inner_join(application::table)
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
device::dsl::dev_eui
.eq(&dev_eui)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
_ => { _ => {
@ -1703,7 +1792,6 @@ impl Validator for ValidateGatewaysAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(tenant_user::table.left_join(tenant::table))
.filter(user::dsl::id.eq(id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -1713,23 +1801,31 @@ impl Validator for ValidateGatewaysAccess {
// gateway admin // gateway admin
Flag::Create => { Flag::Create => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
tenant_user::dsl::tenant_user.filter(
tenant_user::dsl::tenant_id
.eq(&tenant_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(
tenant_user::dsl::is_admin
.eq(true) .eq(true)
.or(tenant::dsl::id .or(tenant_user::dsl::is_gateway_admin.eq(true)),
.eq(&tenant_id) ),
.and(tenant_user::dsl::is_admin.eq(true))) ),
.or(tenant::dsl::id )),
.eq(&tenant_id)
.and(tenant_user::dsl::is_gateway_admin.eq(true))),
); );
} }
// global admin // global admin
// tenant user // tenant user
Flag::List => { Flag::List => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) tenant_user::dsl::tenant_user.filter(
.or(tenant::dsl::id.eq(&tenant_id)), tenant_user::dsl::tenant_id
.eq(&tenant_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
_ => { _ => {
@ -1801,9 +1897,6 @@ impl Validator for ValidateGatewayAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(
tenant_user::table.left_join(tenant::table.left_join(gateway::table)),
)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -1812,24 +1905,39 @@ impl Validator for ValidateGatewayAccess {
// tenant user // tenant user
Flag::Read => { Flag::Read => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) gateway::dsl::gateway
.or(gateway::dsl::gateway_id.eq(&gateway_id)), .inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(gateway::dsl::tenant_id),
))
.filter(
gateway::dsl::gateway_id
.eq(&gateway_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
// admin user // admin user
// tenant admin // tenant admin
// gateway admin // gateway admin
Flag::Update | Flag::Delete => { Flag::Update | Flag::Delete => {
q = q.filter( q =
user::dsl::is_admin q.filter(
.eq(true) user::dsl::is_admin.eq(true).or(dsl::exists(
.or(gateway::dsl::gateway_id gateway::dsl::gateway
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(gateway::dsl::tenant_id),
))
.filter(
gateway::dsl::gateway_id
.eq(&gateway_id) .eq(&gateway_id)
.and(tenant_user::dsl::is_admin.eq(true))) .and(tenant_user::dsl::user_id.eq(user::dsl::id))
.or(gateway::dsl::gateway_id .and(tenant_user::dsl::is_admin.eq(true).or(
.eq(&gateway_id) tenant_user::dsl::is_gateway_admin.eq(true),
.and(tenant_user::dsl::is_gateway_admin.eq(true))), )),
),
)),
); );
} }
_ => { _ => {
@ -1906,12 +2014,6 @@ impl Validator for ValidateMulticastGroupsAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(
tenant_user::table.left_join(
application::table
.on(tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id)),
),
)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -1921,23 +2023,39 @@ impl Validator for ValidateMulticastGroupsAccess {
// tenant device admin // tenant device admin
Flag::Create => { Flag::Create => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
application::dsl::application
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
application::dsl::id
.eq(&application_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(
tenant_user::dsl::is_admin
.eq(true) .eq(true)
.or(application::dsl::id .or(tenant_user::dsl::is_device_admin.eq(true)),
.eq(&application_id) ),
.and(tenant_user::dsl::is_admin.eq(true))) ),
.or(application::dsl::id )),
.eq(&application_id)
.and(tenant_user::dsl::is_device_admin.eq(true))),
); );
} }
// admin user // admin user
// tenant user // tenant user
Flag::List => { Flag::List => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) application::dsl::application
.or(application::dsl::id.eq(&application_id)), .inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
application::dsl::id
.eq(&application_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
_ => { _ => {
@ -2017,16 +2135,6 @@ impl Validator for ValidateMulticastGroupAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(
tenant_user::table.left_join(
application::table
.on(tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id)),
),
)
.left_join(
multicast_group::table
.on(application::dsl::id.eq(multicast_group::dsl::application_id)),
)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -2035,9 +2143,18 @@ impl Validator for ValidateMulticastGroupAccess {
// tenant user // tenant user
Flag::Read => { Flag::Read => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) multicast_group::dsl::multicast_group
.or(multicast_group::dsl::id.eq(&multicast_group_id)), .inner_join(application::table)
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
multicast_group::dsl::id
.eq(&multicast_group_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
// admin user // admin user
@ -2045,14 +2162,23 @@ impl Validator for ValidateMulticastGroupAccess {
// tenant device admin // tenant device admin
Flag::Update | Flag::Delete => { Flag::Update | Flag::Delete => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
multicast_group::dsl::multicast_group
.inner_join(application::table)
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
multicast_group::dsl::id
.eq(&multicast_group_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(
tenant_user::dsl::is_admin
.eq(true) .eq(true)
.or(multicast_group::dsl::id .or(tenant_user::dsl::is_device_admin.eq(true)),
.eq(&multicast_group_id) ),
.and(tenant_user::dsl::is_admin.eq(true))) ),
.or(multicast_group::dsl::id )),
.eq(&multicast_group_id)
.and(tenant_user::dsl::is_device_admin.eq(true))),
); );
} }
_ => { _ => {
@ -2134,16 +2260,6 @@ impl Validator for ValidateMulticastGroupQueueAccess {
let mut c = get_db_conn()?; let mut c = get_db_conn()?;
let mut q = user::dsl::user let mut q = user::dsl::user
.select(dsl::count_star()) .select(dsl::count_star())
.left_join(
tenant_user::table.left_join(
application::table
.on(tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id)),
),
)
.left_join(
multicast_group::table
.on(application::dsl::id.eq(multicast_group::dsl::application_id)),
)
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true))) .filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
.into_boxed(); .into_boxed();
@ -2153,23 +2269,41 @@ impl Validator for ValidateMulticastGroupQueueAccess {
// tenant device admin // tenant device admin
Flag::Create | Flag::Delete => { Flag::Create | Flag::Delete => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
multicast_group::dsl::multicast_group
.inner_join(application::table)
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
multicast_group::dsl::id
.eq(&multicast_group_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(
tenant_user::dsl::is_admin
.eq(true) .eq(true)
.or(multicast_group::dsl::id .or(tenant_user::dsl::is_device_admin.eq(true)),
.eq(&multicast_group_id) ),
.and(tenant_user::dsl::is_admin.eq(true))) ),
.or(multicast_group::dsl::id )),
.eq(&multicast_group_id)
.and(tenant_user::dsl::is_device_admin.eq(true))),
); );
} }
// admin user // admin user
// tenant user // tenant user
Flag::List => { Flag::List => {
q = q.filter( q = q.filter(
user::dsl::is_admin user::dsl::is_admin.eq(true).or(dsl::exists(
.eq(true) multicast_group::dsl::multicast_group
.or(multicast_group::dsl::id.eq(&multicast_group_id)), .inner_join(application::table)
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
multicast_group::dsl::id
.eq(&multicast_group_id)
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
); );
} }
_ => { _ => {
@ -2247,9 +2381,16 @@ pub mod test {
where where
V: Validator + Sync, V: Validator + Sync,
{ {
for tst in tests { println!("Running tests");
for v in tst.validators { for (i, tst) in tests.iter().enumerate() {
assert_eq!(tst.ok, v.validate(&tst.id).await.is_ok()); for (j, v) in tst.validators.iter().enumerate() {
assert_eq!(
tst.ok,
v.validate(&tst.id).await.is_ok(),
"Test {}, assertion {}",
i,
j
);
} }
} }
} }