mirror of
https://github.com/kyantech/Palmr.git
synced 2025-10-22 22:02:00 +00:00
refactor: update filesystem encryption handling and configuration
refactor: simplify server startup script and move provider/config checks to separate files docs: update documentation to reflect encryption changes and default UID/GID values - Changed default behavior to disable filesystem encryption for improved performance. - Updated environment variable handling for DISABLE_FILESYSTEM_ENCRYPTION and ENCRYPTION_KEY across multiple configuration files. - Added new scripts and configuration files for managing application settings and providers. - Adjusted Dockerfile and server start scripts to reflect changes in UID/GID handling and file management. - Enhanced documentation to clarify encryption options and their implications.
This commit is contained in:
147
infra/check-missing.js
Normal file
147
infra/check-missing.js
Normal file
@@ -0,0 +1,147 @@
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const loadConfigs = () => {
|
||||
try {
|
||||
const configsPath = path.join(__dirname, 'configs.json');
|
||||
const configs = JSON.parse(fs.readFileSync(configsPath, 'utf8'));
|
||||
|
||||
return Object.values(configs).flat();
|
||||
} catch (error) {
|
||||
console.error('Error loading configs:', error.message);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const loadProviders = () => {
|
||||
try {
|
||||
const providersPath = path.join(__dirname, 'providers.json');
|
||||
return JSON.parse(fs.readFileSync(providersPath, 'utf8'));
|
||||
} catch (error) {
|
||||
console.error('Error loading providers:', error.message);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
async function checkSeedingNeeded() {
|
||||
try {
|
||||
const appConfigCount = await prisma.appConfig.count();
|
||||
const userCount = await prisma.user.count();
|
||||
const authProviderCount = await prisma.authProvider.count();
|
||||
|
||||
if (appConfigCount === 0 || userCount === 0) {
|
||||
console.log('true');
|
||||
return;
|
||||
}
|
||||
|
||||
if (authProviderCount === 0) {
|
||||
console.log('true');
|
||||
return;
|
||||
}
|
||||
|
||||
const allConfigs = loadConfigs();
|
||||
const existingConfigs = await prisma.appConfig.findMany({
|
||||
where: {
|
||||
key: {
|
||||
in: allConfigs
|
||||
}
|
||||
},
|
||||
select: { key: true }
|
||||
});
|
||||
const existingConfigKeys = existingConfigs.map(c => c.key);
|
||||
const missingConfigs = allConfigs.filter(key => !existingConfigKeys.includes(key));
|
||||
|
||||
if (missingConfigs.length > 0) {
|
||||
console.log('true');
|
||||
return;
|
||||
}
|
||||
|
||||
const expectedProviders = loadProviders();
|
||||
const existingProviders = await prisma.authProvider.findMany({
|
||||
select: { name: true }
|
||||
});
|
||||
const existingProviderNames = existingProviders.map(p => p.name);
|
||||
const missingProviders = expectedProviders.filter(name => !existingProviderNames.includes(name));
|
||||
|
||||
if (missingProviders.length > 0) {
|
||||
console.log('true');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('false');
|
||||
} catch (error) {
|
||||
console.error('Error checking if seeding is needed:', error);
|
||||
console.log('true');
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
async function checkMissingProviders() {
|
||||
try {
|
||||
const expectedProviders = loadProviders();
|
||||
const existingProviders = await prisma.authProvider.findMany({
|
||||
select: { name: true }
|
||||
});
|
||||
const existingProviderNames = existingProviders.map(p => p.name);
|
||||
const missingProviders = expectedProviders.filter(name => !existingProviderNames.includes(name));
|
||||
|
||||
if (missingProviders.length > 0) {
|
||||
console.log('Missing providers: ' + missingProviders.join(', '));
|
||||
} else {
|
||||
console.log('No missing providers');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking missing providers:', error);
|
||||
console.log('Error checking providers');
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
async function checkMissingConfigs() {
|
||||
try {
|
||||
const allConfigs = loadConfigs();
|
||||
const existingConfigs = await prisma.appConfig.findMany({
|
||||
where: {
|
||||
key: {
|
||||
in: allConfigs
|
||||
}
|
||||
},
|
||||
select: { key: true }
|
||||
});
|
||||
const existingConfigKeys = existingConfigs.map(c => c.key);
|
||||
const missingConfigs = allConfigs.filter(key => !existingConfigKeys.includes(key));
|
||||
|
||||
if (missingConfigs.length > 0) {
|
||||
console.log('Missing configurations: ' + missingConfigs.join(', '));
|
||||
} else {
|
||||
console.log('No missing configurations');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking missing configurations:', error);
|
||||
console.log('Error checking configurations');
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
const command = process.argv[2];
|
||||
|
||||
switch (command) {
|
||||
case 'check-seeding':
|
||||
checkSeedingNeeded();
|
||||
break;
|
||||
case 'check-providers':
|
||||
checkMissingProviders();
|
||||
break;
|
||||
case 'check-configs':
|
||||
checkMissingConfigs();
|
||||
break;
|
||||
default:
|
||||
console.error('Unknown command. Use: check-seeding, check-providers, or check-configs');
|
||||
process.exit(1);
|
||||
}
|
37
infra/configs.json
Normal file
37
infra/configs.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"general": [
|
||||
"appName",
|
||||
"showHomePage",
|
||||
"appDescription",
|
||||
"appLogo",
|
||||
"firstUserAccess",
|
||||
"serverUrl"
|
||||
],
|
||||
"storage": [
|
||||
"maxFileSize",
|
||||
"maxTotalStoragePerUser"
|
||||
],
|
||||
"security": [
|
||||
"jwtSecret",
|
||||
"maxLoginAttempts",
|
||||
"loginBlockDuration",
|
||||
"passwordMinLength",
|
||||
"passwordAuthEnabled",
|
||||
"passwordResetTokenExpiration"
|
||||
],
|
||||
"email": [
|
||||
"smtpEnabled",
|
||||
"smtpHost",
|
||||
"smtpPort",
|
||||
"smtpUser",
|
||||
"smtpPass",
|
||||
"smtpFromName",
|
||||
"smtpFromEmail",
|
||||
"smtpSecure",
|
||||
"smtpNoAuth",
|
||||
"smtpTrustSelfSigned"
|
||||
],
|
||||
"auth-providers": [
|
||||
"authProvidersEnabled"
|
||||
]
|
||||
}
|
11
infra/providers.json
Normal file
11
infra/providers.json
Normal file
@@ -0,0 +1,11 @@
|
||||
[
|
||||
"google",
|
||||
"discord",
|
||||
"github",
|
||||
"auth0",
|
||||
"kinde",
|
||||
"zitadel",
|
||||
"authentik",
|
||||
"frontegg",
|
||||
"pocketid"
|
||||
]
|
@@ -3,8 +3,8 @@ set -e
|
||||
|
||||
echo "🌴 Starting Palmr Server..."
|
||||
|
||||
TARGET_UID=${PALMR_UID:-1001}
|
||||
TARGET_GID=${PALMR_GID:-1001}
|
||||
TARGET_UID=${PALMR_UID:-1000}
|
||||
TARGET_GID=${PALMR_GID:-1000}
|
||||
|
||||
if [ -n "$PALMR_UID" ] || [ -n "$PALMR_GID" ]; then
|
||||
echo "🔧 Runtime UID/GID: $TARGET_UID:$TARGET_GID"
|
||||
@@ -35,200 +35,59 @@ if [ "$(id -u)" = "0" ]; then
|
||||
chown -R $TARGET_UID:$TARGET_GID /app/server/prisma 2>/dev/null || true
|
||||
fi
|
||||
|
||||
run_as_user() {
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
su-exec $TARGET_UID:$TARGET_GID "$@"
|
||||
else
|
||||
"$@"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ ! -f "/app/server/prisma/configs.json" ]; then
|
||||
echo "📄 Copying configuration files..."
|
||||
cp -f /app/infra/configs.json /app/server/prisma/configs.json 2>/dev/null || echo "⚠️ Failed to copy configs.json"
|
||||
cp -f /app/infra/providers.json /app/server/prisma/providers.json 2>/dev/null || echo "⚠️ Failed to copy providers.json"
|
||||
cp -f /app/infra/check-missing.js /app/server/prisma/check-missing.js 2>/dev/null || echo "⚠️ Failed to copy check-missing.js"
|
||||
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
chown $TARGET_UID:$TARGET_GID /app/server/prisma/configs.json /app/server/prisma/providers.json /app/server/prisma/check-missing.js 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "/app/server/prisma/palmr.db" ]; then
|
||||
echo "🚀 First run detected - setting up database..."
|
||||
|
||||
echo "🗄️ Creating database schema..."
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
su-exec $TARGET_UID:$TARGET_GID npx prisma db push --schema=./prisma/schema.prisma --skip-generate
|
||||
else
|
||||
npx prisma db push --schema=./prisma/schema.prisma --skip-generate
|
||||
fi
|
||||
run_as_user npx prisma db push --schema=./prisma/schema.prisma --skip-generate
|
||||
|
||||
echo "🌱 Seeding database..."
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
su-exec $TARGET_UID:$TARGET_GID node ./prisma/seed.js
|
||||
else
|
||||
node ./prisma/seed.js
|
||||
fi
|
||||
run_as_user node ./prisma/seed.js
|
||||
|
||||
echo "✅ Database setup completed!"
|
||||
else
|
||||
echo "♻️ Existing database found"
|
||||
|
||||
echo "🔧 Checking for schema updates..."
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
su-exec $TARGET_UID:$TARGET_GID npx prisma db push --schema=./prisma/schema.prisma --skip-generate
|
||||
else
|
||||
npx prisma db push --schema=./prisma/schema.prisma --skip-generate
|
||||
fi
|
||||
run_as_user npx prisma db push --schema=./prisma/schema.prisma --skip-generate
|
||||
|
||||
echo "🔍 Checking if new tables need seeding..."
|
||||
NEEDS_SEEDING=$(
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
su-exec $TARGET_UID:$TARGET_GID node -e "
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function checkSeedingNeeded() {
|
||||
try {
|
||||
const appConfigCount = await prisma.appConfig.count();
|
||||
const userCount = await prisma.user.count();
|
||||
const authProviderCount = await prisma.authProvider.count();
|
||||
|
||||
if (appConfigCount === 0 || userCount === 0) {
|
||||
console.log('true');
|
||||
return;
|
||||
}
|
||||
|
||||
if (authProviderCount === 0) {
|
||||
console.log('true');
|
||||
return;
|
||||
}
|
||||
|
||||
const expectedProviders = ['google', 'discord', 'github', 'auth0', 'kinde', 'zitadel', 'authentik', 'frontegg', 'pocketid'];
|
||||
const existingProviders = await prisma.authProvider.findMany({
|
||||
select: { name: true }
|
||||
});
|
||||
const existingProviderNames = existingProviders.map(p => p.name);
|
||||
|
||||
const missingProviders = expectedProviders.filter(name => !existingProviderNames.includes(name));
|
||||
|
||||
if (missingProviders.length > 0) {
|
||||
console.log('true');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('false');
|
||||
} catch (error) {
|
||||
console.log('true');
|
||||
} finally {
|
||||
await prisma.\$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
checkSeedingNeeded();
|
||||
" 2>/dev/null || echo "true"
|
||||
else
|
||||
node -e "
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function checkSeedingNeeded() {
|
||||
try {
|
||||
const appConfigCount = await prisma.appConfig.count();
|
||||
const userCount = await prisma.user.count();
|
||||
const authProviderCount = await prisma.authProvider.count();
|
||||
|
||||
if (appConfigCount === 0 || userCount === 0) {
|
||||
console.log('true');
|
||||
return;
|
||||
}
|
||||
|
||||
if (authProviderCount === 0) {
|
||||
console.log('true');
|
||||
return;
|
||||
}
|
||||
|
||||
const expectedProviders = ['google', 'discord', 'github', 'auth0', 'kinde', 'zitadel', 'authentik', 'frontegg', 'pocketid'];
|
||||
const existingProviders = await prisma.authProvider.findMany({
|
||||
select: { name: true }
|
||||
});
|
||||
const existingProviderNames = existingProviders.map(p => p.name);
|
||||
|
||||
const missingProviders = expectedProviders.filter(name => !existingProviderNames.includes(name));
|
||||
|
||||
if (missingProviders.length > 0) {
|
||||
console.log('true');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('false');
|
||||
} catch (error) {
|
||||
console.log('true');
|
||||
} finally {
|
||||
await prisma.\$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
checkSeedingNeeded();
|
||||
" 2>/dev/null || echo "true"
|
||||
fi
|
||||
)
|
||||
NEEDS_SEEDING=$(run_as_user node ./prisma/check-missing.js check-seeding 2>/dev/null || echo "true")
|
||||
|
||||
if [ "$NEEDS_SEEDING" = "true" ]; then
|
||||
echo "🌱 New tables detected or missing data, running seed..."
|
||||
|
||||
# Check which providers are missing for better logging
|
||||
MISSING_PROVIDERS=$(
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
su-exec $TARGET_UID:$TARGET_GID node -e "
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function checkMissingProviders() {
|
||||
try {
|
||||
const expectedProviders = ['google', 'discord', 'github', 'auth0', 'kinde', 'zitadel', 'authentik', 'frontegg', 'pocketid'];
|
||||
const existingProviders = await prisma.authProvider.findMany({
|
||||
select: { name: true }
|
||||
});
|
||||
const existingProviderNames = existingProviders.map(p => p.name);
|
||||
const missingProviders = expectedProviders.filter(name => !existingProviderNames.includes(name));
|
||||
|
||||
if (missingProviders.length > 0) {
|
||||
console.log('Missing providers: ' + missingProviders.join(', '));
|
||||
} else {
|
||||
console.log('No missing providers');
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error checking providers');
|
||||
} finally {
|
||||
await prisma.\$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
checkMissingProviders();
|
||||
" 2>/dev/null || echo "Error checking providers"
|
||||
else
|
||||
node -e "
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function checkMissingProviders() {
|
||||
try {
|
||||
const expectedProviders = ['google', 'discord', 'github', 'auth0', 'kinde', 'zitadel', 'authentik', 'frontegg', 'pocketid'];
|
||||
const existingProviders = await prisma.authProvider.findMany({
|
||||
select: { name: true }
|
||||
});
|
||||
const existingProviderNames = existingProviders.map(p => p.name);
|
||||
const missingProviders = expectedProviders.filter(name => !existingProviderNames.includes(name));
|
||||
|
||||
if (missingProviders.length > 0) {
|
||||
console.log('Missing providers: ' + missingProviders.join(', '));
|
||||
} else {
|
||||
console.log('No missing providers');
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error checking providers');
|
||||
} finally {
|
||||
await prisma.\$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
checkMissingProviders();
|
||||
" 2>/dev/null || echo "Error checking providers"
|
||||
fi
|
||||
)
|
||||
|
||||
MISSING_PROVIDERS=$(run_as_user node ./prisma/check-missing.js check-providers 2>/dev/null || echo "Error checking providers")
|
||||
MISSING_CONFIGS=$(run_as_user node ./prisma/check-missing.js check-configs 2>/dev/null || echo "Error checking configurations")
|
||||
|
||||
if [ "$MISSING_PROVIDERS" != "No missing providers" ] && [ "$MISSING_PROVIDERS" != "Error checking providers" ]; then
|
||||
echo "🔍 $MISSING_PROVIDERS"
|
||||
fi
|
||||
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
su-exec $TARGET_UID:$TARGET_GID node ./prisma/seed.js
|
||||
else
|
||||
node ./prisma/seed.js
|
||||
if [ "$MISSING_CONFIGS" != "No missing configurations" ] && [ "$MISSING_CONFIGS" != "Error checking configurations" ]; then
|
||||
echo "⚙️ $MISSING_CONFIGS"
|
||||
fi
|
||||
|
||||
run_as_user node ./prisma/seed.js
|
||||
echo "✅ Seeding completed!"
|
||||
else
|
||||
echo "✅ All tables have data, no seeding needed"
|
||||
@@ -242,4 +101,4 @@ if [ "$(id -u)" = "0" ]; then
|
||||
exec su-exec $TARGET_UID:$TARGET_GID node dist/server.js
|
||||
else
|
||||
exec node dist/server.js
|
||||
fi
|
||||
fi
|
Reference in New Issue
Block a user