Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] Remove/Document implicit assumptions on postgres roles and priviledge #861

Closed
khorshuheng opened this issue Oct 5, 2024 · 7 comments

Comments

@khorshuheng
Copy link
Collaborator

khorshuheng commented Oct 5, 2024

Currently, there are some implicit assumptions being made on the postgres roles and priviledge that are not well documented:

  1. It is assumed that the user will run the following migration script on database start:
    - ./migrations/before:/docker-entrypoint-initdb.d
    . This migration script assumes that the postgres user executing the script has the priviledge of creating roles.
  2. anon, supabase_auth_admin and authenticated postgres user/role are assumed to exists. which are supposed to be created by the script above. However, the anon and authenticated requirement are likely due to dependency on supabase in the past, which is no longer the case. If possible, the dependencies to these roles should be removed.
  3. Without anon and authenticated roles, the following migrations will fail:
  • 20230312043023_user.sql
  • 20230906101222_workspace.sql
  • 20230906102651_collab.sql
  1. It is also assumed that the database name is "postgres", due to: https://github.com/AppFlowy-IO/AppFlowy-Cloud/blob/9c0dffacef6b58070002d988fffd92d09e5516a8/migrations/before/20230312043000_supabase_auth.sql#L35C22-L35C58 .
  2. The postgres user used by gotrue service is assumed to be supabase_auth_admin and the password is hard coded to root (
    ) THEN CREATE USER supabase_auth_admin BYPASSRLS NOINHERIT CREATEROLE LOGIN NOREPLICATION PASSWORD 'root';
    ) Using a different database url can result in gotrue service start up error due to lack of access to auth schema / not able to find the auth schema.
  3. It is assumed that both gotrue and appflowy cloud service shares the same database, and the default search path for supabase_auth_admin is the auth schema. Otherwise, appflowy cloud will fail during start up, due to:
    let result = sqlx::query!(
  4. The database user for AppFlowy Cloud must be able to access and modify the tables in the auth schema. Several migrations in AppFlowy Cloud modifies the tables in auth schema.
  5. The before_migration script didn't grant appflowy cloud's database user the above priviledge. The docker compose setup will only work if the database user happens to be a superuser eg. postgres.
  6. Likewise, it is also assumed that the appflowy database user can create postgres extension eg. pgvector. This is not possible unless the user is superuser.
@khorshuheng khorshuheng changed the title [FR] Remove implicit assumptions on postgres roles and priviledge [FR] Remove/Document implicit assumptions on postgres roles and priviledge Oct 5, 2024
@Schoumi
Copy link

Schoumi commented Oct 5, 2024

You've summarize the problem I encounter/have encounter trying to run AppFlowy Cloud outside of docker.
The fact that the user is not a superuser make that all migration with public schema in it fails since they are created with auth schema. You have to change any mention of postgres/supabase_auth_admin in these scripts,...
20231130150000_user_id_foreign_key.sql REVOKE Rights granted in a previous migration that doesn't affect postgres superuser but affect any other user

I don't know how your ORM work and if it's possible. In Android SQLite Core Library exist a version number that correspond to the version of physical data model of the database. Dev has to make two function: onCreate and onUpgrade.

  • onCreate create the schema for the last version of the physical data model if it's the first installation of the app. New user doesn't have to go througt any migrations. This functions is execute one and only one time.
  • onUpgrade has the old database version and the new database version. It allow devs to make migrations for user that already have the app installed before and have to run some migrations.

I love this approach because new installation has the latest and cleanest version out of the box without any migration. Devs can read the onCreate function to know what is the physical data model and it work the same if you use Room has ORM (Entity Driven).

Anyway this is all the script i have to modify (supabase_auth_admin/public/postgres/rights management problems):

	modified :         migrations/20230312043023_user.sql
	modified :         migrations/20231130140000_user_delete_trigger.sql
	modified :         migrations/20231130150000_user_id_foreign_key.sql
	modified :         migrations/20240123140707_workspace_owner_trigger.sql
	modified :         migrations/20240304173938_workspace_invitation.sql
	modified :         migrations/20240306110000_workspace_invitation_2.sql
	modified :         migrations/20240626184736_publish_collab_4.sql
	modified :         migrations/20240627525836_publish_collab_5.sql
	modified :         migrations/20240629035230_publish_collab_6.sql
	modified :         migrations/20240630010030_workspace_member_foreign_key.sql
	modified :         migrations/20240910100000_af_collab_embeddings_indices.sql

The last problem I encounter, is after receiving the magic link my user can't create user in af_user table because of row low-level security policies. I suppose it has not the anon or authenticated role only supabase_admin or none (not sure on this one if role supposed to be the column role in auth.users table or something else). (see #838 (comment))

select * from pg_policies;
 schemaname |      tablename      |         policyname         | permissive |        roles         |  cmd   | qual | with_check 
------------+---------------------+----------------------------+------------+----------------------+--------+------+------------
 auth       | af_user             | af_user_select_policy      | PERMISSIVE | {anon,authenticated} | SELECT | true | 
 auth       | af_user             | af_user_update_policy      | PERMISSIVE | {public}             | UPDATE | true | true
 auth       | af_user             | af_user_insert_policy      | PERMISSIVE | {anon,authenticated} | INSERT |      | true
 auth       | af_workspace_member | af_workspace_member_policy | PERMISSIVE | {anon,authenticated} | ALL    | true | 
 auth       | af_workspace        | af_workspace_policy        | PERMISSIVE | {anon,authenticated} | ALL    | true | 
 auth       | af_collab           | af_collab_policy           | PERMISSIVE | {anon,authenticated} | ALL    | true | 

Postgres error log

ERROR:  new row violates row-level security policy for table "af
_user"
2024-10-04 22:33:38.682 UTC [8711] user@database STATEMENT:  
            WITH ins_user AS (
                INSERT INTO af_user (uid, uuid, email, name)
                VALUES ($1, $2, $3, $4)
                RETURNING uid
            ),
            owner_role AS (
                SELECT id FROM af_roles WHERE name = 'Owner'
            ),
            ins_workspace AS (
                INSERT INTO af_workspace (owner_uid)
                SELECT uid FROM ins_user
                RETURNING workspace_id, owner_uid
            ),
            ins_collab_member AS (
                INSERT INTO af_collab_member (uid, oid, permission_id)
                SELECT ins_workspace.owner_uid,
                       ins_workspace.workspace_id::TEXT,
                       (SELECT permission_id FROM af_role_permissions WHERE role_id = owner_role.id)
                FROM ins_workspace, owner_role
            )
            SELECT workspace_id FROM ins_workspace;

Thanks for your work, let me know if I can help you in any way.

@khorshuheng
Copy link
Collaborator Author

khorshuheng commented Oct 6, 2024

Let me look into the row security issue, I might have been too hasty in concluding that anon and authenticated roles can be deprecated.

In any case, the requirement of running AppFlowy cloud using postgres superuser is certainly not ideal, though patching the schema in a way that doesn't break existing installation is going to be tricky. We don't use ORM, but we do use the sqlx library to handle our migration. I don't remember seeing an equivalent of onCreate and onUpgrade for the library, but I will check again.

@khorshuheng
Copy link
Collaborator Author

khorshuheng commented Oct 6, 2024

@Schoumi I was able to reproduce your issue on my local deployment. Debugging now.

@khorshuheng
Copy link
Collaborator Author

Row level security will need to be removed from these migrations so that appflowy can use non-superuser:

  • migrations/20230312043023_user_patched_20241006.sql
  • migrations/20230906101222_workspace_patched_20241006.sql
  • migrations/20230906102651_collab_patched_20241006.sql

I don't think we need row level security, though more testing is need. Although changing these migration files will certainly break existing installation due to checksum mismatch. Finding ways to circumvent this.

@khorshuheng
Copy link
Collaborator Author

@Schoumi May i also know what changes have you made to the tables? I was able to get the services running with non-postgres user, different database name, and also separate user for gotrue service, but i didn't modify as many migrations.

@Schoumi
Copy link

Schoumi commented Oct 6, 2024

I may have been a bit violent with the modifications since i have made them with sed :)
Since they exist 37 migrations scripts i didn't want to debug one by one.

index 07bb72b7..b6264840 100644
--- a/migrations/20230312043023_user.sql
+++ b/migrations/20230312043023_user.sql
@@ -33,14 +33,14 @@ UPDATE ON af_user FOR EACH ROW EXECUTE FUNCTION prevent_reset_encryption_sign_fu
 -- Enable RLS on the af_user table
 -- Policy for INSERT
 ALTER TABLE af_user ENABLE ROW LEVEL SECURITY;
-CREATE POLICY af_user_insert_policy ON public.af_user FOR
+CREATE POLICY af_user_insert_policy ON auth.af_user FOR
 INSERT TO anon,
     authenticated WITH CHECK (true);
 -- Policy for UPDATE
-CREATE POLICY af_user_update_policy ON public.af_user FOR
+CREATE POLICY af_user_update_policy ON auth.af_user FOR
 UPDATE USING (true) WITH CHECK (true);
 -- Policy for SELECT
-CREATE POLICY af_user_select_policy ON public.af_user FOR
+CREATE POLICY af_user_select_policy ON auth.af_user FOR
 SELECT TO anon,
     authenticated USING (true);
 ALTER TABLE af_user FORCE ROW LEVEL SECURITY;
index c89c669a..25364f36 100644
--- a/migrations/20231130140000_user_delete_trigger.sql
+++ b/migrations/20231130140000_user_delete_trigger.sql
@@ -1,28 +1,28 @@
-GRANT SELECT, INSERT, UPDATE, DELETE ON public.af_user TO supabase_auth_admin;
+GRANT SELECT, INSERT, UPDATE, DELETE ON auth.af_user TO myuser;
 
--- Trigger Function to delete a user from the pulic.af_user table
+-- Trigger Function to delete a user from the auth.af_user table
 -- when a user is deleted from auth.users table (with matching uuid) field
-CREATE OR REPLACE FUNCTION public.delete_user()
+CREATE OR REPLACE FUNCTION auth.delete_user()
 RETURNS TRIGGER AS $$
 BEGIN
-    DELETE FROM public.af_user WHERE uuid = OLD.id;
+    DELETE FROM auth.af_user WHERE uuid = OLD.id;
     RETURN OLD;
 END;
 $$ LANGUAGE plpgsql;
 
 CREATE TRIGGER delete_user_trigger
 AFTER DELETE ON auth.users
-FOR EACH ROW EXECUTE FUNCTION public.delete_user();
+FOR EACH ROW EXECUTE FUNCTION auth.delete_user();
 
--- Trigger Function to update the 'deleted_at' field in the pulic.af_user table
+-- Trigger Function to update the 'deleted_at' field in the auth.af_user table
 -- (Soft Delete)
-CREATE OR REPLACE FUNCTION public.update_af_user_deleted_at()
+CREATE OR REPLACE FUNCTION auth.update_af_user_deleted_at()
 RETURNS TRIGGER AS $$
 BEGIN
     -- Check if 'deleted_at' field is modified
     IF OLD.deleted_at IS DISTINCT FROM NEW.deleted_at THEN
-        -- Update 'deleted_at' in public.af_user
-        UPDATE public.af_user
+        -- Update 'deleted_at' in auth.af_user
+        UPDATE auth.af_user
         SET deleted_at = NEW.deleted_at
         WHERE uuid = NEW.id;
     END IF;
@@ -32,4 +32,4 @@ $$ LANGUAGE plpgsql;
 
 CREATE TRIGGER update_af_user_deleted_at_trigger
 AFTER UPDATE OF deleted_at ON auth.users
-FOR EACH ROW EXECUTE FUNCTION public.update_af_user_deleted_at();
+FOR EACH ROW EXECUTE FUNCTION auth.update_af_user_deleted_at();
index 12be9e89..adaa38b3 100644
--- a/migrations/20231130150000_user_id_foreign_key.sql
+++ b/migrations/20231130150000_user_id_foreign_key.sql
@@ -1,20 +1,20 @@
 -- Revert the last migration
-REVOKE SELECT, INSERT, UPDATE, DELETE ON public.af_user FROM supabase_auth_admin;
+--REVOKE SELECT, INSERT, UPDATE, DELETE ON auth.af_user FROM myuser;
 DROP TRIGGER delete_user_trigger ON auth.users;
 DROP TRIGGER update_af_user_deleted_at_trigger ON auth.users;
-DROP FUNCTION public.delete_user();
-DROP FUNCTION public.update_af_user_deleted_at();
+DROP FUNCTION auth.delete_user();
+DROP FUNCTION auth.update_af_user_deleted_at();
 
--- Delete all users from public.af_user table that are not in auth.users table
-DELETE FROM public.af_user
+-- Delete all users from auth.af_user table that are not in auth.users table
+DELETE FROM auth.af_user
 WHERE NOT EXISTS (
     SELECT 1
     FROM auth.users
     WHERE af_user.uuid = users.id
 );
 
--- Add foreign key constraint to public.af_user table
-ALTER TABLE public.af_user
+-- Add foreign key constraint to auth.af_user table
+ALTER TABLE auth.af_user
 ADD CONSTRAINT af_user_email_foreign_key
 FOREIGN KEY (uuid)
 REFERENCES auth.users(id)
index 3ae74b50..bac9a012 100644
--- a/migrations/20240123140707_workspace_owner_trigger.sql
+++ b/migrations/20240123140707_workspace_owner_trigger.sql
@@ -2,11 +2,11 @@ CREATE OR REPLACE FUNCTION af_workspace_insert_trigger()
 RETURNS TRIGGER AS $$
 BEGIN
     -- Insert a record into af_workspace_member
-    INSERT INTO public.af_workspace_member (
+    INSERT INTO auth.af_workspace_member (
 	uid, role_id,
 	workspace_id, created_at, updated_at)
     VALUES (
-	NEW.owner_uid, (SELECT id FROM public.af_roles WHERE name = 'Owner'),
+	NEW.owner_uid, (SELECT id FROM auth.af_roles WHERE name = 'Owner'),
 	NEW.workspace_id, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
 
     -- Return the new record to complete the insert operation
@@ -15,6 +15,6 @@ END;
 $$ LANGUAGE plpgsql;
 
 CREATE TRIGGER af_workspace_after_insert
-AFTER INSERT ON public.af_workspace
+AFTER INSERT ON auth.af_workspace
 FOR EACH ROW
 EXECUTE FUNCTION af_workspace_insert_trigger();
index 998cee13..6de36edf 100644
--- a/migrations/20240304173938_workspace_invitation.sql
+++ b/migrations/20240304173938_workspace_invitation.sql
@@ -45,8 +45,8 @@ BEGIN
       NEW.invitee,
       NEW.workspace_id,
       (SELECT permission_id
-       FROM public.af_role_permissions
-       WHERE public.af_role_permissions.role_id = NEW.role_id)
+       FROM auth.af_role_permissions
+       WHERE auth.af_role_permissions.role_id = NEW.role_id)
     )
     ON CONFLICT (uid, oid)
     DO UPDATE
index 8c301d34..3949185c 100644
--- a/migrations/20240306110000_workspace_invitation_2.sql
+++ b/migrations/20240306110000_workspace_invitation_2.sql
@@ -20,8 +20,8 @@ BEGIN
       (SELECT uid FROM af_user WHERE email = NEW.invitee_email),
       NEW.workspace_id,
       (SELECT permission_id
-       FROM public.af_role_permissions
-       WHERE public.af_role_permissions.role_id = NEW.role_id)
+       FROM auth.af_role_permissions
+       WHERE auth.af_role_permissions.role_id = NEW.role_id)
     )
     ON CONFLICT (uid, oid)
     DO UPDATE
index f2a5b62a..514b49d3 100644
--- a/migrations/20240626184736_publish_collab_4.sql
+++ b/migrations/20240626184736_publish_collab_4.sql
@@ -1,6 +1,6 @@
 -- Add a unique constraint on publish_name
-ALTER TABLE public.af_published_collab
+ALTER TABLE auth.af_published_collab
 ADD CONSTRAINT unique_publish_name UNIQUE (publish_name);
 
 -- Add an index on publish_name
-CREATE INDEX idx_publish_name ON public.af_published_collab (publish_name);
+CREATE INDEX idx_publish_name ON auth.af_published_collab (publish_name);
index 605ab2f3..48f49694 100644
--- a/migrations/20240627525836_publish_collab_5.sql
+++ b/migrations/20240627525836_publish_collab_5.sql
@@ -1,7 +1,7 @@
 -- Drop the existing unique constraint on publish_name
-ALTER TABLE public.af_published_collab
+ALTER TABLE auth.af_published_collab
 DROP CONSTRAINT unique_publish_name;
 
 -- Add a new unique constraint for the combination of publish_name and workspace_id
-ALTER TABLE public.af_published_collab
+ALTER TABLE auth.af_published_collab
 ADD CONSTRAINT unique_workspace_id_publish_name UNIQUE (workspace_id, publish_name);
index 7a6ae459..b32e4ef8 100644
--- a/migrations/20240629035230_publish_collab_6.sql
+++ b/migrations/20240629035230_publish_collab_6.sql
@@ -1,9 +1,9 @@
 -- Update existing null values to ensure no nulls are present before adding NOT NULL constraint
-UPDATE public.af_workspace
+UPDATE auth.af_workspace
 SET publish_namespace = uuid_generate_v4()::text
 WHERE publish_namespace IS NULL;
 
 -- Alter the column to set NOT NULL constraint and a default value
-ALTER TABLE public.af_workspace
+ALTER TABLE auth.af_workspace
 ALTER COLUMN publish_namespace SET NOT NULL,
 ALTER COLUMN publish_namespace SET DEFAULT uuid_generate_v4()::text;
index 9ff48923..f4211813 100644
--- a/migrations/20240630010030_workspace_member_foreign_key.sql
+++ b/migrations/20240630010030_workspace_member_foreign_key.sql
@@ -1,3 +1,3 @@
-ALTER TABLE public.af_workspace_member
+ALTER TABLE auth.af_workspace_member
 ADD CONSTRAINT af_workspace_member_uid_fkey
 FOREIGN KEY (uid) REFERENCES af_user(uid) ON DELETE CASCADE;
index a96761d4..4c479473 100644
--- a/migrations/20240910100000_af_collab_embeddings_indices.sql
+++ b/migrations/20240910100000_af_collab_embeddings_indices.sql
@@ -1,6 +1,6 @@
 DO $$
 BEGIN
-    CREATE INDEX IF NOT EXISTS af_collab_embeddings_oid_idx ON public.af_collab_embeddings (oid);
+    CREATE INDEX IF NOT EXISTS af_collab_embeddings_oid_idx ON auth.af_collab_embeddings (oid);
 EXCEPTION WHEN others THEN
     RAISE NOTICE 'could not create index on af_collab_embeddings(oid), ignoring this migration';
 END $$;

And yes i confirm the checksum fail if you modify a migration script that has been already run. I did try that when i remove the line that revoke access to my user.

Remove low level security will not be the problem, you can do that in a migration script. The major problem is migrate from postgres/supabase_auth_admin to the user/pass/db set in environment variable. I've no knowledge of postgres but maybe is it possible to rename db/user and migrate data from one db to another as superadmin? With that, you'll have to use default values to run all migrations and after the new one is applied you'll use new database/user/password for that

@Schoumi
Copy link

Schoumi commented Oct 15, 2024

Update i've been able to run it perfectly with some adjustment and a cargo sqlx prepare --workspace I've not tested AI part for now but login, workspace edit sync with smartphone.

index 59e9a1df..7797d168 100644
--- a/libs/database/src/chat/chat_ops.rs
+++ b/libs/database/src/chat/chat_ops.rs
@@ -434,7 +434,7 @@ pub async fn select_chat_messages(
   let total = sqlx::query_scalar!(
     r#"
         SELECT COUNT(*)
-        FROM public.af_chat_messages
+        FROM af_chat_messages
         WHERE chat_id = $1
         "#,
     &chat_id
index 56a31bc5..8cf8c300 100644
--- a/libs/database/src/workspace.rs
+++ b/libs/database/src/workspace.rs
@@ -20,7 +20,7 @@ use app_error::AppError;
 pub async fn delete_from_workspace(pg_pool: &PgPool, workspace_id: &Uuid) -> Result<(), AppError> {
   let pg_row = sqlx::query!(
     r#"
-    DELETE FROM public.af_workspace where workspace_id = $1
+    DELETE FROM af_workspace where workspace_id = $1
     "#,
     workspace_id
   )
@@ -42,8 +42,8 @@ pub async fn insert_user_workspace(
     AFWorkspaceRow,
     r#"
     WITH new_workspace AS (
-      INSERT INTO public.af_workspace (owner_uid, workspace_name, is_initialized)
-      VALUES ((SELECT uid FROM public.af_user WHERE uuid = $1), $2, $3)
+      INSERT INTO af_workspace (owner_uid, workspace_name, is_initialized)
+      VALUES ((SELECT uid FROM af_user WHERE uuid = $1), $2, $3)
       RETURNING *
     )
     SELECT
@@ -58,7 +58,7 @@ pub async fn insert_user_workspace(
       workspace_name,
       icon
     FROM new_workspace
-    JOIN public.af_user AS owner_profile ON new_workspace.owner_uid = owner_profile.uid;
+    JOIN af_user AS owner_profile ON new_workspace.owner_uid = owner_profile.uid;
     "#,
     user_uuid,
     workspace_name,
@@ -78,7 +78,7 @@ pub async fn rename_workspace(
 ) -> Result<(), AppError> {
   let res = sqlx::query!(
     r#"
-      UPDATE public.af_workspace
+      UPDATE af_workspace
       SET workspace_name = $1
       WHERE workspace_id = $2
     "#,
@@ -102,7 +102,7 @@ pub async fn change_workspace_icon(
 ) -> Result<(), AppError> {
   let res = sqlx::query!(
     r#"
-      UPDATE public.af_workspace
+      UPDATE af_workspace
       SET icon = $1
       WHERE workspace_id = $2
     "#,
@@ -133,11 +133,11 @@ pub async fn select_user_is_workspace_owner(
     r#"
   SELECT EXISTS(
     SELECT 1
-    FROM public.af_workspace_member
+    FROM af_workspace_member
       JOIN af_roles ON af_workspace_member.role_id = af_roles.id
     WHERE workspace_id = $1
     AND af_workspace_member.uid = (
-      SELECT uid FROM public.af_user WHERE uuid = $2
+      SELECT uid FROM af_user WHERE uuid = $2
     )
     AND af_roles.name = 'Owner'
   ) AS "exists";
@@ -265,9 +265,9 @@ pub async fn upsert_workspace_member_with_txn(
   let role_id: i32 = role.into();
   sqlx::query!(
     r#"
-      INSERT INTO public.af_workspace_member (workspace_id, uid, role_id)
+      INSERT INTO af_workspace_member (workspace_id, uid, role_id)
       SELECT $1, af_user.uid, $3
-      FROM public.af_user
+      FROM af_user
       WHERE
         af_user.email = $2
       ON CONFLICT (workspace_id, uid)
@@ -295,7 +295,7 @@ pub async fn insert_workspace_invitation(
   let role_id: i32 = invitee_role.into();
   sqlx::query!(
     r#"
-      INSERT INTO public.af_workspace_invitation (
+      INSERT INTO af_workspace_invitation (
           id,
           workspace_id,
           inviter,
@@ -305,7 +305,7 @@ pub async fn insert_workspace_invitation(
       VALUES (
         $1,
         $2,
-        (SELECT uid FROM public.af_user WHERE uuid = $3),
+        (SELECT uid FROM af_user WHERE uuid = $3),
         $4,
         $5
       )
@@ -329,9 +329,9 @@ pub async fn update_workspace_invitation_set_status_accepted(
 ) -> Result<(), AppError> {
   let res = sqlx::query_scalar!(
     r#"
-    UPDATE public.af_workspace_invitation
+    UPDATE af_workspace_invitation
     SET status = 1
-    WHERE invitee_email = (SELECT email FROM public.af_user WHERE uuid = $1)
+    WHERE invitee_email = (SELECT email FROM af_user WHERE uuid = $1)
       AND id = $2
       AND status = 0
     "#,
@@ -366,11 +366,11 @@ pub async fn get_invitation_by_id(
     SELECT
         workspace_id,
         inviter AS inviter_uid,
-        (SELECT uid FROM public.af_user WHERE email = invitee_email) AS invitee_uid,
+        (SELECT uid FROM af_user WHERE email = invitee_email) AS invitee_uid,
         status,
         role_id AS role
     FROM
-    public.af_workspace_invitation
+    af_workspace_invitation
     WHERE id = $1
     "#,
     invite_id,
@@ -400,12 +400,12 @@ pub async fn select_workspace_invitations_for_user(
         i.updated_at,
         u_inviter.metadata->>'icon_url' AS inviter_icon,
         w.icon AS workspace_icon,
-        (SELECT COUNT(*) FROM public.af_workspace_member m WHERE m.workspace_id = i.workspace_id) AS member_count
+        (SELECT COUNT(*) FROM af_workspace_member m WHERE m.workspace_id = i.workspace_id) AS member_count
       FROM
-        public.af_workspace_invitation i
-        JOIN public.af_workspace w ON i.workspace_id = w.workspace_id
-        JOIN public.af_user u_inviter ON i.inviter = u_inviter.uid
-        JOIN public.af_user u_invitee ON u_invitee.uuid = $1
+        af_workspace_invitation i
+        JOIN af_workspace w ON i.workspace_id = w.workspace_id
+        JOIN af_user u_inviter ON i.inviter = u_inviter.uid
+        JOIN af_user u_invitee ON u_invitee.uuid = $1
       WHERE
         i.invitee_email = u_invitee.email
         AND ($2::SMALLINT IS NULL OR i.status = $2);
@@ -437,12 +437,12 @@ pub async fn select_workspace_invitation_for_user(
         i.updated_at,
         u_inviter.metadata->>'icon_url' AS inviter_icon,
         w.icon AS workspace_icon,
-        (SELECT COUNT(*) FROM public.af_workspace_member m WHERE m.workspace_id = i.workspace_id) AS member_count
+        (SELECT COUNT(*) FROM af_workspace_member m WHERE m.workspace_id = i.workspace_id) AS member_count
       FROM
-        public.af_workspace_invitation i
-        JOIN public.af_workspace w ON i.workspace_id = w.workspace_id
-        JOIN public.af_user u_inviter ON i.inviter = u_inviter.uid
-        JOIN public.af_user u_invitee ON u_invitee.uuid = $1
+        af_workspace_invitation i
+        JOIN af_workspace w ON i.workspace_id = w.workspace_id
+        JOIN af_user u_inviter ON i.inviter = u_inviter.uid
+        JOIN af_user u_invitee ON u_invitee.uuid = $1
       WHERE
         i.invitee_email = u_invitee.email
         AND i.id = $2;
@@ -501,11 +501,11 @@ pub async fn delete_workspace_members(
     r#"
   SELECT EXISTS (
     SELECT 1
-    FROM public.af_workspace
+    FROM af_workspace
     WHERE
         workspace_id = $1
         AND owner_uid = (
-            SELECT uid FROM public.af_user WHERE email = $2
+            SELECT uid FROM af_user WHERE email = $2
         )
    ) AS "is_owner";
   "#,
@@ -525,17 +525,17 @@ pub async fn delete_workspace_members(
 
   sqlx::query!(
     r#"
-    DELETE FROM public.af_workspace_member
+    DELETE FROM af_workspace_member
     WHERE
     workspace_id = $1
     AND uid = (
-        SELECT uid FROM public.af_user WHERE email = $2
+        SELECT uid FROM af_user WHERE email = $2
     )
     -- Ensure the user to be deleted is not the original owner.
     -- 1. TODO(nathan): User must transfer ownership to another user first.
     -- 2. User must have at least one workspace
     AND uid <> (
-        SELECT owner_uid FROM public.af_workspace WHERE workspace_id = $1
+        SELECT owner_uid FROM af_workspace WHERE workspace_id = $1
     );
     "#,
     workspace_id,
@@ -568,8 +568,8 @@ pub async fn select_workspace_member_list(
     r#"
     SELECT af_user.uid, af_user.name, af_user.email,
     af_workspace_member.role_id AS role
-    FROM public.af_workspace_member
-        JOIN public.af_user ON af_workspace_member.uid = af_user.uid
+    FROM af_workspace_member
+        JOIN af_user ON af_workspace_member.uid = af_user.uid
     WHERE af_workspace_member.workspace_id = $1
     ORDER BY af_workspace_member.created_at ASC;
     "#,
@@ -590,8 +590,8 @@ pub async fn select_workspace_member<'a, E: Executor<'a, Database = Postgres>>(
     AFWorkspaceMemberRow,
     r#"
     SELECT af_user.uid, af_user.name, af_user.email, af_workspace_member.role_id AS role
-    FROM public.af_workspace_member
-      JOIN public.af_user ON af_workspace_member.uid = af_user.uid
+    FROM af_workspace_member
+      JOIN af_user ON af_workspace_member.uid = af_user.uid
     WHERE af_workspace_member.workspace_id = $1
     AND af_workspace_member.uid = $2
     "#,
@@ -658,8 +658,8 @@ pub async fn select_workspace<'a, E: Executor<'a, Database = Postgres>>(
         af_workspace.deleted_at,
         workspace_name,
         icon
-      FROM public.af_workspace
-      JOIN public.af_user owner_profile ON af_workspace.owner_uid = owner_profile.uid
+      FROM af_workspace
+      JOIN af_user owner_profile ON af_workspace.owner_uid = owner_profile.uid
       WHERE workspace_id = $1
     "#,
     workspace_id
@@ -679,7 +679,7 @@ pub async fn select_workspace_database_storage_id<'a, E: Executor<'a, Database =
     r#"
         SELECT
             database_storage_id
-        FROM public.af_workspace
+        FROM af_workspace
         WHERE workspace_id = $1
         "#,
     workspace_id
@@ -700,7 +700,7 @@ pub async fn update_updated_at_of_workspace<'a, E: Executor<'a, Database = Postg
     r#"
        UPDATE af_workspace_member
        SET updated_at = CURRENT_TIMESTAMP
-       WHERE uid = (SELECT uid FROM public.af_user WHERE uuid = $1) AND workspace_id = $2;
+       WHERE uid = (SELECT uid FROM af_user WHERE uuid = $1) AND workspace_id = $2;
     "#,
     user_uuid,
     workspace_id
@@ -733,9 +733,9 @@ pub async fn select_all_user_workspaces<'a, E: Executor<'a, Database = Postgres>
         w.icon
       FROM af_workspace w
       JOIN af_workspace_member wm ON w.workspace_id = wm.workspace_id
-      JOIN public.af_user u ON w.owner_uid = u.uid
+      JOIN af_user u ON w.owner_uid = u.uid
       WHERE wm.uid = (
-         SELECT uid FROM public.af_user WHERE uuid = $1
+         SELECT uid FROM af_user WHERE uuid = $1
       )
       AND COALESCE(w.is_initialized, true) = true;
     "#,
@@ -756,7 +756,7 @@ pub async fn select_user_owned_workspaces_id<'a, E: Executor<'a, Database = Post
     r#"
       SELECT workspace_id
       FROM af_workspace
-      WHERE owner_uid = (SELECT uid FROM public.af_user WHERE uuid = $1)
+      WHERE owner_uid = (SELECT uid FROM af_user WHERE uuid = $1)
     "#,
     user_uuid
   )
@@ -772,7 +772,7 @@ pub async fn update_workspace_status<'a, E: Executor<'a, Database = Postgres>>(
 ) -> Result<(), AppError> {
   let res = sqlx::query!(
     r#"
-    UPDATE public.af_workspace
+    UPDATE af_workspace
     SET is_initialized = $2
     WHERE workspace_id = $1
     "#,
@@ -831,7 +831,7 @@ pub async fn select_permission(
   let permission = sqlx::query_as!(
     AFPermissionRow,
     r#"
-      SELECT * FROM public.af_permissions WHERE id = $1
+      SELECT * FROM af_permissions WHERE id = $1
     "#,
     *permission_id as i32
   )
@@ -888,7 +888,7 @@ pub async fn select_workspace_name_from_workspace_id(
   let workspace_name = sqlx::query_scalar!(
     r#"
       SELECT workspace_name
-      FROM public.af_workspace
+      FROM af_workspace
       WHERE workspace_id = $1
     "#,
     workspace_id
@@ -906,7 +906,7 @@ pub async fn select_workspace_member_count_from_workspace_id(
   let workspace_count = sqlx::query_scalar!(
     r#"
       SELECT COUNT(*)
-      FROM public.af_workspace_member
+      FROM af_workspace_member
       WHERE workspace_id = $1
     "#,
     workspace_id
@@ -924,7 +924,7 @@ pub async fn select_workspace_pending_invitations(
   let res = sqlx::query!(
     r#"
       SELECT id, invitee_email
-      FROM public.af_workspace_invitation
+      FROM af_workspace_invitation
       WHERE workspace_id = $1
       AND status = 0
     "#,

Migration 20240614171931_collab_embeddings.sql failed silently if pgvector extension is not installed for postgres

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants