mirror of https://github.com/buster-so/buster.git
Merge branch 'staging' into nate/security-remediation
This commit is contained in:
commit
d39373ac18
|
@ -23,7 +23,7 @@ CREATE TRIGGER sync_user_org_attributes
|
||||||
EXECUTE FUNCTION update_user_org_attributes();
|
EXECUTE FUNCTION update_user_org_attributes();
|
||||||
|
|
||||||
-- Update existing records
|
-- Update existing records
|
||||||
UPDATE users u
|
UPDATE public.users u
|
||||||
SET attributes = jsonb_set(
|
SET attributes = jsonb_set(
|
||||||
jsonb_set(
|
jsonb_set(
|
||||||
COALESCE(attributes, '{}'::jsonb),
|
COALESCE(attributes, '{}'::jsonb),
|
||||||
|
|
|
@ -982,25 +982,25 @@ INSERT INTO public.terms (id, name, definition, sql_snippet, organization_id, cr
|
||||||
--
|
--
|
||||||
|
|
||||||
INSERT INTO public.users_to_organizations (
|
INSERT INTO public.users_to_organizations (
|
||||||
user_id,
|
user_id,
|
||||||
organization_id,
|
organization_id,
|
||||||
role,
|
role,
|
||||||
status,
|
status,
|
||||||
sharing_setting,
|
sharing_setting,
|
||||||
edit_sql,
|
edit_sql,
|
||||||
upload_csv,
|
upload_csv,
|
||||||
export_assets,
|
export_assets,
|
||||||
email_slack_enabled,
|
email_slack_enabled,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at,
|
updated_at,
|
||||||
deleted_at,
|
deleted_at,
|
||||||
created_by,
|
created_by,
|
||||||
updated_by,
|
updated_by,
|
||||||
deleted_by
|
deleted_by
|
||||||
) VALUES
|
) VALUES
|
||||||
('c2dd64cd-f7f3-4884-bc91-d46ae431901e', 'bf58d19a-8bb9-4f1d-a257-2d2105e7f1ce', 'workspace_admin', 'active', 'public', false, false, false, false, '2024-11-05 15:41:13.958254+00', '2024-11-05 15:41:13.958254+00', NULL, 'c2dd64cd-f7f3-4884-bc91-d46ae431901e', 'c2dd64cd-f7f3-4884-bc91-d46ae431901e', NULL),
|
('c2dd64cd-f7f3-4884-bc91-d46ae431901e', 'bf58d19a-8bb9-4f1d-a257-2d2105e7f1ce', 'workspace_admin', 'active', 'none', false, false, false, false, '2024-11-05 15:41:13.958254+00', '2024-11-05 15:41:13.958254+00', NULL, 'c2dd64cd-f7f3-4884-bc91-d46ae431901e', 'c2dd64cd-f7f3-4884-bc91-d46ae431901e', NULL),
|
||||||
('1fe85021-e799-471b-8837-953e9ae06e4c', 'bf58d19a-8bb9-4f1d-a257-2d2105e7f1ce', 'querier', 'active', 'team', false, false, false, false, '2024-11-05 15:41:13.958255+00', '2024-11-05 15:41:13.958255+00', NULL, '1fe85021-e799-471b-8837-953e9ae06e4c', '1fe85021-e799-471b-8837-953e9ae06e4c', NULL),
|
('1fe85021-e799-471b-8837-953e9ae06e4c', 'bf58d19a-8bb9-4f1d-a257-2d2105e7f1ce', 'querier', 'active', 'none', false, false, false, false, '2024-11-05 15:41:13.958255+00', '2024-11-05 15:41:13.958255+00', NULL, '1fe85021-e799-471b-8837-953e9ae06e4c', '1fe85021-e799-471b-8837-953e9ae06e4c', NULL),
|
||||||
('6840fa04-c0d7-4e0e-8d3d-ea9190d93874', 'bf58d19a-8bb9-4f1d-a257-2d2105e7f1ce', 'data_admin', 'active', 'public', false, false, false, false, '2024-11-05 15:41:13.958256+00', '2024-11-05 15:41:13.958256+00', NULL, '6840fa04-c0d7-4e0e-8d3d-ea9190d93874', '6840fa04-c0d7-4e0e-8d3d-ea9190d93874', NULL);
|
('6840fa04-c0d7-4e0e-8d3d-ea9190d93874', 'bf58d19a-8bb9-4f1d-a257-2d2105e7f1ce', 'data_admin', 'active', 'none', false, false, false, false, '2024-11-05 15:41:13.958256+00', '2024-11-05 15:41:13.958256+00', NULL, '6840fa04-c0d7-4e0e-8d3d-ea9190d93874', '6840fa04-c0d7-4e0e-8d3d-ea9190d93874', NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,10 @@ pub async fn update_user_handler(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if &auth_user.id == user_id {
|
||||||
|
return Err(anyhow::anyhow!("Cannot update self"));
|
||||||
|
};
|
||||||
|
|
||||||
match is_user_workspace_admin_or_data_admin(auth_user, &user_organization_id).await {
|
match is_user_workspace_admin_or_data_admin(auth_user, &user_organization_id).await {
|
||||||
Ok(true) => (),
|
Ok(true) => (),
|
||||||
Ok(false) => return Err(anyhow::anyhow!("Insufficient permissions")),
|
Ok(false) => return Err(anyhow::anyhow!("Insufficient permissions")),
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
enums::{AssetPermissionRole, AssetType},
|
enums::{AssetPermissionRole, AssetType},
|
||||||
lib::get_pg_pool,
|
lib::get_pg_pool,
|
||||||
models::{Dashboard, Message},
|
models::{Dashboard, Message},
|
||||||
schema::{asset_permissions, dashboards, messages, teams_to_users, threads_to_dashboards},
|
schema::{asset_permissions, dashboards, messages, teams_to_users, threads_to_dashboards, users_to_organizations},
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
clients::{sentry_utils::send_sentry_error, supabase_vault::read_secret},
|
clients::{sentry_utils::send_sentry_error, supabase_vault::read_secret},
|
||||||
|
@ -270,16 +270,43 @@ pub async fn get_user_dashboard_permission(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// First get the dashboard's organization
|
||||||
|
let dashboard_org = match dashboards::table
|
||||||
|
.select(dashboards::organization_id)
|
||||||
|
.filter(dashboards::id.eq(dashboard_id))
|
||||||
|
.filter(dashboards::deleted_at.is_null())
|
||||||
|
.first::<Uuid>(&mut conn)
|
||||||
|
.await {
|
||||||
|
Ok(org_id) => org_id,
|
||||||
|
Err(diesel::result::Error::NotFound) => return Ok(None),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("Error querying dashboard organization: {}", e);
|
||||||
|
return Err(anyhow!("Error querying dashboard organization: {}", e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Then get the user's organization
|
||||||
|
let user_org = match users_to_organizations::table
|
||||||
|
.select(users_to_organizations::organization_id)
|
||||||
|
.filter(users_to_organizations::user_id.eq(user_id))
|
||||||
|
.first::<Uuid>(&mut conn)
|
||||||
|
.await {
|
||||||
|
Ok(org_id) => org_id,
|
||||||
|
Err(diesel::result::Error::NotFound) => return Ok(None),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("Error querying user organization: {}", e);
|
||||||
|
return Err(anyhow!("Error querying user organization: {}", e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// If organizations don't match, deny access
|
||||||
|
if dashboard_org != user_org {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
let permissions = match asset_permissions::table
|
let permissions = match asset_permissions::table
|
||||||
.left_join(
|
|
||||||
teams_to_users::table.on(asset_permissions::identity_id.eq(teams_to_users::team_id)),
|
|
||||||
)
|
|
||||||
.select(asset_permissions::role)
|
.select(asset_permissions::role)
|
||||||
.filter(
|
.filter(asset_permissions::identity_id.eq(&user_id))
|
||||||
asset_permissions::identity_id
|
|
||||||
.eq(&user_id)
|
|
||||||
.or(teams_to_users::user_id.eq(&user_id)),
|
|
||||||
)
|
|
||||||
.filter(asset_permissions::asset_id.eq(&dashboard_id))
|
.filter(asset_permissions::asset_id.eq(&dashboard_id))
|
||||||
.filter(asset_permissions::deleted_at.is_null())
|
.filter(asset_permissions::deleted_at.is_null())
|
||||||
.load::<AssetPermissionRole>(&mut conn)
|
.load::<AssetPermissionRole>(&mut conn)
|
||||||
|
@ -321,18 +348,27 @@ pub async fn get_bulk_user_dashboard_permission(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get user's organization
|
||||||
|
let user_org = match users_to_organizations::table
|
||||||
|
.select(users_to_organizations::organization_id)
|
||||||
|
.filter(users_to_organizations::user_id.eq(user_id))
|
||||||
|
.first::<Uuid>(&mut conn)
|
||||||
|
.await {
|
||||||
|
Ok(org_id) => org_id,
|
||||||
|
Err(diesel::result::Error::NotFound) => return Ok(HashMap::new()),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("Error querying user organization: {}", e);
|
||||||
|
return Err(anyhow!("Error querying user organization: {}", e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let permissions = match asset_permissions::table
|
let permissions = match asset_permissions::table
|
||||||
.left_join(
|
.inner_join(dashboards::table.on(asset_permissions::asset_id.eq(dashboards::id)))
|
||||||
teams_to_users::table.on(asset_permissions::identity_id.eq(teams_to_users::team_id)),
|
|
||||||
)
|
|
||||||
.select((asset_permissions::asset_id, asset_permissions::role))
|
.select((asset_permissions::asset_id, asset_permissions::role))
|
||||||
.filter(
|
.filter(asset_permissions::identity_id.eq(&user_id))
|
||||||
asset_permissions::identity_id
|
|
||||||
.eq(&user_id)
|
|
||||||
.or(teams_to_users::user_id.eq(&user_id)),
|
|
||||||
)
|
|
||||||
.filter(asset_permissions::asset_id.eq_any(dashboard_ids))
|
.filter(asset_permissions::asset_id.eq_any(dashboard_ids))
|
||||||
.filter(asset_permissions::deleted_at.is_null())
|
.filter(asset_permissions::deleted_at.is_null())
|
||||||
|
.filter(dashboards::organization_id.eq(user_org))
|
||||||
.load::<(Uuid, AssetPermissionRole)>(&mut conn)
|
.load::<(Uuid, AssetPermissionRole)>(&mut conn)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|
|
@ -115,13 +115,6 @@ async fn list_dashboards_handler(
|
||||||
.and(asset_permissions::asset_type.eq(AssetType::Dashboard))
|
.and(asset_permissions::asset_type.eq(AssetType::Dashboard))
|
||||||
.and(asset_permissions::deleted_at.is_null())),
|
.and(asset_permissions::deleted_at.is_null())),
|
||||||
)
|
)
|
||||||
.left_join(
|
|
||||||
teams_to_users::table.on(asset_permissions::identity_id
|
|
||||||
.eq(teams_to_users::user_id)
|
|
||||||
.and(asset_permissions::identity_type.eq(IdentityType::Team))
|
|
||||||
.and(teams_to_users::deleted_at.is_null())
|
|
||||||
.and(asset_permissions::deleted_at.is_null())),
|
|
||||||
)
|
|
||||||
.inner_join(users::table.on(users::id.eq(dashboards::created_by)))
|
.inner_join(users::table.on(users::id.eq(dashboards::created_by)))
|
||||||
.select((
|
.select((
|
||||||
dashboards::id,
|
dashboards::id,
|
||||||
|
@ -133,11 +126,7 @@ async fn list_dashboards_handler(
|
||||||
users::name.nullable(),
|
users::name.nullable(),
|
||||||
))
|
))
|
||||||
.filter(dashboards::deleted_at.is_null())
|
.filter(dashboards::deleted_at.is_null())
|
||||||
.filter(
|
.filter(asset_permissions::identity_id.eq(user_id))
|
||||||
asset_permissions::identity_id
|
|
||||||
.eq(user_id)
|
|
||||||
.or(teams_to_users::user_id.eq(user_id)),
|
|
||||||
)
|
|
||||||
.distinct()
|
.distinct()
|
||||||
.order((dashboards::updated_at.desc(), dashboards::id.asc()))
|
.order((dashboards::updated_at.desc(), dashboards::id.asc()))
|
||||||
.offset(page * page_size)
|
.offset(page * page_size)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import { BASE_URL } from './buster_rest/instances';
|
import { BASE_URL } from './buster_rest/instances';
|
||||||
import type { RequestInit } from 'next/dist/server/web/spec-extension/request';
|
import type { RequestInit } from 'next/dist/server/web/spec-extension/request';
|
||||||
import { createClient } from '../context/Supabase/server';
|
import { createServerSupabaseClient } from '../context/Supabase/server';
|
||||||
|
|
||||||
export interface FetchConfig extends RequestInit {
|
export interface FetchConfig extends RequestInit {
|
||||||
baseURL?: string;
|
baseURL?: string;
|
||||||
|
@ -10,7 +10,7 @@ export interface FetchConfig extends RequestInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const serverFetch = async <T>(url: string, config: FetchConfig = {}): Promise<T> => {
|
export const serverFetch = async <T>(url: string, config: FetchConfig = {}): Promise<T> => {
|
||||||
const supabase = await createClient();
|
const supabase = await createServerSupabaseClient();
|
||||||
const sessionData = await supabase.auth.getSession();
|
const sessionData = await supabase.auth.getSession();
|
||||||
const accessToken = sessionData.data?.session?.access_token;
|
const accessToken = sessionData.data?.session?.access_token;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue