security: fix private storage buckets, api access, and admin RLS bypasses
All checks were successful
Staging Build / build (push) Successful in 3m41s
All checks were successful
Staging Build / build (push) Successful in 3m41s
This commit is contained in:
@@ -67,7 +67,7 @@ export async function updateSession(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Admin protection
|
// Admin protection
|
||||||
if (request.nextUrl.pathname.startsWith("/admin")) {
|
if (request.nextUrl.pathname.startsWith("/admin") || request.nextUrl.pathname.startsWith("/api/admin")) {
|
||||||
if (!user || !user.sub) {
|
if (!user || !user.sub) {
|
||||||
const url = request.nextUrl.clone();
|
const url = request.nextUrl.clone();
|
||||||
url.pathname = "/auth/login";
|
url.pathname = "/auth/login";
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
-- Migration: Secure invoices bucket and allow admin access in RLS policies
|
||||||
|
|
||||||
|
-- 1. Secure storage bucket and set public to false
|
||||||
|
UPDATE storage.buckets SET public = false WHERE id = 'invoices';
|
||||||
|
|
||||||
|
-- 2. Update storage policy for invoice access to check authenticated company assignment or admin
|
||||||
|
DROP POLICY IF EXISTS "Public Access" ON storage.objects;
|
||||||
|
CREATE POLICY "Secure Invoice Access" ON storage.objects FOR SELECT USING (
|
||||||
|
bucket_id = 'invoices'
|
||||||
|
AND (
|
||||||
|
-- Admins can read all invoices
|
||||||
|
(SELECT role FROM public.users WHERE id = auth.uid()) = 'admin'
|
||||||
|
OR
|
||||||
|
-- Partner users can only read invoices belonging to their company
|
||||||
|
-- Filename format: ab_[order_id].pdf
|
||||||
|
(SELECT company_id FROM public.users WHERE id = auth.uid()) = (
|
||||||
|
SELECT company_id FROM public.orders
|
||||||
|
WHERE id = CAST(substring(name from 'ab_(.+)\.pdf') AS UUID)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 3. Recreate end_customers RLS policies to allow admin bypass
|
||||||
|
DROP POLICY IF EXISTS "Partner sehen nur eigene Endkunden" ON public.end_customers;
|
||||||
|
CREATE POLICY "Partner sehen nur eigene Endkunden" ON public.end_customers
|
||||||
|
FOR ALL
|
||||||
|
USING (
|
||||||
|
(SELECT role FROM public.users WHERE id = auth.uid()) = 'admin'
|
||||||
|
OR partner_id = (SELECT company_id FROM public.users WHERE id = auth.uid())
|
||||||
|
)
|
||||||
|
WITH CHECK (
|
||||||
|
(SELECT role FROM public.users WHERE id = auth.uid()) = 'admin'
|
||||||
|
OR partner_id = (SELECT company_id FROM public.users WHERE id = auth.uid())
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 4. Recreate licenses SELECT RLS policy to allow admin bypass
|
||||||
|
DROP POLICY IF EXISTS "Partner sehen Lizenzen eigener Kunden" ON public.licenses;
|
||||||
|
CREATE POLICY "Partner sehen Lizenzen eigener Kunden" ON public.licenses
|
||||||
|
FOR SELECT
|
||||||
|
USING (
|
||||||
|
(SELECT role FROM public.users WHERE id = auth.uid()) = 'admin'
|
||||||
|
OR EXISTS (
|
||||||
|
SELECT 1 FROM public.end_customers c
|
||||||
|
WHERE c.id = licenses.end_customer_id
|
||||||
|
AND c.partner_id = (SELECT company_id FROM public.users WHERE id = auth.uid())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 5. Recreate licenses INSERT RLS policy to allow admin bypass
|
||||||
|
DROP POLICY IF EXISTS "Partner erstellen Lizenzen eigener Kunden" ON public.licenses;
|
||||||
|
CREATE POLICY "Partner erstellen Lizenzen eigener Kunden" ON public.licenses
|
||||||
|
FOR INSERT
|
||||||
|
WITH CHECK (
|
||||||
|
(SELECT role FROM public.users WHERE id = auth.uid()) = 'admin'
|
||||||
|
OR EXISTS (
|
||||||
|
SELECT 1 FROM public.end_customers c
|
||||||
|
WHERE c.id = licenses.end_customer_id
|
||||||
|
AND c.partner_id = (SELECT company_id FROM public.users WHERE id = auth.uid())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Reload Schema Cache
|
||||||
|
NOTIFY pgrst, 'reload schema';
|
||||||
Reference in New Issue
Block a user