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
+28
-34
@@ -1,5 +1,12 @@
|
||||
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> {}
|
||||
|
||||
@@ -14,17 +21,14 @@ export async function getAllSyncedRows(token?: string): Promise<Record<string, S
|
||||
`${SUPABASE_URL}/rest/v1/products?select=product_id,data,status&order=updated_at.desc`,
|
||||
{
|
||||
cache: 'no-store',
|
||||
headers: {
|
||||
'apikey': SUPABASE_KEY,
|
||||
'Authorization': `Bearer ${SUPABASE_KEY}`
|
||||
}
|
||||
headers: authHeaders(token),
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errText = await response.text();
|
||||
console.error('getAllSyncedRows failed:', response.status, errText);
|
||||
return {};
|
||||
const errText = await response.text();
|
||||
console.error('getAllSyncedRows failed:', response.status, errText);
|
||||
return {};
|
||||
}
|
||||
const rows = await response.json();
|
||||
const result: Record<string, SyncedRow> = {};
|
||||
@@ -46,9 +50,8 @@ export async function saveRowToSupabase(articleNo: string, rowData: ExcelRow, to
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': SUPABASE_KEY,
|
||||
'Authorization': `Bearer ${SUPABASE_KEY}`,
|
||||
'Prefer': 'resolution=merge-duplicates'
|
||||
...authHeaders(token),
|
||||
'Prefer': 'resolution=merge-duplicates',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
product_id: articleNo,
|
||||
@@ -99,9 +102,8 @@ export async function saveHistoryEntry(
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': SUPABASE_KEY,
|
||||
'Authorization': `Bearer ${SUPABASE_KEY}`,
|
||||
'Prefer': 'return=minimal'
|
||||
...authHeaders(token),
|
||||
'Prefer': 'return=minimal',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
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`,
|
||||
{
|
||||
cache: 'no-store',
|
||||
headers: {
|
||||
'apikey': SUPABASE_KEY,
|
||||
// Try using only the ANON key just in case RLS or token expiry is failing silently
|
||||
'Authorization': `Bearer ${SUPABASE_KEY}`
|
||||
}
|
||||
headers: authHeaders(token),
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const err = await response.text();
|
||||
return [{
|
||||
id: 'error-' + Date.now(),
|
||||
id: -1,
|
||||
product_id: 'ERROR',
|
||||
article_name: `Failed: ${response.status} ${err}`,
|
||||
old_data: [],
|
||||
@@ -159,13 +157,13 @@ export async function getHistory(token?: string): Promise<HistoryEntry[]> {
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching history:', error);
|
||||
return [{
|
||||
id: 'error-' + Date.now(),
|
||||
product_id: 'EXCEPTION',
|
||||
article_name: `Message: ${error.message}`,
|
||||
old_data: [],
|
||||
new_data: [],
|
||||
changed_at: new Date().toISOString(),
|
||||
changed_by: 'system'
|
||||
id: -2,
|
||||
product_id: 'EXCEPTION',
|
||||
article_name: `Message: ${error.message}`,
|
||||
old_data: [],
|
||||
new_data: [],
|
||||
changed_at: new Date().toISOString(),
|
||||
changed_by: 'system'
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -176,10 +174,7 @@ export async function deleteHistoryEntry(id: string, token?: string): Promise<bo
|
||||
`${SUPABASE_URL}/rest/v1/products_history?id=eq.${encodeURIComponent(id)}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'apikey': SUPABASE_KEY,
|
||||
'Authorization': `Bearer ${SUPABASE_KEY}`
|
||||
}
|
||||
headers: authHeaders(token),
|
||||
}
|
||||
);
|
||||
|
||||
@@ -198,9 +193,8 @@ export async function resetAllPendingRows(token?: string): Promise<boolean> {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': SUPABASE_KEY,
|
||||
'Authorization': `Bearer ${SUPABASE_KEY}`,
|
||||
'Prefer': 'return=minimal'
|
||||
...authHeaders(token),
|
||||
'Prefer': 'return=minimal',
|
||||
},
|
||||
body: JSON.stringify({ status: 'synced' })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user