MIF_E31222656/lib/utils/fix_users_policy.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');
}
}
}
}
}