Compare commits

...

1 Commits

Author SHA1 Message Date
wendrul
2cd52d8468 WIP: In pause for now because of uncertainty about the feature 2025-01-28 18:11:28 +01:00
5 changed files with 112 additions and 13 deletions

View File

@@ -0,0 +1,37 @@
-- Add down migration script here
DO
$do$
DECLARE
i text;
arr text[] := array['resource', 'variable'];
BEGIN
FOREACH i IN ARRAY arr
LOOP
EXECUTE FORMAT(
$$
DROP POLICY see_globally_shared_resource ON %1$I
$$,
i
);
END LOOP;
END
$do$;
DO
$do$
DECLARE
i text;
arr text[] := array['variable', 'resource'];
BEGIN
FOREACH i IN ARRAY arr
LOOP
EXECUTE FORMAT(
$$
ALTER TABLE %1$I DROP CONSTRAINT proper_id;
ALTER TABLE %1$I ADD CONSTRAINT proper_id CHECK (path ~ '^[ufg](\/[\w-]+){2,}$');
$$,
i
);
END LOOP;
END
$do$;

View File

@@ -0,0 +1,37 @@
DO
$do$
DECLARE
i text;
arr text[] := array['resource', 'variable'];
BEGIN
FOREACH i IN ARRAY arr
LOOP
EXECUTE FORMAT(
$$
CREATE POLICY see_globally_shared_resource ON %1$I FOR SELECT
USING (SPLIT_PART(%1$I.path, '/', 1) = 's');
$$,
i
);
END LOOP;
END
$do$;
DO
$do$
DECLARE
i text;
arr text[] := array['variable', 'resource'];
BEGIN
FOREACH i IN ARRAY arr
LOOP
EXECUTE FORMAT(
$$
ALTER TABLE %1$I DROP CONSTRAINT proper_id;
ALTER TABLE %1$I ADD CONSTRAINT proper_id CHECK (path ~ '^[ufgs](\/[\w-]+){2,}$');
$$,
i
);
END LOOP;
END
$do$;

View File

@@ -157,7 +157,7 @@ async fn list_names(
) -> JsonResult<Vec<NamePath>> {
let mut tx = user_db.begin(&authed).await?;
let rows = sqlx::query!(
"SELECT value->>'name' as name, path from resource WHERE resource_type = $1 AND workspace_id = $2",
"SELECT value->>'name' as name, path from resource WHERE resource_type = $1 AND workspace_id = $2 OR (workspace_id = 'admins' AND path LIKE 's/%')",
rt,
&w_id
)
@@ -189,7 +189,7 @@ async fn list_search_resources(
let rows = sqlx::query_as!(
SearchResource,
"SELECT path, value from resource WHERE workspace_id = $1 LIMIT $2",
"SELECT path, value from resource WHERE workspace_id = $1 OR (workspace_id = 'admins' AND path LIKE 's/%') LIMIT $2",
&w_id,
n
)
@@ -235,6 +235,7 @@ async fn list_resources(
.on("variable.account = account.id AND account.workspace_id = variable.workspace_id")
.order_by("path", true)
.and_where("resource.workspace_id = ?".bind(&w_id))
.or_where("(resource.workspace_id = ? AND resource.path LIKE ?)".bind(&"admins").bind(&"s/%"))
.offset(offset)
.limit(per_page)
.clone();
@@ -290,9 +291,9 @@ async fn get_resource(
variable.is_oauth as \"is_oauth?\",
variable.account
FROM resource
LEFT JOIN variable ON variable.path = resource.path AND variable.workspace_id = $2
LEFT JOIN account ON variable.account = account.id AND account.workspace_id = $2
WHERE resource.path = $1 AND resource.workspace_id = $2",
LEFT JOIN variable ON variable.path = resource.path AND variable.workspace_id = $2 OR (variable.workspace_id = 'admins' AND variable.path LIKE 's/%')
LEFT JOIN account ON variable.account = account.id AND account.workspace_id = $2 OR (account.workspace_id = 'admins' AND variable.path LIKE 's/%')
WHERE resource.path = $1 AND resource.workspace_id = $2 OR (resource.workspace_id = 'admins' AND resource.path LIKE 's/%')",
path.to_owned(),
&w_id
)
@@ -313,7 +314,7 @@ async fn exists_resource(
let path = path.to_path();
let exists = sqlx::query_scalar!(
"SELECT EXISTS(SELECT 1 FROM resource WHERE path = $1 AND workspace_id = $2)",
"SELECT EXISTS(SELECT 1 FROM resource WHERE path = $1 AND (workspace_id = $2 OR (workspace_id = 'admins' AND path LIKE 's/%')) )",
path,
w_id
)
@@ -334,7 +335,7 @@ async fn get_resource_value(
let mut tx = user_db.begin(&authed).await?;
let value_o = sqlx::query_scalar!(
"SELECT value from resource WHERE path = $1 AND workspace_id = $2",
"SELECT value from resource WHERE path = $1 AND (workspace_id = $2 OR (workspace_id = 'admins' AND path LIKE 's/%'))",
path.to_owned(),
&w_id
)
@@ -357,7 +358,7 @@ async fn explain_resource_perm_error(
authed: &ApiAuthed,
) -> windmill_common::error::Result<()> {
let extra_perms = sqlx::query_scalar!(
"SELECT extra_perms from resource WHERE path = $1 AND workspace_id = $2",
"SELECT extra_perms from resource WHERE path = $1 AND (workspace_id = $2 OR (workspace_id = 'admins' AND path LIKE 's/%'))",
path,
w_id
)
@@ -450,7 +451,7 @@ pub async fn get_resource_value_interpolated_internal(
let mut tx = authed_transaction_or_default(authed, user_db.clone(), db).await?;
let value_o = sqlx::query_scalar!(
"SELECT value from resource WHERE path = $1 AND workspace_id = $2",
"SELECT value from resource WHERE path = $1 AND (workspace_id = $2 OR (workspace_id = 'admins' AND path LIKE 's/%'))",
path,
workspace
)
@@ -521,7 +522,7 @@ pub async fn transform_json_value<'c>(
let mut tx: Transaction<'_, Postgres> =
authed_transaction_or_default(authed, user_db.clone(), db).await?;
let v = sqlx::query_scalar!(
"SELECT value from resource WHERE path = $1 AND workspace_id = $2",
"SELECT value from resource WHERE path = $1 AND (workspace_id = $2 OR (workspace_id = 'admins' AND path LIKE 's/%'))",
path,
&workspace
)
@@ -538,7 +539,7 @@ pub async fn transform_json_value<'c>(
Value::String(y) if y.starts_with("$") && job_id.is_some() => {
let mut tx = authed_transaction_or_default(authed, user_db.clone(), db).await?;
let job = sqlx::query_as::<_, QueuedJob>(
"SELECT * FROM queue WHERE id = $1 AND workspace_id = $2",
"SELECT * FROM queue WHERE id = $1 AND (workspace_id = $2 OR (workspace_id = 'admins' AND path LIKE 's/%'))",
)
.bind(job_id.unwrap())
.bind(workspace)

View File

@@ -1,6 +1,6 @@
import type { Script } from './gen'
export type OwnerKind = 'group' | 'user' | 'folder'
export type OwnerKind = 'group' | 'user' | 'folder' | 'shared'
export type ActionKind = 'Create' | 'Update' | 'Delete' | 'Execute'

View File

@@ -27,7 +27,7 @@
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
import FolderEditor from './FolderEditor.svelte'
import { random_adj } from './random_positive_adjetive'
import { Eye, Folder, Plus, SearchCode, User } from 'lucide-svelte'
import { Earth, Eye, Folder, Plus, SearchCode, User } from 'lucide-svelte'
type PathKind =
| 'resource'
@@ -353,6 +353,8 @@
if (meta) {
if (kind === 'folder') {
meta.owner = folders?.[0]?.name ?? ''
} else if (kind === 'shared') {
meta.owner = 'global'
} else if (kind === 'group') {
meta.owner = 'all'
} else {
@@ -380,6 +382,18 @@
position="right"
label="Folder"
/>
{#if $workspaceStore === 'admins' && (kind === 'resource' || kind == 'variable')}
<ToggleButton
icon={Earth}
{disabled}
light
tooltip={`This ${kind} will be shared with everyone across all workspaces. But it can only be created and edited from the admins workspace`}
size="xs"
value="shared"
position="right"
label="Global"
/>
{/if}
</ToggleButtonGroup>
</div>
{/if}
@@ -398,6 +412,16 @@
on:keydown={setDirty}
/>
</label>
{:else if meta.ownerKind === 'shared'}
<label class="block shrink min-w-0">
<input
class="!w-36"
type="text"
bind:value={meta.owner}
placeholder="global"
on:keydown={setDirty}
/>
</label>
{:else if meta.ownerKind === 'folder'}
<label class="block grow w-48">
<div class="flex flex-row items-center gap-1 w-full">