mirror of
https://github.com/QuivrHQ/quivr.git
synced 2024-12-15 01:21:48 +03:00
feat: supabase vault (#1605)
# Description https://github.com/StanGirard/quivr/issues/1551 ## Checklist before requesting a review Please delete options that are not relevant. - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented hard-to-understand areas - [ ] I have ideally added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged ## Screenshots (if appropriate):
This commit is contained in:
parent
dd2bc1f6fc
commit
ed5de8b80c
3
backend/repository/external_api_secret/__init__.py
Normal file
3
backend/repository/external_api_secret/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
from .create_secret import create_secret
|
||||
from .delete_secret import delete_secret
|
||||
from .read_secret import read_secret
|
21
backend/repository/external_api_secret/create_secret.py
Normal file
21
backend/repository/external_api_secret/create_secret.py
Normal file
@ -0,0 +1,21 @@
|
||||
from uuid import UUID
|
||||
|
||||
from models import get_supabase_client
|
||||
from utils import build_secret_unique_name
|
||||
|
||||
|
||||
def create_secret(
|
||||
user_id: UUID, brain_id: UUID, secret_name: str, secret_value
|
||||
) -> UUID | None:
|
||||
supabase_client = get_supabase_client()
|
||||
response = supabase_client.rpc(
|
||||
"insert_secret",
|
||||
{
|
||||
"name": build_secret_unique_name(
|
||||
user_id=user_id, brain_id=brain_id, secret_name=secret_name
|
||||
),
|
||||
"secret": secret_value,
|
||||
},
|
||||
).execute()
|
||||
|
||||
return response.data
|
18
backend/repository/external_api_secret/delete_secret.py
Normal file
18
backend/repository/external_api_secret/delete_secret.py
Normal file
@ -0,0 +1,18 @@
|
||||
from uuid import UUID
|
||||
|
||||
from models import get_supabase_client
|
||||
from utils import build_secret_unique_name
|
||||
|
||||
|
||||
def delete_secret(user_id: UUID, brain_id: UUID, secret_name: str) -> bool:
|
||||
supabase_client = get_supabase_client()
|
||||
response = supabase_client.rpc(
|
||||
"delete_secret",
|
||||
{
|
||||
"name": build_secret_unique_name(
|
||||
user_id=user_id, brain_id=brain_id, secret_name=secret_name
|
||||
),
|
||||
},
|
||||
).execute()
|
||||
|
||||
return response.data
|
20
backend/repository/external_api_secret/read_secret.py
Normal file
20
backend/repository/external_api_secret/read_secret.py
Normal file
@ -0,0 +1,20 @@
|
||||
from uuid import UUID
|
||||
|
||||
from models import get_supabase_client
|
||||
from utils import build_secret_unique_name
|
||||
|
||||
|
||||
def read_secret(
|
||||
user_id: UUID, brain_id: UUID, secret_name: str, secret_value
|
||||
) -> UUID | None:
|
||||
supabase_client = get_supabase_client()
|
||||
response = supabase_client.rpc(
|
||||
"read_secret",
|
||||
{
|
||||
"secret_name": build_secret_unique_name(
|
||||
user_id=user_id, brain_id=brain_id, secret_name=secret_name
|
||||
),
|
||||
},
|
||||
).execute()
|
||||
|
||||
return response.data
|
5
backend/repository/external_api_secret/utils.py
Normal file
5
backend/repository/external_api_secret/utils.py
Normal file
@ -0,0 +1,5 @@
|
||||
from uuid import UUID
|
||||
|
||||
|
||||
def build_secret_unique_name(user_id: UUID, brain_id: UUID, secret_name: str):
|
||||
return f"{user_id}-{brain_id}-{secret_name}"
|
53
scripts/20231107104700_setup_vault.sql
Normal file
53
scripts/20231107104700_setup_vault.sql
Normal file
@ -0,0 +1,53 @@
|
||||
CREATE OR REPLACE FUNCTION insert_secret(name text, secret text)
|
||||
returns uuid
|
||||
language plpgsql
|
||||
security definer
|
||||
set search_path = public
|
||||
as $$
|
||||
begin
|
||||
return vault.create_secret(secret, name);
|
||||
end;
|
||||
$$;
|
||||
|
||||
|
||||
create or replace function read_secret(secret_name text)
|
||||
returns text
|
||||
language plpgsql
|
||||
security definer set search_path = public
|
||||
as $$
|
||||
declare
|
||||
secret text;
|
||||
begin
|
||||
select decrypted_secret from vault.decrypted_secrets where name =
|
||||
secret_name into secret;
|
||||
return secret;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function delete_secret(secret_name text)
|
||||
returns text
|
||||
language plpgsql
|
||||
security definer set search_path = public
|
||||
as $$
|
||||
declare
|
||||
deleted_rows int;
|
||||
begin
|
||||
delete from vault.decrypted_secrets where name = secret_name;
|
||||
get diagnostics deleted_rows = row_count;
|
||||
if deleted_rows = 0 then
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
end if;
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- Insert a migration record if it doesn't exist
|
||||
INSERT INTO migrations (name)
|
||||
SELECT '20231107104700_setup_vault'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM migrations WHERE name = '20231107104700_setup_vault'
|
||||
);
|
||||
|
||||
-- Commit the changes
|
||||
COMMIT;
|
@ -167,13 +167,59 @@ CREATE TABLE IF NOT EXISTS brain_subscription_invitations (
|
||||
FOREIGN KEY (brain_id) REFERENCES brains (brain_id)
|
||||
);
|
||||
|
||||
-- Create functions for secrets in vault
|
||||
CREATE OR REPLACE FUNCTION insert_secret(name text, secret text)
|
||||
returns uuid
|
||||
language plpgsql
|
||||
security definer
|
||||
set search_path = public
|
||||
as $$
|
||||
begin
|
||||
return vault.create_secret(secret, name);
|
||||
end;
|
||||
$$;
|
||||
|
||||
|
||||
create or replace function read_secret(secret_name text)
|
||||
returns text
|
||||
language plpgsql
|
||||
security definer set search_path = public
|
||||
as $$
|
||||
declare
|
||||
secret text;
|
||||
begin
|
||||
select decrypted_secret from vault.decrypted_secrets where name =
|
||||
secret_name into secret;
|
||||
return secret;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function delete_secret(secret_name text)
|
||||
returns text
|
||||
language plpgsql
|
||||
security definer set search_path = public
|
||||
as $$
|
||||
declare
|
||||
deleted_rows int;
|
||||
begin
|
||||
delete from vault.decrypted_secrets where name = secret_name;
|
||||
get diagnostics deleted_rows = row_count;
|
||||
if deleted_rows = 0 then
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
end if;
|
||||
end;
|
||||
$$;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS migrations (
|
||||
name VARCHAR(255) PRIMARY KEY,
|
||||
executed_at TIMESTAMPTZ DEFAULT current_timestamp
|
||||
);
|
||||
|
||||
INSERT INTO migrations (name)
|
||||
SELECT '202307111517031_change_vectors_id_type'
|
||||
SELECT '20231107104700_setup_vault'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM migrations WHERE name = '202307111517031_change_vectors_id_type'
|
||||
SELECT 1 FROM migrations WHERE name = '20231107104700_setup_vault'
|
||||
);
|
@ -398,10 +398,54 @@ CREATE POLICY "Access Quivr Storage 1jccrwz_2" ON storage.objects FOR UPDATE TO
|
||||
|
||||
CREATE POLICY "Access Quivr Storage 1jccrwz_3" ON storage.objects FOR DELETE TO anon USING (bucket_id = 'quivr');
|
||||
|
||||
-- Create functions for secrets in vault
|
||||
CREATE OR REPLACE FUNCTION insert_secret(name text, secret text)
|
||||
returns uuid
|
||||
language plpgsql
|
||||
security definer
|
||||
set search_path = public
|
||||
as $$
|
||||
begin
|
||||
return vault.create_secret(secret, name);
|
||||
end;
|
||||
$$;
|
||||
|
||||
|
||||
create or replace function read_secret(secret_name text)
|
||||
returns text
|
||||
language plpgsql
|
||||
security definer set search_path = public
|
||||
as $$
|
||||
declare
|
||||
secret text;
|
||||
begin
|
||||
select decrypted_secret from vault.decrypted_secrets where name =
|
||||
secret_name into secret;
|
||||
return secret;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function delete_secret(secret_name text)
|
||||
returns text
|
||||
language plpgsql
|
||||
security definer set search_path = public
|
||||
as $$
|
||||
declare
|
||||
deleted_rows int;
|
||||
begin
|
||||
delete from vault.decrypted_secrets where name = secret_name;
|
||||
get diagnostics deleted_rows = row_count;
|
||||
if deleted_rows = 0 then
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
end if;
|
||||
end;
|
||||
$$;
|
||||
|
||||
|
||||
INSERT INTO migrations (name)
|
||||
SELECT '20231106110000_add_field_brain_type_to_brain_table'
|
||||
SELECT '20231107104700_setup_vault'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM migrations WHERE name = '20231106110000_add_field_brain_type_to_brain_table'
|
||||
SELECT 1 FROM migrations WHERE name = '20231107104700_setup_vault'
|
||||
);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user