mirror of
https://github.com/christianvidalwolf-prog/Craze-Data-check.git
synced 2026-08-03 13:45:24 +02:00
Security: Enable RLS support by passing user JWT in Supabase requests
Replaced hardcoded anon key as Bearer token with authHeaders() helper that uses the authenticated user's access_token when available, enabling Row Level Security policies to identify the calling user correctly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
7a32605189
commit
dec24f52f4
+19
-25
@@ -1,5 +1,12 @@
|
|||||||
const SUPABASE_URL = 'https://hwithddwaapyhnfwcesj.supabase.co';
|
const SUPABASE_URL = 'https://hwithddwaapyhnfwcesj.supabase.co';
|
||||||
const SUPABASE_KEY = 'sb_publishable_fGXkh0bSrAOqSk2jWKAzSg_NJD9YPCv';
|
const SUPABASE_ANON_KEY = 'sb_publishable_fGXkh0bSrAOqSk2jWKAzSg_NJD9YPCv';
|
||||||
|
|
||||||
|
function authHeaders(token?: string): Record<string, string> {
|
||||||
|
return {
|
||||||
|
'apikey': SUPABASE_ANON_KEY,
|
||||||
|
'Authorization': `Bearer ${token ?? SUPABASE_ANON_KEY}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export interface ExcelRow extends Array<any> {}
|
export interface ExcelRow extends Array<any> {}
|
||||||
|
|
||||||
@@ -14,10 +21,7 @@ export async function getAllSyncedRows(token?: string): Promise<Record<string, S
|
|||||||
`${SUPABASE_URL}/rest/v1/products?select=product_id,data,status&order=updated_at.desc`,
|
`${SUPABASE_URL}/rest/v1/products?select=product_id,data,status&order=updated_at.desc`,
|
||||||
{
|
{
|
||||||
cache: 'no-store',
|
cache: 'no-store',
|
||||||
headers: {
|
headers: authHeaders(token),
|
||||||
'apikey': SUPABASE_KEY,
|
|
||||||
'Authorization': `Bearer ${SUPABASE_KEY}`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -46,9 +50,8 @@ export async function saveRowToSupabase(articleNo: string, rowData: ExcelRow, to
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'apikey': SUPABASE_KEY,
|
...authHeaders(token),
|
||||||
'Authorization': `Bearer ${SUPABASE_KEY}`,
|
'Prefer': 'resolution=merge-duplicates',
|
||||||
'Prefer': 'resolution=merge-duplicates'
|
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
product_id: articleNo,
|
product_id: articleNo,
|
||||||
@@ -99,9 +102,8 @@ export async function saveHistoryEntry(
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'apikey': SUPABASE_KEY,
|
...authHeaders(token),
|
||||||
'Authorization': `Bearer ${SUPABASE_KEY}`,
|
'Prefer': 'return=minimal',
|
||||||
'Prefer': 'return=minimal'
|
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
product_id: productId,
|
product_id: productId,
|
||||||
@@ -135,18 +137,14 @@ export async function getHistory(token?: string): Promise<HistoryEntry[]> {
|
|||||||
`${SUPABASE_URL}/rest/v1/products_history?select=*&order=changed_at.desc&limit=100`,
|
`${SUPABASE_URL}/rest/v1/products_history?select=*&order=changed_at.desc&limit=100`,
|
||||||
{
|
{
|
||||||
cache: 'no-store',
|
cache: 'no-store',
|
||||||
headers: {
|
headers: authHeaders(token),
|
||||||
'apikey': SUPABASE_KEY,
|
|
||||||
// Try using only the ANON key just in case RLS or token expiry is failing silently
|
|
||||||
'Authorization': `Bearer ${SUPABASE_KEY}`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const err = await response.text();
|
const err = await response.text();
|
||||||
return [{
|
return [{
|
||||||
id: 'error-' + Date.now(),
|
id: -1,
|
||||||
product_id: 'ERROR',
|
product_id: 'ERROR',
|
||||||
article_name: `Failed: ${response.status} ${err}`,
|
article_name: `Failed: ${response.status} ${err}`,
|
||||||
old_data: [],
|
old_data: [],
|
||||||
@@ -159,7 +157,7 @@ export async function getHistory(token?: string): Promise<HistoryEntry[]> {
|
|||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Error fetching history:', error);
|
console.error('Error fetching history:', error);
|
||||||
return [{
|
return [{
|
||||||
id: 'error-' + Date.now(),
|
id: -2,
|
||||||
product_id: 'EXCEPTION',
|
product_id: 'EXCEPTION',
|
||||||
article_name: `Message: ${error.message}`,
|
article_name: `Message: ${error.message}`,
|
||||||
old_data: [],
|
old_data: [],
|
||||||
@@ -176,10 +174,7 @@ export async function deleteHistoryEntry(id: string, token?: string): Promise<bo
|
|||||||
`${SUPABASE_URL}/rest/v1/products_history?id=eq.${encodeURIComponent(id)}`,
|
`${SUPABASE_URL}/rest/v1/products_history?id=eq.${encodeURIComponent(id)}`,
|
||||||
{
|
{
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: authHeaders(token),
|
||||||
'apikey': SUPABASE_KEY,
|
|
||||||
'Authorization': `Bearer ${SUPABASE_KEY}`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -198,9 +193,8 @@ export async function resetAllPendingRows(token?: string): Promise<boolean> {
|
|||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'apikey': SUPABASE_KEY,
|
...authHeaders(token),
|
||||||
'Authorization': `Bearer ${SUPABASE_KEY}`,
|
'Prefer': 'return=minimal',
|
||||||
'Prefer': 'return=minimal'
|
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ status: 'synced' })
|
body: JSON.stringify({ status: 'synced' })
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user