Initial commit of akmon project
This commit is contained in:
119
doc_mall/subscription_rls_policies.sql
Normal file
119
doc_mall/subscription_rls_policies.sql
Normal file
@@ -0,0 +1,119 @@
|
||||
-- Subscription RLS and permissions
|
||||
-- Purpose: Ensure admins can read/write ml_user_subscriptions and ml_subscription_plans;
|
||||
-- consumers can only access their own subscriptions; everyone can read active plans.
|
||||
-- Notes:
|
||||
-- - Designed for Supabase (auth.uid(), auth.jwt()).
|
||||
-- - Adjust table/column names if they differ in your DB.
|
||||
|
||||
-- 1) Helper: identify admin users
|
||||
-- Prefer JWT app_metadata.role = 'admin' if you set it; fallback to ak_users.user_type = 5
|
||||
-- (5 corresponds to ADMIN per MALL_USER_TYPE).
|
||||
create or replace function public.is_admin()
|
||||
returns boolean
|
||||
language sql
|
||||
stable
|
||||
as $$
|
||||
select coalesce(
|
||||
-- Check custom claim from JWT: { app_metadata: { role: 'admin' } }
|
||||
((auth.jwt() -> 'app_metadata' ->> 'role') = 'admin')
|
||||
-- Fallback: ak_users.user_type = 5 (cast to text for compatibility), match user by id as text
|
||||
or exists (
|
||||
select 1 from public.ak_users u
|
||||
where u.id::text = auth.uid()::text
|
||||
and u.user_type::text = '5'
|
||||
)
|
||||
, false);
|
||||
$$;
|
||||
|
||||
comment on function public.is_admin is 'Returns true if current JWT/app user is admin by claim or ak_users.user_type=5.';
|
||||
|
||||
-- 2) Enable RLS on subscription tables
|
||||
alter table if exists public.ml_subscription_plans enable row level security;
|
||||
alter table if exists public.ml_user_subscriptions enable row level security;
|
||||
|
||||
grant select on table public.ml_subscription_plans to anon, authenticated;
|
||||
grant select, insert, update, delete on table public.ml_subscription_plans to authenticated; -- limited by RLS
|
||||
grant select, insert, update, delete on table public.ml_user_subscriptions to authenticated; -- limited by RLS
|
||||
|
||||
-- 4) Policies for ml_subscription_plans
|
||||
-- 4.1 Everyone can read active plans
|
||||
drop policy if exists ml_plans_select_active on public.ml_subscription_plans;
|
||||
create policy ml_plans_select_active
|
||||
on public.ml_subscription_plans
|
||||
for select
|
||||
to anon, authenticated
|
||||
using (is_active = true);
|
||||
|
||||
-- 4.2 Admin can do anything
|
||||
drop policy if exists ml_plans_admin_all on public.ml_subscription_plans;
|
||||
create policy ml_plans_admin_all
|
||||
on public.ml_subscription_plans
|
||||
for all
|
||||
to authenticated
|
||||
using (public.is_admin())
|
||||
with check (public.is_admin());
|
||||
|
||||
-- 5) Policies for ml_user_subscriptions
|
||||
-- 5.1 Users can see their own subscriptions
|
||||
drop policy if exists ml_user_subs_select_own on public.ml_user_subscriptions;
|
||||
create policy ml_user_subs_select_own
|
||||
on public.ml_user_subscriptions
|
||||
for select
|
||||
to authenticated
|
||||
using (user_id = auth.uid());
|
||||
|
||||
-- 5.2 Users can create their own subscriptions (checkout)
|
||||
drop policy if exists ml_user_subs_insert_own on public.ml_user_subscriptions;
|
||||
create policy ml_user_subs_insert_own
|
||||
on public.ml_user_subscriptions
|
||||
for insert
|
||||
to authenticated
|
||||
with check (user_id = auth.uid());
|
||||
|
||||
-- 5.3 Users may update their own records (e.g., auto_renew, cancel_at_period_end)
|
||||
-- NOTE: This allows updating any columns; for stricter control, add a BEFORE UPDATE trigger
|
||||
-- that restricts column changes for non-admins.
|
||||
drop policy if exists ml_user_subs_update_own on public.ml_user_subscriptions;
|
||||
create policy ml_user_subs_update_own
|
||||
on public.ml_user_subscriptions
|
||||
for update
|
||||
to authenticated
|
||||
using (user_id = auth.uid())
|
||||
with check (user_id = auth.uid());
|
||||
|
||||
-- 5.4 Admin can do anything on user subscriptions
|
||||
drop policy if exists ml_user_subs_admin_all on public.ml_user_subscriptions;
|
||||
create policy ml_user_subs_admin_all
|
||||
on public.ml_user_subscriptions
|
||||
for all
|
||||
to authenticated
|
||||
using (public.is_admin())
|
||||
with check (public.is_admin());
|
||||
|
||||
-- 6) Optional: Trigger to limit non-admin updates to specific fields
|
||||
-- Uncomment if you want to enforce column-level restrictions
|
||||
-- create or replace function public.enforce_user_sub_update()
|
||||
-- returns trigger language plpgsql as $$
|
||||
-- begin
|
||||
-- if public.is_admin() then
|
||||
-- return new; -- admins can change anything
|
||||
-- end if;
|
||||
-- -- Only allow toggling auto_renew and cancel_at_period_end for owners
|
||||
-- if new.user_id = auth.uid() then
|
||||
-- new.status := old.status;
|
||||
-- new.plan_id := old.plan_id;
|
||||
-- new.start_date := old.start_date;
|
||||
-- new.end_date := old.end_date;
|
||||
-- new.next_billing_date := old.next_billing_date;
|
||||
-- -- allow: auto_renew, cancel_at_period_end
|
||||
-- return new;
|
||||
-- end if;
|
||||
-- raise exception 'Forbidden';
|
||||
-- end $$;
|
||||
-- drop trigger if exists trg_enforce_user_sub_update on public.ml_user_subscriptions;
|
||||
-- create trigger trg_enforce_user_sub_update
|
||||
-- before update on public.ml_user_subscriptions
|
||||
-- for each row execute function public.enforce_user_sub_update();
|
||||
|
||||
-- 7) Safety: ensure no rows are exposed to non-auth users except active plans via select policy above.
|
||||
-- Admins authenticate as normal users with admin claim or ak_users.user_type=5.
|
||||
Reference in New Issue
Block a user