Merge pull request #11637 from tvogel/patch-4

Add section about storage management
This commit is contained in:
dng authored and GitHub committed 2023-01-25 16:33:56 -08:00
commit c9839227e5
16 files changed
+166

No files matched your search

@@ -0,0 +1,108 @@
If you upload additional profile photos, they'll accumulate
in the `avatars` bucket because of their random names with only the latest being referenced
from `public.profiles` and the older versions getting orphaned.
To automatically remove obsolete storage objects, extend the database
triggers. Note that it is not sufficient to delete the objects from the
`storage.objects` table because that would orphan and leak the actual storage objects in
the S3 backend. Instead, invoke the storage API within Postgres via the `http` extension.
Enable the [http extension for the `extensions` schema](https://app.supabase.com/project/_/database/extensions) in the Dashboard.
Then, define the following SQL functions in the SQL Editor to delete
storage objects via the API:
```SQL
create or replace function delete_storage_object(bucket text, object text, out status int, out content varchar)
returns record
language 'plpgsql'
security definer
as $$
declare
project_url varchar := '<YOURPROJECTURL>';
service_role_key varchar := '<YOURSERVICEROLEKEY>'; -- full access needed
url varchar := project_url||'/storage/v1/object/'||bucket||'/'||object;
begin
select
into status, content
result.status::int, result.content::varchar
FROM extensions.http((
'DELETE',
url,
ARRAY[extensions.http_header('authorization','Bearer '||service_role_key)],
NULL,
NULL)::extensions.http_request) as result;
end;
$$;
create or replace function delete_avatar(avatar_url text, out status int, out content varchar)
returns record
language 'plpgsql'
security definer
as $$
begin
select
into status, content
result.status, result.content
from public.delete_storage_object('avatars', avatar_url) as result;
end;
$$;
```
Next, add a trigger that removes any obsolete avatar whenever the
profile is updated or deleted:
```SQL
create or replace function delete_old_avatar()
returns trigger
language 'plpgsql'
security definer
as $$
declare
status int;
content varchar;
begin
if coalesce(old.avatar_url, '') <> ''
and (tg_op = 'DELETE' or (old.avatar_url <> new.avatar_url)) then
select
into status, content
result.status, result.content
from public.delete_avatar(old.avatar_url) as result;
if status <> 200 then
raise warning 'Could not delete avatar: % %', status, content;
end if;
end if;
if tg_op = 'DELETE' then
return old;
end if;
return new;
end;
$$;
create trigger before_profile_changes
before update of avatar_url or delete on public.profiles
for each row execute function public.delete_old_avatar();
```
Finally, delete the `public.profile` row before a user is deleted.
If this step is omitted, you won't be able to delete users without
first manually deleting their avatar image.
```SQL
create or replace function delete_old_profile()
returns trigger
language 'plpgsql'
security definer
as $$
begin
delete from public.profiles where id = old.id;
return old;
end;
$$;
create trigger before_delete_user
before delete on auth.users
for each row execute function public.delete_old_profile();
```
+2
View File
@@ -20,6 +20,7 @@ import QuickstartIntro from './MDX/quickstart_intro.mdx'
import ProjectSetup from './MDX/project_setup.mdx'
import SocialProviderSetup from './MDX/social_provider_setup.mdx'
import SocialProviderSettingsSupabase from './MDX/social_provider_settings_supabase.mdx'
import StorageManagement from './MDX/storage_management.mdx'
import { Mermaid } from 'mdx-mermaid/lib/Mermaid'
import InlineCodeTag from './CustomHTMLElements/InlineCode'
import React from 'react'
@@ -49,6 +50,7 @@ const components = {
ProjectSetup,
SocialProviderSetup,
SocialProviderSettingsSupabase,
StorageManagement,
Mermaid,
Extensions,
Alert: (props: any) => (
@@ -530,6 +530,10 @@ export class AccountComponent implements OnInit {
}
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -500,6 +500,10 @@ Now you will need to run the prebuild command to get the application working on
expo prebuild
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -793,6 +793,10 @@ class _AccountPageState extends State<AccountPage> {
}
```
### Storage management
<StorageManagement />
Congratulations, that is it! You have now built a fully functional user management app using Flutter and Supabase!
## See also
@@ -522,6 +522,10 @@ template: `
`
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -495,6 +495,10 @@ return (
<Avatar url={profile.avatar_url} onUpload={updateProfile}></Avatar>
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -555,6 +555,10 @@ export default defineComponent({
</script>
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -718,6 +718,10 @@ return (
)
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -420,6 +420,10 @@ And then we can add the widget to the Account page:
That is it! You should now be able to upload a profile photo to Supabase Storage.
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -397,6 +397,10 @@ return (
)
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -771,6 +771,10 @@ return (
)
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -415,6 +415,10 @@ return (
)
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -368,6 +368,10 @@ And then we can add the widget to the Account page:
</form>
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -434,6 +434,10 @@ And then we can add the widget to the Account page:
</form>
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!
@@ -379,6 +379,10 @@ And then we can add the widget to the Account page:
</template>
```
### Storage management
<StorageManagement />
## Next steps
At this stage you have a fully functional application!