mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-05 08:02:18 +00:00
fix(frontend): workspace color race condition for superadmins (#7229)
This commit is contained in:
+58
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT\n workspace.id AS \"id!\",\n workspace.name AS \"name!\",\n workspace.owner AS \"owner!\",\n workspace.deleted AS \"deleted!\",\n workspace.premium AS \"premium!\",\n workspace_settings.color AS \"color\",\n workspace.parent_workspace_id AS \"parent_workspace_id\"\n FROM workspace\n LEFT JOIN workspace_settings ON workspace.id = workspace_settings.workspace_id\n WHERE workspace.id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id!",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name!",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "owner!",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "deleted!",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "premium!",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "color",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "parent_workspace_id",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "00c1dd0cfaf15aafdcfcabc1f123cebdf8d777f48e148bcb171fa15e8bf6f098"
|
||||
}
|
||||
@@ -688,6 +688,22 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/UserWorkspaceList"
|
||||
|
||||
/w/{workspace}/workspaces/get_as_superadmin:
|
||||
get:
|
||||
summary: get workspace as super admin (require to be super admin)
|
||||
operationId: getWorkspaceAsSuperAdmin
|
||||
tags:
|
||||
- workspace
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
responses:
|
||||
"200":
|
||||
description: workspace
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Workspace"
|
||||
|
||||
/workspaces/list_as_superadmin:
|
||||
get:
|
||||
summary: list all workspaces as super admin (require to be super admin)
|
||||
|
||||
@@ -50,7 +50,7 @@ use windmill_common::{
|
||||
oauth2::WORKSPACE_SLACK_BOT_TOKEN_PATH,
|
||||
utils::{paginate, rd_string, require_admin, Pagination},
|
||||
};
|
||||
use windmill_git_sync::{handle_fork_branch_creation, handle_deployment_metadata, DeployedObject};
|
||||
use windmill_git_sync::{handle_deployment_metadata, handle_fork_branch_creation, DeployedObject};
|
||||
use windmill_worker::scoped_dependency_map::{DependencyMap, ScopedDependencyMap};
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
@@ -73,6 +73,7 @@ lazy_static::lazy_static! {
|
||||
|
||||
pub fn workspaced_service() -> Router {
|
||||
let router = Router::new()
|
||||
.route("/get_as_superadmin", get(get_workspace_as_superadmin))
|
||||
.route("/list_pending_invites", get(list_pending_invites))
|
||||
.route("/update", post(edit_workspace))
|
||||
.route("/archive", post(archive_workspace))
|
||||
@@ -163,7 +164,10 @@ pub fn workspaced_service() -> Router {
|
||||
post(acknowledge_all_critical_alerts),
|
||||
)
|
||||
.route("/critical_alerts/mute", post(mute_critical_alerts))
|
||||
.route("/create_workspace_fork_branch", post(create_workspace_fork_branch))
|
||||
.route(
|
||||
"/create_workspace_fork_branch",
|
||||
post(create_workspace_fork_branch),
|
||||
)
|
||||
.route("/operator_settings", post(update_operator_settings));
|
||||
|
||||
#[cfg(all(feature = "stripe", feature = "enterprise"))]
|
||||
@@ -706,7 +710,9 @@ async fn get_slack_oauth_config(
|
||||
.await?;
|
||||
|
||||
// Mask the secret if it exists
|
||||
let masked_secret = settings.slack_oauth_client_secret.map(|_| "***".to_string());
|
||||
let masked_secret = settings
|
||||
.slack_oauth_client_secret
|
||||
.map(|_| "***".to_string());
|
||||
|
||||
Ok(Json(GetSlackOAuthConfigResponse {
|
||||
slack_oauth_client_id: settings.slack_oauth_client_id,
|
||||
@@ -2227,6 +2233,35 @@ async fn get_used_triggers(
|
||||
Ok(Json(websocket_used))
|
||||
}
|
||||
|
||||
async fn get_workspace_as_superadmin(
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
Path(w_id): Path<String>,
|
||||
) -> JsonResult<Workspace> {
|
||||
require_super_admin(&db, &authed.email).await?;
|
||||
let workspace = sqlx::query_as!(
|
||||
Workspace,
|
||||
"SELECT
|
||||
workspace.id AS \"id!\",
|
||||
workspace.name AS \"name!\",
|
||||
workspace.owner AS \"owner!\",
|
||||
workspace.deleted AS \"deleted!\",
|
||||
workspace.premium AS \"premium!\",
|
||||
workspace_settings.color AS \"color\",
|
||||
workspace.parent_workspace_id AS \"parent_workspace_id\"
|
||||
FROM workspace
|
||||
LEFT JOIN workspace_settings ON workspace.id = workspace_settings.workspace_id
|
||||
WHERE workspace.id = $1",
|
||||
w_id
|
||||
)
|
||||
.fetch_optional(&db)
|
||||
.await?;
|
||||
|
||||
let workspace = not_found_if_none(workspace, "workspace", w_id)?;
|
||||
|
||||
Ok(Json(workspace))
|
||||
}
|
||||
|
||||
async fn list_workspaces_as_super_admin(
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
|
||||
@@ -3,9 +3,11 @@ import { derived, type Readable, writable } from 'svelte/store'
|
||||
|
||||
import type { IntrospectionQuery } from 'graphql'
|
||||
import {
|
||||
CancelablePromise,
|
||||
type OperatorSettings,
|
||||
type TokenResponse,
|
||||
type UserWorkspaceList,
|
||||
type Workspace,
|
||||
type WorkspaceDefaultScripts,
|
||||
WorkspaceService
|
||||
} from './gen'
|
||||
@@ -168,32 +170,40 @@ export const instanceSettingsSelectedTab = writable('Core')
|
||||
|
||||
export const isCriticalAlertsUIOpen = writable(false)
|
||||
|
||||
let getWorkspacePromise: CancelablePromise<Workspace> | null = null
|
||||
export const workspaceColor: Readable<string | null | undefined> = derived(
|
||||
[workspaceStore, usersWorkspaceStore, superadmin],
|
||||
([workspaceStore, usersWorkspaceStore, superadmin], set: (value: string | undefined) => void) => {
|
||||
if (!workspaceStore) {
|
||||
set(undefined)
|
||||
if (!workspaceStore || !usersWorkspaceStore) {
|
||||
return
|
||||
}
|
||||
|
||||
// First try to get the color from usersWorkspaceStore
|
||||
const color = usersWorkspaceStore?.workspaces.find((w) => w.id === workspaceStore)?.color
|
||||
const workspace = usersWorkspaceStore.workspaces.find((w) => w.id === workspaceStore)
|
||||
|
||||
if (color) {
|
||||
set(color)
|
||||
if (workspace) {
|
||||
set(workspace.color)
|
||||
return
|
||||
}
|
||||
|
||||
// If not found and user is superadmin, try to get it from superadmin list
|
||||
// If workspace not found and user is superadmin, get it as superadmin
|
||||
if (!superadmin) {
|
||||
set(undefined)
|
||||
return
|
||||
}
|
||||
|
||||
WorkspaceService.listWorkspacesAsSuperAdmin().then((workspaces) => {
|
||||
const superadminColor = workspaces.find((w) => w.id === workspaceStore)?.color
|
||||
set(superadminColor)
|
||||
getWorkspacePromise?.cancel()
|
||||
|
||||
getWorkspacePromise = WorkspaceService.getWorkspaceAsSuperAdmin({
|
||||
workspace: workspaceStore
|
||||
})
|
||||
|
||||
getWorkspacePromise
|
||||
.then((workspace) => set(workspace.color))
|
||||
.catch((error) => {
|
||||
console.error('error getting workspace as superadmin', error)
|
||||
set(undefined)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user