This commit introduces several new scripts for managing database operations, including user creation, permission grants, and data migrations. It also adds new documentation files to guide users through the setup and configuration processes. Additionally, the project structure is updated to enhance organization and maintainability, ensuring a smoother development experience for contributors. These changes support the ongoing transition to a web-based architecture and improve overall project functionality.
140 lines
3.9 KiB
TypeScript
Executable File
140 lines
3.9 KiB
TypeScript
Executable File
#!/usr/bin/env tsx
|
|
/**
|
|
* Check database permissions and provide helpful error messages
|
|
* This script checks if the read-only user has SELECT permissions on required tables
|
|
*/
|
|
|
|
import { PrismaClient } from '@prisma/client';
|
|
import { prisma } from '../lib/db';
|
|
|
|
const REQUIRED_TABLES = [
|
|
'photos',
|
|
'people',
|
|
'faces',
|
|
'person_encodings',
|
|
'tags',
|
|
'phototaglinkage',
|
|
'photo_favorites',
|
|
];
|
|
|
|
async function checkPermissions() {
|
|
console.log('🔍 Checking database permissions...\n');
|
|
|
|
// Extract username from DATABASE_URL
|
|
const dbUrl = process.env.DATABASE_URL;
|
|
if (!dbUrl) {
|
|
console.error('❌ DATABASE_URL not found in environment variables');
|
|
console.log('\nPlease add DATABASE_URL to your .env file:');
|
|
console.log('DATABASE_URL="postgresql://username:password@localhost:5432/punimtag"');
|
|
process.exit(1);
|
|
}
|
|
|
|
const match = dbUrl.match(/postgresql:\/\/([^:]+):/);
|
|
if (!match) {
|
|
console.error('❌ Could not parse username from DATABASE_URL');
|
|
process.exit(1);
|
|
}
|
|
|
|
const username = match[1];
|
|
console.log(`📋 Checking permissions for user: ${username}\n`);
|
|
|
|
const errors: string[] = [];
|
|
const successes: string[] = [];
|
|
|
|
// Test each required table
|
|
for (const table of REQUIRED_TABLES) {
|
|
try {
|
|
// Try to query the table
|
|
let query: any;
|
|
switch (table) {
|
|
case 'photos':
|
|
query = prisma.photo.findFirst();
|
|
break;
|
|
case 'people':
|
|
query = prisma.person.findFirst();
|
|
break;
|
|
case 'faces':
|
|
query = prisma.face.findFirst();
|
|
break;
|
|
case 'person_encodings':
|
|
// Skip person_encodings if not in schema
|
|
try {
|
|
query = (prisma as any).personEncoding?.findFirst();
|
|
if (!query) continue;
|
|
} catch {
|
|
continue;
|
|
}
|
|
break;
|
|
case 'tags':
|
|
query = prisma.tag.findFirst();
|
|
break;
|
|
case 'phototaglinkage':
|
|
query = prisma.photoTagLinkage.findFirst();
|
|
break;
|
|
case 'photo_favorites':
|
|
query = prisma.photoFavorite.findFirst();
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
|
|
if (query) {
|
|
await query;
|
|
successes.push(`✅ ${table} - SELECT permission OK`);
|
|
}
|
|
} catch (error: any) {
|
|
if (error.message?.includes('permission denied')) {
|
|
errors.push(`❌ ${table} - Permission denied`);
|
|
} else if (error.message?.includes('does not exist')) {
|
|
errors.push(`⚠️ ${table} - Table does not exist (may be OK if not used)`);
|
|
} else {
|
|
errors.push(`❌ ${table} - ${error.message}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log('\n📊 Permission Check Results:\n');
|
|
successes.forEach((msg) => console.log(msg));
|
|
if (errors.length > 0) {
|
|
console.log('');
|
|
errors.forEach((msg) => console.log(msg));
|
|
}
|
|
|
|
if (errors.some((e) => e.includes('Permission denied'))) {
|
|
console.log('\n❌ Permission errors detected!\n');
|
|
console.log('To fix this, run the following SQL as a PostgreSQL superuser:\n');
|
|
console.log('```bash');
|
|
console.log(`psql -U postgres -d punimtag -f grant_readonly_permissions.sql`);
|
|
console.log('```\n');
|
|
console.log('Or manually run:\n');
|
|
console.log('```sql');
|
|
console.log(`-- Connect to database`);
|
|
console.log(`\\c punimtag`);
|
|
console.log('');
|
|
console.log(`-- Grant permissions`);
|
|
REQUIRED_TABLES.forEach((table) => {
|
|
console.log(`GRANT SELECT ON TABLE ${table} TO ${username};`);
|
|
});
|
|
console.log(`GRANT USAGE ON SCHEMA public TO ${username};`);
|
|
console.log(`GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO ${username};`);
|
|
console.log('```\n');
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log('\n✅ All required permissions are granted!');
|
|
process.exit(0);
|
|
}
|
|
|
|
checkPermissions().catch((error) => {
|
|
console.error('Error checking permissions:', error);
|
|
process.exit(1);
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|