@nextblock-cms/db 0.2.10 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -3
- package/supabase/config.toml +319 -0
- package/supabase/migrations/20250513194738_setup_roles_and_profiles.sql +41 -0
- package/supabase/migrations/20250513194910_auto_create_profile_trigger.sql +48 -0
- package/supabase/migrations/20250513194916_rls_for_profiles.sql +85 -0
- package/supabase/migrations/20250514125634_fix_recursive_rls_policies.sql +51 -0
- package/supabase/migrations/20250514143016_setup_languages_table.sql +66 -0
- package/supabase/migrations/20250514171549_create_pages_table.sql +73 -0
- package/supabase/migrations/20250514171550_create_posts_table.sql +61 -0
- package/supabase/migrations/20250514171552_create_media_table.sql +45 -0
- package/supabase/migrations/20250514171553_create_blocks_table.sql +54 -0
- package/supabase/migrations/20250514171615_create_navigation_table.sql +56 -0
- package/supabase/migrations/20250514171627_rls_policies_for_content_tables.sql +70 -0
- package/supabase/migrations/20250515194800_add_translation_group_id.sql +39 -0
- package/supabase/migrations/20250520171900_add_translation_group_to_nav_items.sql +21 -0
- package/supabase/migrations/20250521143933_seed_homepage_and_nav.sql +64 -0
- package/supabase/migrations/20250523145833_add_feature_image_to_posts.sql +8 -0
- package/supabase/migrations/20250523151737_add_rls_to_media_table.sql +18 -0
- package/supabase/migrations/20250526110400_add_image_dimensions_to_media.sql +14 -0
- package/supabase/migrations/20250526153321_optimize_rls_policies.sql +188 -0
- package/supabase/migrations/20250526172513_resolve_select_policy_overlaps.sql +96 -0
- package/supabase/migrations/20250526172853_resolve_remaining_rls_v5.sql +107 -0
- package/supabase/migrations/20250526173538_finalize_rls_cleanup_v7.sql +110 -0
- package/supabase/migrations/20250526174710_separate_write_policies_v8.sql +147 -0
- package/supabase/migrations/20250526175359_fix_languages_select_rls_v9.sql +81 -0
- package/supabase/migrations/20250526182940_fix_nav_read_policy_v10.sql +27 -0
- package/supabase/migrations/20250526183239_fix_posts_read_rls_v11.sql +59 -0
- package/supabase/migrations/20250526183746_fix_media_select_rls_v12.sql +39 -0
- package/supabase/migrations/20250526184205_consolidate_content_read_rls_v13.sql +61 -0
- package/supabase/migrations/20250526185854_optimize_indexes.sql +47 -0
- package/supabase/migrations/20250526190900_debug_blocks_rls.sql +56 -0
- package/supabase/migrations/20250526191217_consolidate_blocks_select_rls.sql +79 -0
- package/supabase/migrations/20250526192822_fix_handle_languages_update_search_path.sql +32 -0
- package/supabase/migrations/20250527150500_fix_blocks_rls_policy.sql +54 -0
- package/supabase/migrations/20250602150602_add_blur_data_url_to_media.sql +4 -0
- package/supabase/migrations/20250602150959_add_variants_to_media.sql +4 -0
- package/supabase/migrations/20250618124000_create_get_my_claim_function.sql +5 -0
- package/supabase/migrations/20250618124100_create_logos_table.sql +29 -0
- package/supabase/migrations/20250618130000_fix_linter_warnings.sql +58 -0
- package/supabase/migrations/20250618151500_revert_storage_rls.sql +6 -0
- package/supabase/migrations/20250619084800_reinstate_storage_rls.sql +13 -0
- package/supabase/migrations/20250619092430_widen_logo_insert_policy.sql +6 -0
- package/supabase/migrations/20250619093122_fix_get_my_claim_volatility.sql +5 -0
- package/supabase/migrations/20250619104249_consolidated_logo_rls_fix.sql +56 -0
- package/supabase/migrations/20250619110700_fix_logo_rls_again.sql +59 -0
- package/supabase/migrations/20250619113200_add_file_path_to_media.sql +4 -0
- package/supabase/migrations/20250619124100_fix_rls_performance_warnings.sql +74 -0
- package/supabase/migrations/20250619195500_create_site_settings_table.sql +28 -0
- package/supabase/migrations/20250619201500_add_anon_read_to_site_settings.sql +7 -0
- package/supabase/migrations/20250619202000_add_is_active_to_languages.sql +5 -0
- package/supabase/migrations/20250620085700_fix_site_settings_write_rls.sql +27 -0
- package/supabase/migrations/20250620095500_fix_profiles_read_rls.sql +11 -0
- package/supabase/migrations/20250620100000_use_security_definer_for_rls.sql +39 -0
- package/supabase/migrations/20250620130000_add_public_read_to_logos.sql +4 -0
- package/supabase/migrations/20250708091700_create_translations_table.sql +55 -0
- package/supabase/migrations/20250708093403_seed_translations_table.sql +20 -0
- package/supabase/migrations/20250708110600_fix_translations_rls_policies.sql +11 -0
- package/supabase/migrations/20250708112300_add_new_translations.sql +9 -0
- package/supabase/migrations/20250709120000_create_revisions_tables.sql +109 -0
- package/supabase/migrations/20251001113000_add_folder_to_media.sql +14 -0
- package/supabase/migrations/20251112113736_fix_search_path_functions.sql +74 -0
- package/supabase/migrations/20251112124444_fix_rls_performance.sql +63 -0
- package/supabase/migrations/20251112125935_fix_combined_policies.sql +194 -0
- package/supabase/migrations/20251112132146_fix_foreign_key_indexes.sql +21 -0
- package/supabase/migrations/20251112132525_cleanup_unused_indexes.sql +10 -0
- package/supabase/migrations/20251112132822_fix_final_indexes.sql +14 -0
- package/supabase/migrations/20251112140000_scaffold_foundational_content.sql +95 -0
- package/supabase/migrations/20251112141000_seed_homepage_blocks.sql +656 -0
- package/supabase/migrations/20251112142000_seed_how_it_works_post_blocks.sql +100 -0
- package/supabase/migrations/20251112143000_seed_additional_translations.sql +102 -0
- package/supabase/migrations/20251112145000_grant_public_schema_usage.sql +6 -0
- package/supabase/migrations/20251112145500_grant_select_on_public_tables.sql +19 -0
- package/supabase/migrations/20251117093000_add_admin_created_flag.sql +21 -0
- package/supabase/migrations/20251117103000_relax_profile_username_constraint.sql +6 -0
- package/supabase/migrations/20251117110000_relax_profiles_site_settings_rls_for_signup.sql +20 -0
- package/supabase/migrations/20251117112000_fix_handle_new_user_role_enum.sql +45 -0
- package/supabase/migrations/20251117113000_cleanup_rls_duplicates.sql +20 -0
- package/supabase/migrations/20251117200000_media_service_role_insert.sql +14 -0
- package/supabase/migrations/20251117201500_media_service_role_select.sql +11 -0
- package/supabase/migrations/20251117203000_media_admin_writer_select.sql +11 -0
- package/supabase/migrations/20251117204500_fix_media_permissions.sql +43 -0
- package/lib/supabase/client.d.ts +0 -9
- package/lib/supabase/middleware.d.ts +0 -2
- package/lib/supabase/server.d.ts +0 -7
- package/lib/supabase/ssg-client.d.ts +0 -2
- package/lib/supabase/types.d.ts +0 -635
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextblock-cms/db",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"main": "index.cjs.js",
|
|
5
5
|
"module": "index.es.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -16,5 +16,15 @@
|
|
|
16
16
|
"default": "./server.es.js"
|
|
17
17
|
},
|
|
18
18
|
"./package.json": "./package.json"
|
|
19
|
-
}
|
|
20
|
-
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"supabase",
|
|
23
|
+
"supabase/**",
|
|
24
|
+
"*.js",
|
|
25
|
+
"*.cjs.js",
|
|
26
|
+
"*.es.js",
|
|
27
|
+
"*.mjs",
|
|
28
|
+
"*.d.ts"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# For detailed configuration reference documentation, visit:
|
|
2
|
+
# https://supabase.com/docs/guides/local-development/cli/config
|
|
3
|
+
# A string used to distinguish different Supabase projects on the same host. Defaults to the
|
|
4
|
+
# working directory name when running `supabase init`.
|
|
5
|
+
project_id = "env(SUPABASE_PROJECT_ID)"
|
|
6
|
+
|
|
7
|
+
[api]
|
|
8
|
+
enabled = true
|
|
9
|
+
# Port to use for the API URL.
|
|
10
|
+
port = 54321
|
|
11
|
+
# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API
|
|
12
|
+
# endpoints. `public` and `graphql_public` schemas are included by default.
|
|
13
|
+
schemas = ["public", "graphql_public"]
|
|
14
|
+
# Extra schemas to add to the search_path of every request.
|
|
15
|
+
extra_search_path = ["public", "extensions"]
|
|
16
|
+
# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size
|
|
17
|
+
# for accidental or malicious requests.
|
|
18
|
+
max_rows = 1000
|
|
19
|
+
|
|
20
|
+
[api.tls]
|
|
21
|
+
# Enable HTTPS endpoints locally using a self-signed certificate.
|
|
22
|
+
enabled = false
|
|
23
|
+
|
|
24
|
+
[db]
|
|
25
|
+
# Port to use for the local database URL.
|
|
26
|
+
port = 54322
|
|
27
|
+
# Port used by db diff command to initialize the shadow database.
|
|
28
|
+
shadow_port = 54320
|
|
29
|
+
# The database major version to use. This has to be the same as your remote database's. Run `SHOW
|
|
30
|
+
# server_version;` on the remote database to check.
|
|
31
|
+
major_version = 17
|
|
32
|
+
|
|
33
|
+
[db.pooler]
|
|
34
|
+
enabled = false
|
|
35
|
+
# Port to use for the local connection pooler.
|
|
36
|
+
port = 54329
|
|
37
|
+
# Specifies when a server connection can be reused by other clients.
|
|
38
|
+
# Configure one of the supported pooler modes: `transaction`, `session`.
|
|
39
|
+
pool_mode = "transaction"
|
|
40
|
+
# How many server connections to allow per user/database pair.
|
|
41
|
+
default_pool_size = 20
|
|
42
|
+
# Maximum number of client connections allowed.
|
|
43
|
+
max_client_conn = 100
|
|
44
|
+
|
|
45
|
+
# [db.vault]
|
|
46
|
+
# secret_key = "env(SECRET_VALUE)"
|
|
47
|
+
|
|
48
|
+
[db.migrations]
|
|
49
|
+
# Specifies an ordered list of schema files that describe your database.
|
|
50
|
+
# Supports glob patterns relative to supabase directory: "./schemas/*.sql"
|
|
51
|
+
schema_paths = []
|
|
52
|
+
|
|
53
|
+
[db.seed]
|
|
54
|
+
# If enabled, seeds the database after migrations during a db reset.
|
|
55
|
+
enabled = true
|
|
56
|
+
# Specifies an ordered list of seed files to load during db reset.
|
|
57
|
+
# Supports glob patterns relative to supabase directory: "./seeds/*.sql"
|
|
58
|
+
sql_paths = ["./seed.sql"]
|
|
59
|
+
|
|
60
|
+
[realtime]
|
|
61
|
+
enabled = true
|
|
62
|
+
# Bind realtime via either IPv4 or IPv6. (default: IPv4)
|
|
63
|
+
# ip_version = "IPv6"
|
|
64
|
+
# The maximum length in bytes of HTTP request headers. (default: 4096)
|
|
65
|
+
# max_header_length = 4096
|
|
66
|
+
|
|
67
|
+
[studio]
|
|
68
|
+
enabled = true
|
|
69
|
+
# Port to use for Supabase Studio.
|
|
70
|
+
port = 54323
|
|
71
|
+
# External URL of the API server that frontend connects to.
|
|
72
|
+
api_url = "http://127.0.0.1"
|
|
73
|
+
# OpenAI API Key to use for Supabase AI in the Supabase Studio.
|
|
74
|
+
openai_api_key = "env(OPENAI_API_KEY)"
|
|
75
|
+
|
|
76
|
+
# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they
|
|
77
|
+
# are monitored, and you can view the emails that would have been sent from the web interface.
|
|
78
|
+
[inbucket]
|
|
79
|
+
enabled = true
|
|
80
|
+
# Port to use for the email testing server web interface.
|
|
81
|
+
port = 54324
|
|
82
|
+
# Uncomment to expose additional ports for testing user applications that send emails.
|
|
83
|
+
# smtp_port = 54325
|
|
84
|
+
# pop3_port = 54326
|
|
85
|
+
# admin_email = "admin@email.com"
|
|
86
|
+
# sender_name = "Admin"
|
|
87
|
+
|
|
88
|
+
[storage]
|
|
89
|
+
enabled = true
|
|
90
|
+
# The maximum file size allowed (e.g. "5MB", "500KB").
|
|
91
|
+
file_size_limit = "50MiB"
|
|
92
|
+
|
|
93
|
+
# Image transformation API is available to Supabase Pro plan.
|
|
94
|
+
# [storage.image_transformation]
|
|
95
|
+
# enabled = true
|
|
96
|
+
|
|
97
|
+
# Uncomment to configure local storage buckets
|
|
98
|
+
# [storage.buckets.images]
|
|
99
|
+
# public = false
|
|
100
|
+
# file_size_limit = "50MiB"
|
|
101
|
+
# allowed_mime_types = ["image/png", "image/jpeg"]
|
|
102
|
+
# objects_path = "./images"
|
|
103
|
+
|
|
104
|
+
[auth]
|
|
105
|
+
enabled = true
|
|
106
|
+
# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used
|
|
107
|
+
# in emails.
|
|
108
|
+
site_url = "http://localhost:3000"
|
|
109
|
+
# A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
|
|
110
|
+
additional_redirect_urls = []
|
|
111
|
+
# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week).
|
|
112
|
+
jwt_expiry = 3600
|
|
113
|
+
# If disabled, the refresh token will never expire.
|
|
114
|
+
enable_refresh_token_rotation = true
|
|
115
|
+
# Allows refresh tokens to be reused after expiry, up to the specified interval in seconds.
|
|
116
|
+
# Requires enable_refresh_token_rotation = true.
|
|
117
|
+
refresh_token_reuse_interval = 10
|
|
118
|
+
# Allow/disallow new user signups to your project.
|
|
119
|
+
enable_signup = true
|
|
120
|
+
# Allow/disallow anonymous sign-ins to your project.
|
|
121
|
+
enable_anonymous_sign_ins = false
|
|
122
|
+
# Allow/disallow testing manual linking of accounts
|
|
123
|
+
enable_manual_linking = false
|
|
124
|
+
# Passwords shorter than this value will be rejected as weak. Minimum 6, recommended 8 or more.
|
|
125
|
+
minimum_password_length = 6
|
|
126
|
+
# Passwords that do not meet the following requirements will be rejected as weak. Supported values
|
|
127
|
+
# are: `letters_digits`, `lower_upper_letters_digits`, `lower_upper_letters_digits_symbols`
|
|
128
|
+
password_requirements = ""
|
|
129
|
+
|
|
130
|
+
[auth.rate_limit]
|
|
131
|
+
# Number of emails that can be sent per hour. Requires auth.email.smtp to be enabled.
|
|
132
|
+
email_sent = 2
|
|
133
|
+
# Number of SMS messages that can be sent per hour. Requires auth.sms to be enabled.
|
|
134
|
+
sms_sent = 30
|
|
135
|
+
# Number of anonymous sign-ins that can be made per hour per IP address. Requires enable_anonymous_sign_ins = true.
|
|
136
|
+
anonymous_users = 30
|
|
137
|
+
# Number of sessions that can be refreshed in a 5 minute interval per IP address.
|
|
138
|
+
token_refresh = 150
|
|
139
|
+
# Number of sign up and sign-in requests that can be made in a 5 minute interval per IP address (excludes anonymous users).
|
|
140
|
+
sign_in_sign_ups = 30
|
|
141
|
+
# Number of OTP / Magic link verifications that can be made in a 5 minute interval per IP address.
|
|
142
|
+
token_verifications = 30
|
|
143
|
+
|
|
144
|
+
# Configure one of the supported captcha providers: `hcaptcha`, `turnstile`.
|
|
145
|
+
# [auth.captcha]
|
|
146
|
+
# enabled = true
|
|
147
|
+
# provider = "hcaptcha"
|
|
148
|
+
# secret = ""
|
|
149
|
+
|
|
150
|
+
[auth.email]
|
|
151
|
+
# Allow/disallow new user signups via email to your project.
|
|
152
|
+
enable_signup = true
|
|
153
|
+
# If enabled, a user will be required to confirm any email change on both the old, and new email
|
|
154
|
+
# addresses. If disabled, only the new email is required to confirm.
|
|
155
|
+
double_confirm_changes = true
|
|
156
|
+
# If enabled, users need to confirm their email address before signing in.
|
|
157
|
+
enable_confirmations = true
|
|
158
|
+
# If enabled, users will need to reauthenticate or have logged in recently to change their password.
|
|
159
|
+
secure_password_change = false
|
|
160
|
+
# Controls the minimum amount of time that must pass before sending another signup confirmation or password reset email.
|
|
161
|
+
max_frequency = "1m0s"
|
|
162
|
+
# Number of characters used in the email OTP.
|
|
163
|
+
otp_length = 6
|
|
164
|
+
# Number of seconds before the email OTP expires (defaults to 1 hour).
|
|
165
|
+
otp_expiry = 3600
|
|
166
|
+
|
|
167
|
+
# Use a production-ready SMTP server
|
|
168
|
+
# [auth.email.smtp]
|
|
169
|
+
# enabled = true
|
|
170
|
+
# host = "smtp.sendgrid.net"
|
|
171
|
+
# port = 587
|
|
172
|
+
# user = "apikey"
|
|
173
|
+
# pass = "env(SENDGRID_API_KEY)"
|
|
174
|
+
# admin_email = "admin@email.com"
|
|
175
|
+
# sender_name = "Admin"
|
|
176
|
+
|
|
177
|
+
# Uncomment to customize email template
|
|
178
|
+
# [auth.email.template.invite]
|
|
179
|
+
# subject = "You have been invited"
|
|
180
|
+
# content_path = "./supabase/templates/invite.html"
|
|
181
|
+
|
|
182
|
+
[auth.sms]
|
|
183
|
+
# Allow/disallow new user signups via SMS to your project.
|
|
184
|
+
enable_signup = false
|
|
185
|
+
# If enabled, users need to confirm their phone number before signing in.
|
|
186
|
+
enable_confirmations = false
|
|
187
|
+
# Template for sending OTP to users
|
|
188
|
+
template = "Your code is {{ .Code }}"
|
|
189
|
+
# Controls the minimum amount of time that must pass before sending another sms otp.
|
|
190
|
+
max_frequency = "5s"
|
|
191
|
+
|
|
192
|
+
# Use pre-defined map of phone number to OTP for testing.
|
|
193
|
+
# [auth.sms.test_otp]
|
|
194
|
+
# 4152127777 = "123456"
|
|
195
|
+
|
|
196
|
+
# Configure logged in session timeouts.
|
|
197
|
+
# [auth.sessions]
|
|
198
|
+
# Force log out after the specified duration.
|
|
199
|
+
# timebox = "24h"
|
|
200
|
+
# Force log out if the user has been inactive longer than the specified duration.
|
|
201
|
+
# inactivity_timeout = "8h"
|
|
202
|
+
|
|
203
|
+
# This hook runs before a token is issued and allows you to add additional claims based on the authentication method used.
|
|
204
|
+
# [auth.hook.custom_access_token]
|
|
205
|
+
# enabled = true
|
|
206
|
+
# uri = "pg-functions://<database>/<schema>/<hook_name>"
|
|
207
|
+
|
|
208
|
+
# Configure one of the supported SMS providers: `twilio`, `twilio_verify`, `messagebird`, `textlocal`, `vonage`.
|
|
209
|
+
[auth.sms.twilio]
|
|
210
|
+
enabled = false
|
|
211
|
+
account_sid = ""
|
|
212
|
+
message_service_sid = ""
|
|
213
|
+
# DO NOT commit your Twilio auth token to git. Use environment variable substitution instead:
|
|
214
|
+
auth_token = "env(SUPABASE_AUTH_SMS_TWILIO_AUTH_TOKEN)"
|
|
215
|
+
|
|
216
|
+
# Multi-factor-authentication is available to Supabase Pro plan.
|
|
217
|
+
[auth.mfa]
|
|
218
|
+
# Control how many MFA factors can be enrolled at once per user.
|
|
219
|
+
max_enrolled_factors = 10
|
|
220
|
+
|
|
221
|
+
# Control MFA via App Authenticator (TOTP)
|
|
222
|
+
[auth.mfa.totp]
|
|
223
|
+
enroll_enabled = false
|
|
224
|
+
verify_enabled = false
|
|
225
|
+
|
|
226
|
+
# Configure MFA via Phone Messaging
|
|
227
|
+
[auth.mfa.phone]
|
|
228
|
+
enroll_enabled = false
|
|
229
|
+
verify_enabled = false
|
|
230
|
+
otp_length = 6
|
|
231
|
+
template = "Your code is {{ .Code }}"
|
|
232
|
+
max_frequency = "5s"
|
|
233
|
+
|
|
234
|
+
# Configure MFA via WebAuthn
|
|
235
|
+
# [auth.mfa.web_authn]
|
|
236
|
+
# enroll_enabled = true
|
|
237
|
+
# verify_enabled = true
|
|
238
|
+
|
|
239
|
+
# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,
|
|
240
|
+
# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin_oidc`, `notion`, `twitch`,
|
|
241
|
+
# `twitter`, `slack`, `spotify`, `workos`, `zoom`.
|
|
242
|
+
[auth.external.apple]
|
|
243
|
+
enabled = false
|
|
244
|
+
client_id = ""
|
|
245
|
+
# DO NOT commit your OAuth provider secret to git. Use environment variable substitution instead:
|
|
246
|
+
secret = "env(SUPABASE_AUTH_EXTERNAL_APPLE_SECRET)"
|
|
247
|
+
# Overrides the default auth redirectUrl.
|
|
248
|
+
redirect_uri = ""
|
|
249
|
+
# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure,
|
|
250
|
+
# or any other third-party OIDC providers.
|
|
251
|
+
url = ""
|
|
252
|
+
# If enabled, the nonce check will be skipped. Required for local sign in with Google auth.
|
|
253
|
+
skip_nonce_check = false
|
|
254
|
+
|
|
255
|
+
# Use Firebase Auth as a third-party provider alongside Supabase Auth.
|
|
256
|
+
[auth.third_party.firebase]
|
|
257
|
+
enabled = false
|
|
258
|
+
# project_id = "my-firebase-project"
|
|
259
|
+
|
|
260
|
+
# Use Auth0 as a third-party provider alongside Supabase Auth.
|
|
261
|
+
[auth.third_party.auth0]
|
|
262
|
+
enabled = false
|
|
263
|
+
# tenant = "my-auth0-tenant"
|
|
264
|
+
# tenant_region = "us"
|
|
265
|
+
|
|
266
|
+
# Use AWS Cognito (Amplify) as a third-party provider alongside Supabase Auth.
|
|
267
|
+
[auth.third_party.aws_cognito]
|
|
268
|
+
enabled = false
|
|
269
|
+
# user_pool_id = "my-user-pool-id"
|
|
270
|
+
# user_pool_region = "us-east-1"
|
|
271
|
+
|
|
272
|
+
# Use Clerk as a third-party provider alongside Supabase Auth.
|
|
273
|
+
[auth.third_party.clerk]
|
|
274
|
+
enabled = false
|
|
275
|
+
# Obtain from https://clerk.com/setup/supabase
|
|
276
|
+
# domain = "example.clerk.accounts.dev"
|
|
277
|
+
|
|
278
|
+
[edge_runtime]
|
|
279
|
+
enabled = true
|
|
280
|
+
# Configure one of the supported request policies: `oneshot`, `per_worker`.
|
|
281
|
+
# Use `oneshot` for hot reload, or `per_worker` for load testing.
|
|
282
|
+
policy = "oneshot"
|
|
283
|
+
# Port to attach the Chrome inspector for debugging edge functions.
|
|
284
|
+
inspector_port = 8083
|
|
285
|
+
# The Deno major version to use.
|
|
286
|
+
deno_version = 1
|
|
287
|
+
|
|
288
|
+
# [edge_runtime.secrets]
|
|
289
|
+
# secret_key = "env(SECRET_VALUE)"
|
|
290
|
+
|
|
291
|
+
[analytics]
|
|
292
|
+
enabled = true
|
|
293
|
+
port = 54327
|
|
294
|
+
# Configure one of the supported backends: `postgres`, `bigquery`.
|
|
295
|
+
backend = "postgres"
|
|
296
|
+
|
|
297
|
+
# Experimental features may be deprecated any time
|
|
298
|
+
[experimental]
|
|
299
|
+
# Configures Postgres storage engine to use OrioleDB (S3)
|
|
300
|
+
orioledb_version = ""
|
|
301
|
+
# Configures S3 bucket URL, eg. <bucket_name>.s3-<region>.amazonaws.com
|
|
302
|
+
s3_host = "env(S3_HOST)"
|
|
303
|
+
# Configures S3 bucket region, eg. us-east-1
|
|
304
|
+
s3_region = "env(S3_REGION)"
|
|
305
|
+
# Configures AWS_ACCESS_KEY_ID for S3 bucket
|
|
306
|
+
s3_access_key = "env(S3_ACCESS_KEY)"
|
|
307
|
+
# Configures AWS_SECRET_ACCESS_KEY for S3 bucket
|
|
308
|
+
s3_secret_key = "env(S3_SECRET_KEY)"
|
|
309
|
+
|
|
310
|
+
[functions.on-content-change-revalidate]
|
|
311
|
+
enabled = true
|
|
312
|
+
verify_jwt = true
|
|
313
|
+
import_map = "./functions/on-content-change-revalidate/deno.json"
|
|
314
|
+
# Uncomment to specify a custom file path to the entrypoint.
|
|
315
|
+
# Supported file extensions are: .ts, .js, .mjs, .jsx, .tsx
|
|
316
|
+
entrypoint = "./functions/on-content-change-revalidate/index.ts"
|
|
317
|
+
# Specifies static files to be bundled with the function. Supports glob patterns.
|
|
318
|
+
# For example, if you want to serve static HTML pages in your function:
|
|
319
|
+
# static_files = [ "./functions/on-content-change-revalidate/*.html" ]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
-- lowercase sql
|
|
2
|
+
|
|
3
|
+
-- 1. create the user_role enum type
|
|
4
|
+
create type public.user_role as enum ('ADMIN', 'WRITER', 'USER');
|
|
5
|
+
|
|
6
|
+
-- 2. create the profiles table
|
|
7
|
+
create table public.profiles (
|
|
8
|
+
id uuid not null primary key, -- references auth.users(id)
|
|
9
|
+
updated_at timestamp with time zone,
|
|
10
|
+
username text unique,
|
|
11
|
+
full_name text,
|
|
12
|
+
avatar_url text,
|
|
13
|
+
website text,
|
|
14
|
+
role public.user_role not null default 'USER',
|
|
15
|
+
|
|
16
|
+
constraint username_length check (char_length(username) >= 3)
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
-- 3. set up foreign key from profiles.id to auth.users.id
|
|
20
|
+
alter table public.profiles
|
|
21
|
+
add constraint profiles_id_fkey
|
|
22
|
+
foreign key (id)
|
|
23
|
+
references auth.users (id)
|
|
24
|
+
on delete cascade; -- if a user is deleted, their profile is also deleted
|
|
25
|
+
|
|
26
|
+
-- 4. (optional) add some sample inserts for roles if needed directly, though roles are part of the enum.
|
|
27
|
+
-- users will get roles assigned. an admin user might need to be set manually or via seed.
|
|
28
|
+
-- example: update a specific user to be an admin after they sign up.
|
|
29
|
+
-- update public.profiles set role = 'ADMIN' where id = 'user_id_of_admin';
|
|
30
|
+
|
|
31
|
+
-- 5. (optional) seed an initial admin user if you know their auth.users.id
|
|
32
|
+
-- this requires the user to exist in auth.users first.
|
|
33
|
+
-- insert into public.profiles (id, username, full_name, role)
|
|
34
|
+
-- values ('<some-auth-user-id>', 'admin_user', 'Admin User', 'ADMIN')
|
|
35
|
+
-- on conflict (id) do update set role = 'ADMIN';
|
|
36
|
+
-- note: the trigger in the next migration is preferred for new users.
|
|
37
|
+
-- this manual insert/update is for bootstrapping your first admin.
|
|
38
|
+
|
|
39
|
+
comment on table public.profiles is 'profile information for each user, extending auth.users.';
|
|
40
|
+
comment on column public.profiles.id is 'references auth.users.id';
|
|
41
|
+
comment on column public.profiles.role is 'user role for rbac.';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
-- This function is triggered when a new user signs up in auth.users
|
|
2
|
+
-- It creates a corresponding profile in public.profiles
|
|
3
|
+
-- and assigns 'ADMIN' to the first user, then 'USER' thereafter, using a KV flag in site_settings.
|
|
4
|
+
|
|
5
|
+
CREATE OR REPLACE FUNCTION public.handle_new_user()
|
|
6
|
+
RETURNS TRIGGER
|
|
7
|
+
LANGUAGE plpgsql
|
|
8
|
+
SECURITY DEFINER
|
|
9
|
+
SET search_path = 'public'
|
|
10
|
+
AS $$
|
|
11
|
+
DECLARE
|
|
12
|
+
admin_flag_set BOOLEAN := FALSE;
|
|
13
|
+
user_role TEXT;
|
|
14
|
+
BEGIN
|
|
15
|
+
-- Ensure the admin flag row exists
|
|
16
|
+
INSERT INTO public.site_settings (key, value)
|
|
17
|
+
VALUES ('is_admin_created', 'false'::jsonb)
|
|
18
|
+
ON CONFLICT (key) DO NOTHING;
|
|
19
|
+
|
|
20
|
+
-- Lock and read the flag
|
|
21
|
+
SELECT COALESCE((value)::jsonb::boolean, FALSE)
|
|
22
|
+
INTO admin_flag_set
|
|
23
|
+
FROM public.site_settings
|
|
24
|
+
WHERE key = 'is_admin_created'
|
|
25
|
+
FOR UPDATE;
|
|
26
|
+
|
|
27
|
+
IF admin_flag_set = FALSE THEN
|
|
28
|
+
user_role := 'ADMIN';
|
|
29
|
+
UPDATE public.site_settings
|
|
30
|
+
SET value = 'true'::jsonb
|
|
31
|
+
WHERE key = 'is_admin_created';
|
|
32
|
+
ELSE
|
|
33
|
+
user_role := 'USER';
|
|
34
|
+
END IF;
|
|
35
|
+
|
|
36
|
+
INSERT INTO public.profiles (id, role)
|
|
37
|
+
VALUES (NEW.id, user_role);
|
|
38
|
+
|
|
39
|
+
RETURN NEW;
|
|
40
|
+
END;
|
|
41
|
+
$$;
|
|
42
|
+
|
|
43
|
+
-- Drop and recreate the trigger to use the updated function
|
|
44
|
+
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
|
|
45
|
+
|
|
46
|
+
CREATE TRIGGER on_auth_user_created
|
|
47
|
+
AFTER INSERT ON auth.users
|
|
48
|
+
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
-- lowercase sql
|
|
2
|
+
|
|
3
|
+
-- 1. enable row level security on the profiles table
|
|
4
|
+
alter table public.profiles enable row level security;
|
|
5
|
+
|
|
6
|
+
-- 2. create policies for profiles table
|
|
7
|
+
|
|
8
|
+
-- allow users to read their own profile
|
|
9
|
+
create policy "users_can_select_own_profile"
|
|
10
|
+
on public.profiles for select
|
|
11
|
+
using (auth.uid() = id);
|
|
12
|
+
|
|
13
|
+
-- allow users to update their own profile
|
|
14
|
+
create policy "users_can_update_own_profile"
|
|
15
|
+
on public.profiles for update
|
|
16
|
+
using (auth.uid() = id)
|
|
17
|
+
with check (auth.uid() = id);
|
|
18
|
+
|
|
19
|
+
-- allow admins to select any profile
|
|
20
|
+
create policy "admins_can_select_any_profile"
|
|
21
|
+
on public.profiles for select
|
|
22
|
+
using (
|
|
23
|
+
exists (
|
|
24
|
+
select 1
|
|
25
|
+
from public.profiles
|
|
26
|
+
where id = auth.uid() and role = 'ADMIN'
|
|
27
|
+
)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
-- allow admins to update any profile
|
|
31
|
+
create policy "admins_can_update_any_profile"
|
|
32
|
+
on public.profiles for update
|
|
33
|
+
using (
|
|
34
|
+
exists (
|
|
35
|
+
select 1
|
|
36
|
+
from public.profiles
|
|
37
|
+
where id = auth.uid() and role = 'ADMIN'
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
with check (
|
|
41
|
+
exists (
|
|
42
|
+
select 1
|
|
43
|
+
from public.profiles
|
|
44
|
+
where id = auth.uid() and role = 'ADMIN'
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
-- allow admins to insert profiles (e.g., for manual setup, though trigger handles new users)
|
|
49
|
+
create policy "admins_can_insert_profiles"
|
|
50
|
+
on public.profiles for insert
|
|
51
|
+
with check (
|
|
52
|
+
exists (
|
|
53
|
+
select 1
|
|
54
|
+
from public.profiles
|
|
55
|
+
where id = auth.uid() and role = 'ADMIN'
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
-- (optional) allow any authenticated user to read any profile if roles need to be widely available
|
|
60
|
+
-- create policy "authenticated_users_can_read_profiles"
|
|
61
|
+
-- on public.profiles for select
|
|
62
|
+
-- to authenticated
|
|
63
|
+
-- using (true);
|
|
64
|
+
-- For now, we'll stick to more restrictive select policies above.
|
|
65
|
+
-- The middleware will need to fetch the current user's role. The "users_can_select_own_profile"
|
|
66
|
+
-- policy allows this. If an admin needs to see other user's roles in a list,
|
|
67
|
+
-- "admins_can_select_any_profile" covers that.
|
|
68
|
+
|
|
69
|
+
comment on policy "users_can_select_own_profile" on public.profiles is 'users can read their own profile.';
|
|
70
|
+
comment on policy "users_can_update_own_profile" on public.profiles is 'users can update their own profile.';
|
|
71
|
+
comment on policy "admins_can_select_any_profile" on public.profiles is 'admin users can read any profile.';
|
|
72
|
+
comment on policy "admins_can_update_any_profile" on public.profiles is 'admin users can update any profile.';
|
|
73
|
+
comment on policy "admins_can_insert_profiles" on public.profiles is 'admin users can insert new profiles.';
|
|
74
|
+
|
|
75
|
+
-- Note on Deletion: Deletion is handled by `on delete cascade` from `auth.users`.
|
|
76
|
+
-- If direct deletion from `profiles` table is needed (e.g., by an admin), a policy would be:
|
|
77
|
+
-- create policy "admins_can_delete_profiles"
|
|
78
|
+
-- on public.profiles for delete
|
|
79
|
+
-- using (
|
|
80
|
+
-- exists (
|
|
81
|
+
-- select 1
|
|
82
|
+
-- from public.profiles
|
|
83
|
+
-- where id = auth.uid() and role = 'ADMIN'
|
|
84
|
+
-- )
|
|
85
|
+
-- );
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
-- Migration to fix recursive RLS policies on the 'profiles' table
|
|
2
|
+
|
|
3
|
+
-- 1. Create a helper function to get the current user's role securely
|
|
4
|
+
-- This function runs with the definer's privileges, avoiding RLS recursion
|
|
5
|
+
-- when called from within an RLS policy.
|
|
6
|
+
create or replace function public.get_current_user_role()
|
|
7
|
+
returns public.user_role -- Your ENUM type for roles
|
|
8
|
+
language sql
|
|
9
|
+
stable -- Indicates the function doesn't modify the database
|
|
10
|
+
security definer
|
|
11
|
+
set search_path = public -- Ensures 'profiles' table is found in 'public' schema
|
|
12
|
+
as $$
|
|
13
|
+
select role from public.profiles where id = auth.uid();
|
|
14
|
+
$$;
|
|
15
|
+
|
|
16
|
+
comment on function public.get_current_user_role() is 'Fetches the role of the currently authenticated user. SECURITY DEFINER to prevent RLS recursion issues when used in policies.';
|
|
17
|
+
|
|
18
|
+
-- 2. Drop the old, problematic RLS policies
|
|
19
|
+
-- It's good practice to drop before creating, even if they might not exist or cause errors if they don't.
|
|
20
|
+
-- The original error means the "admins_can_select_any_profile" policy was indeed created.
|
|
21
|
+
drop policy if exists "admins_can_select_any_profile" on public.profiles;
|
|
22
|
+
drop policy if exists "admins_can_update_any_profile" on public.profiles;
|
|
23
|
+
drop policy if exists "admins_can_insert_profiles" on public.profiles;
|
|
24
|
+
-- Add any other admin policies that used the recursive pattern, e.g., for delete
|
|
25
|
+
-- drop policy if exists "admins_can_delete_profiles" on public.profiles;
|
|
26
|
+
|
|
27
|
+
-- 3. Recreate the admin policies using the helper function
|
|
28
|
+
-- For SELECT: Allows admins to select any profile.
|
|
29
|
+
create policy "admins_can_select_any_profile"
|
|
30
|
+
on public.profiles for select
|
|
31
|
+
using (public.get_current_user_role() = 'ADMIN'); -- Compares ENUM to 'ADMIN' literal
|
|
32
|
+
|
|
33
|
+
-- For UPDATE: Allows admins to update any profile.
|
|
34
|
+
create policy "admins_can_update_any_profile"
|
|
35
|
+
on public.profiles for update
|
|
36
|
+
using (public.get_current_user_role() = 'ADMIN')
|
|
37
|
+
with check (public.get_current_user_role() = 'ADMIN');
|
|
38
|
+
|
|
39
|
+
-- For INSERT: Allows admins to insert profiles (trigger handles new users, this is for manual admin action).
|
|
40
|
+
create policy "admins_can_insert_profiles"
|
|
41
|
+
on public.profiles for insert
|
|
42
|
+
with check (public.get_current_user_role() = 'ADMIN');
|
|
43
|
+
|
|
44
|
+
-- (Optional) If you had an admin delete policy with the recursive pattern:
|
|
45
|
+
-- create policy "admins_can_delete_profiles"
|
|
46
|
+
-- on public.profiles for delete
|
|
47
|
+
-- using (public.get_current_user_role() = 'ADMIN');
|
|
48
|
+
|
|
49
|
+
-- Note: The "users_can_select_own_profile" and "users_can_update_own_profile"
|
|
50
|
+
-- policies from your previous migration are fine and do not need to be changed
|
|
51
|
+
-- as they don't have the recursive subquery pattern.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
-- lowercase sql
|
|
2
|
+
|
|
3
|
+
-- 1. create the languages table
|
|
4
|
+
create table public.languages (
|
|
5
|
+
id bigint generated by default as identity primary key,
|
|
6
|
+
code text not null unique, -- e.g., 'en', 'fr' (BCP 47 language tags)
|
|
7
|
+
name text not null, -- e.g., 'English', 'Français'
|
|
8
|
+
is_default boolean not null default false,
|
|
9
|
+
created_at timestamp with time zone not null default now(),
|
|
10
|
+
updated_at timestamp with time zone not null default now()
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
comment on table public.languages is 'Stores supported languages for the CMS.';
|
|
14
|
+
comment on column public.languages.code is 'BCP 47 language code (e.g., en, en-US, fr, fr-CA).';
|
|
15
|
+
comment on column public.languages.name is 'Human-readable name of the language.';
|
|
16
|
+
comment on column public.languages.is_default is 'Indicates if this is the default fallback language.';
|
|
17
|
+
|
|
18
|
+
-- 2. create a partial unique index to ensure only one language can be default
|
|
19
|
+
-- This ensures data integrity at the database level for the is_default flag.
|
|
20
|
+
create unique index ensure_single_default_language_idx
|
|
21
|
+
on public.languages (is_default)
|
|
22
|
+
where (is_default = true);
|
|
23
|
+
|
|
24
|
+
-- 3. seed initial languages: english (default) and french
|
|
25
|
+
insert into public.languages (code, name, is_default)
|
|
26
|
+
values
|
|
27
|
+
('en', 'English', true),
|
|
28
|
+
('fr', 'Français', false);
|
|
29
|
+
|
|
30
|
+
-- 4. enable row level security (rls) on the languages table
|
|
31
|
+
alter table public.languages enable row level security;
|
|
32
|
+
|
|
33
|
+
-- 5. create rls policies for the languages table
|
|
34
|
+
-- policy: allow public read access to languages
|
|
35
|
+
create policy "languages_are_publicly_readable"
|
|
36
|
+
on public.languages for select
|
|
37
|
+
to anon, authenticated
|
|
38
|
+
using (true);
|
|
39
|
+
|
|
40
|
+
-- policy: allow admins to manage languages (insert, update, delete)
|
|
41
|
+
create policy "admins_can_manage_languages"
|
|
42
|
+
on public.languages for all -- covers insert, update, delete
|
|
43
|
+
to authenticated
|
|
44
|
+
using (
|
|
45
|
+
-- check if the user is an admin by calling the helper function created in phase 1
|
|
46
|
+
public.get_current_user_role() = 'ADMIN'
|
|
47
|
+
)
|
|
48
|
+
with check (
|
|
49
|
+
public.get_current_user_role() = 'ADMIN'
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
-- (Optional) Trigger to automatically update 'updated_at' timestamp
|
|
53
|
+
create or replace function public.handle_languages_update()
|
|
54
|
+
returns trigger
|
|
55
|
+
language plpgsql
|
|
56
|
+
as $$
|
|
57
|
+
begin
|
|
58
|
+
new.updated_at = now();
|
|
59
|
+
return new;
|
|
60
|
+
end;
|
|
61
|
+
$$;
|
|
62
|
+
|
|
63
|
+
create trigger on_languages_update
|
|
64
|
+
before update on public.languages
|
|
65
|
+
for each row
|
|
66
|
+
execute procedure public.handle_languages_update();
|