184 lines
5.3 KiB
Dart
184 lines
5.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
|
|
/// Utility class to fix the users policy
|
|
class FixUsersPolicyUtil {
|
|
/// Fix the users policy to prevent infinite recursion
|
|
static Future<void> fixUsersPolicy(BuildContext context) async {
|
|
try {
|
|
// Show loading dialog
|
|
showDialog(
|
|
context: context,
|
|
barrierDismissible: false,
|
|
builder:
|
|
(context) => const AlertDialog(
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
CircularProgressIndicator(),
|
|
SizedBox(height: 16),
|
|
Text('Memperbaiki kebijakan tabel users...'),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
final client = Supabase.instance.client;
|
|
|
|
// Ensure execute_sql function exists
|
|
await _ensureExecuteSqlExists(client);
|
|
|
|
// Step 1: Drop the problematic policy
|
|
await client.rpc(
|
|
'execute_sql',
|
|
params: {
|
|
'sql_statement': 'DROP POLICY IF EXISTS users_policy ON auth.users;',
|
|
},
|
|
);
|
|
print('Dropped problematic policy');
|
|
|
|
// Step 2: Ensure user_roles table exists
|
|
try {
|
|
await client.rpc(
|
|
'execute_sql',
|
|
params: {
|
|
'sql_statement': '''
|
|
CREATE TABLE IF NOT EXISTS public.user_roles (
|
|
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
user_id uuid REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
role text NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
''',
|
|
},
|
|
);
|
|
print('Ensured user_roles table exists');
|
|
} catch (e) {
|
|
print('Error creating user_roles table: $e');
|
|
}
|
|
|
|
// Step 3: Create a new policy without recursion
|
|
await client.rpc(
|
|
'execute_sql',
|
|
params: {
|
|
'sql_statement': '''
|
|
CREATE POLICY users_policy ON auth.users
|
|
FOR SELECT
|
|
USING (
|
|
auth.uid() = id
|
|
OR
|
|
EXISTS (
|
|
SELECT 1 FROM public.user_roles
|
|
WHERE user_id = auth.uid() AND role = 'admin'
|
|
)
|
|
);
|
|
''',
|
|
},
|
|
);
|
|
print('Created new policy');
|
|
|
|
// Step 4: Ensure current user is admin
|
|
final userId = client.auth.currentUser?.id;
|
|
if (userId != null) {
|
|
try {
|
|
await client.rpc(
|
|
'execute_sql',
|
|
params: {
|
|
'sql_statement': '''
|
|
INSERT INTO public.user_roles (user_id, role)
|
|
VALUES ('$userId', 'admin')
|
|
ON CONFLICT (user_id, role) DO NOTHING;
|
|
''',
|
|
},
|
|
);
|
|
print('Ensured current user is admin');
|
|
} catch (e) {
|
|
// Try without constraint if the first attempt fails
|
|
try {
|
|
await client.rpc(
|
|
'execute_sql',
|
|
params: {
|
|
'sql_statement': '''
|
|
INSERT INTO public.user_roles (user_id, role)
|
|
SELECT '$userId', 'admin'
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM public.user_roles WHERE user_id = '$userId' AND role = 'admin'
|
|
);
|
|
''',
|
|
},
|
|
);
|
|
print('Ensured current user is admin (alternative method)');
|
|
} catch (innerE) {
|
|
print('Error ensuring admin status: $innerE');
|
|
}
|
|
}
|
|
}
|
|
|
|
// Step 5: Grant necessary permissions
|
|
await client.rpc(
|
|
'execute_sql',
|
|
params: {
|
|
'sql_statement':
|
|
'GRANT SELECT ON auth.users TO authenticated; GRANT SELECT ON auth.users TO anon;',
|
|
},
|
|
);
|
|
print('Granted permissions');
|
|
|
|
// Close the dialog
|
|
Navigator.pop(context);
|
|
|
|
// Show success message
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text('Kebijakan tabel users berhasil diperbaiki'),
|
|
backgroundColor: Colors.green,
|
|
),
|
|
);
|
|
} catch (e) {
|
|
print('Error fixing users policy: $e');
|
|
|
|
// Close the dialog if it's open
|
|
Navigator.pop(context);
|
|
|
|
// Show error message
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text(
|
|
'Gagal memperbaiki kebijakan tabel users: ${e.toString()}',
|
|
),
|
|
backgroundColor: Colors.red,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Ensure the execute_sql function exists
|
|
static Future<void> _ensureExecuteSqlExists(SupabaseClient client) async {
|
|
try {
|
|
// Try to call the function to see if it exists
|
|
await client.rpc('execute_sql', params: {'sql_statement': 'SELECT 1;'});
|
|
print('execute_sql function exists');
|
|
} catch (e) {
|
|
print('execute_sql function may not exist, trying to create it: $e');
|
|
|
|
// Function doesn't exist, create it using raw SQL query
|
|
try {
|
|
// Try to access a table to check connection
|
|
await client.from('_temp_execute_sql_check').select();
|
|
} catch (e) {
|
|
print('Error checking database connection: $e');
|
|
|
|
// Try a different approach
|
|
try {
|
|
// Try to access profiles table which should exist
|
|
final response = await client.from('profiles').select().limit(1);
|
|
print('Database connection works: ${response.length} profiles found');
|
|
} catch (e) {
|
|
print('Could not connect to database: $e');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|