fix: database location
Founded a major mistake: db overwrites during install. Now all scripts save db in special folder and don't overwrite it.
This commit is contained in:
@@ -63,3 +63,8 @@ docker-compose.yml
|
|||||||
README.md
|
README.md
|
||||||
*.md
|
*.md
|
||||||
|
|
||||||
|
# Database files
|
||||||
|
db/
|
||||||
|
*.db
|
||||||
|
*.db-shm
|
||||||
|
*.db-wal
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -45,7 +45,7 @@ next-env.d.ts
|
|||||||
error.log
|
error.log
|
||||||
|
|
||||||
# database files
|
# database files
|
||||||
data/
|
db/
|
||||||
*.db
|
*.db
|
||||||
*.db-shm
|
*.db-shm
|
||||||
*.db-wal
|
*.db-wal
|
||||||
@@ -109,7 +109,7 @@ kspguti-schedule/
|
|||||||
│ └── README.md # Documentation for old files
|
│ └── README.md # Documentation for old files
|
||||||
├── scripts/ # Deployment scripts
|
├── scripts/ # Deployment scripts
|
||||||
├── systemd/ # Systemd service file
|
├── systemd/ # Systemd service file
|
||||||
├── data/ # SQLite database files
|
├── db/ # SQLite database files
|
||||||
├── components.json # shadcn/ui config
|
├── components.json # shadcn/ui config
|
||||||
├── docker-compose.yml # Docker Compose config
|
├── docker-compose.yml # Docker Compose config
|
||||||
├── Dockerfile # Docker image definition
|
├── Dockerfile # Docker image definition
|
||||||
@@ -215,11 +215,12 @@ docker-compose down
|
|||||||
- `NEXT_PUBLIC_SITE_URL` - Site URL for canonical links and sitemap (optional)
|
- `NEXT_PUBLIC_SITE_URL` - Site URL for canonical links and sitemap (optional)
|
||||||
|
|
||||||
**Database:**
|
**Database:**
|
||||||
- The application uses SQLite database (`data/schedule-app.db`) for storing:
|
- The application uses SQLite database (`db/schedule-app.db`) for storing:
|
||||||
- Groups configuration
|
- Groups configuration
|
||||||
- Application settings
|
- Application settings
|
||||||
- Admin password (hashed with bcrypt)
|
- Admin password (hashed with bcrypt)
|
||||||
- Database is automatically created on first run
|
- Database is automatically created on first run in the `db/` directory at the project root
|
||||||
|
- Database directory is excluded from deployment scripts to preserve data
|
||||||
- No additional database setup required
|
- No additional database setup required
|
||||||
|
|
||||||
**Note:** Admin password is stored in SQLite database. Default password is `ksadmin` - change it after first login!
|
**Note:** Admin password is stored in SQLite database. Default password is `ksadmin` - change it after first login!
|
||||||
|
|||||||
27
old/data/groups.json
Normal file
27
old/data/groups.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"ib4k": {
|
||||||
|
"parseId": 138,
|
||||||
|
"name": "ИБ-4к",
|
||||||
|
"course": 4
|
||||||
|
},
|
||||||
|
"ib5": {
|
||||||
|
"parseId": 144,
|
||||||
|
"name": "ИБ-5",
|
||||||
|
"course": 3
|
||||||
|
},
|
||||||
|
"ib6": {
|
||||||
|
"parseId": 145,
|
||||||
|
"name": "ИБ-6",
|
||||||
|
"course": 3
|
||||||
|
},
|
||||||
|
"ib7k": {
|
||||||
|
"parseId": 172,
|
||||||
|
"name": "ИБ-7к",
|
||||||
|
"course": 3
|
||||||
|
},
|
||||||
|
"ib3": {
|
||||||
|
"parseId": 123,
|
||||||
|
"name": "ИБ-3",
|
||||||
|
"course": 4
|
||||||
|
}
|
||||||
|
}
|
||||||
18
old/data/groups.ts
Normal file
18
old/data/groups.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// Загружаем группы из JSON файла только на сервере
|
||||||
|
// На клиенте будет пустой объект, группы должны передаваться через props
|
||||||
|
let groups: { [group: string]: [number, string] } = {}
|
||||||
|
|
||||||
|
// Используем условный require только на сервере для избежания включения fs в клиентскую сборку
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
// Серверная сторона
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
|
const groupsLoader = require('./groups-loader')
|
||||||
|
groups = groupsLoader.loadGroups()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading groups:', error)
|
||||||
|
groups = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { groups }
|
||||||
@@ -146,6 +146,7 @@ rsync -av --exclude='node_modules' \
|
|||||||
--exclude='.env.test' \
|
--exclude='.env.test' \
|
||||||
--exclude='.env.test.local' \
|
--exclude='.env.test.local' \
|
||||||
--exclude='*.md' \
|
--exclude='*.md' \
|
||||||
|
--exclude='db/' \
|
||||||
"$PROJECT_DIR/" "$INSTALL_DIR/"
|
"$PROJECT_DIR/" "$INSTALL_DIR/"
|
||||||
|
|
||||||
# Handle .env file
|
# Handle .env file
|
||||||
@@ -162,6 +163,16 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Создаем папку db для базы данных, если её нет
|
||||||
|
if [ ! -d "$INSTALL_DIR/db" ]; then
|
||||||
|
echo -e "${YELLOW}Creating db directory for database...${NC}"
|
||||||
|
mkdir -p "$INSTALL_DIR/db"
|
||||||
|
chmod 755 "$INSTALL_DIR/db"
|
||||||
|
echo -e "${GREEN}Database directory created at $INSTALL_DIR/db${NC}"
|
||||||
|
elif [ -d "$INSTALL_DIR/db" ]; then
|
||||||
|
echo -e "${GREEN}Database directory already exists, preserving existing database${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Install dependencies (with check)
|
# Install dependencies (with check)
|
||||||
echo -e "${YELLOW}Checking dependencies...${NC}"
|
echo -e "${YELLOW}Checking dependencies...${NC}"
|
||||||
cd "$INSTALL_DIR"
|
cd "$INSTALL_DIR"
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ case "$1" in
|
|||||||
--exclude='.env.test.local' \
|
--exclude='.env.test.local' \
|
||||||
--exclude='*.md' \
|
--exclude='*.md' \
|
||||||
--exclude='.dependencies.hash' \
|
--exclude='.dependencies.hash' \
|
||||||
|
--exclude='db/' \
|
||||||
"$PROJECT_DIR/" "$INSTALL_DIR/"
|
"$PROJECT_DIR/" "$INSTALL_DIR/"
|
||||||
|
|
||||||
# Handle .env file (preserve existing if present)
|
# Handle .env file (preserve existing if present)
|
||||||
@@ -113,6 +114,15 @@ case "$1" in
|
|||||||
cp "$PROJECT_DIR/.env" "$INSTALL_DIR/.env"
|
cp "$PROJECT_DIR/.env" "$INSTALL_DIR/.env"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Убеждаемся, что папка db существует и не перезаписывается
|
||||||
|
if [ ! -d "$INSTALL_DIR/db" ]; then
|
||||||
|
echo -e "${YELLOW}Creating db directory for database...${NC}"
|
||||||
|
mkdir -p "$INSTALL_DIR/db"
|
||||||
|
chmod 755 "$INSTALL_DIR/db"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}Database directory exists, preserving existing database${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Change to installation directory for build
|
# Change to installation directory for build
|
||||||
cd "$INSTALL_DIR"
|
cd "$INSTALL_DIR"
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,26 @@ const readline = require('readline');
|
|||||||
|
|
||||||
// Определяем путь к базе данных
|
// Определяем путь к базе данных
|
||||||
function findDatabase() {
|
function findDatabase() {
|
||||||
|
// Определяем корень проекта (для standalone режима поднимаемся на 2 уровня вверх)
|
||||||
|
let projectRoot = process.cwd();
|
||||||
|
if (projectRoot.includes('.next/standalone')) {
|
||||||
|
const match = projectRoot.match(/^(.+?)\/\.next\/standalone/);
|
||||||
|
if (match && match[1]) {
|
||||||
|
projectRoot = match[1];
|
||||||
|
} else {
|
||||||
|
projectRoot = path.resolve(projectRoot, '..', '..');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const possiblePaths = [
|
const possiblePaths = [
|
||||||
path.join(process.cwd(), 'data', 'schedule-app.db'),
|
path.join(projectRoot, 'db', 'schedule-app.db'),
|
||||||
path.join(process.cwd(), '.next', 'standalone', 'data', 'schedule-app.db'),
|
'/opt/kspguti-schedule/db/schedule-app.db',
|
||||||
|
path.join(process.cwd(), 'db', 'schedule-app.db'),
|
||||||
|
path.join(process.cwd(), '.next', 'standalone', 'db', 'schedule-app.db'),
|
||||||
|
'/opt/kspguti-schedule/.next/standalone/db/schedule-app.db',
|
||||||
|
// Старые пути для обратной совместимости
|
||||||
|
path.join(projectRoot, 'data', 'schedule-app.db'),
|
||||||
'/opt/kspguti-schedule/data/schedule-app.db',
|
'/opt/kspguti-schedule/data/schedule-app.db',
|
||||||
'/opt/kspguti-schedule/.next/standalone/data/schedule-app.db',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const dbPath of possiblePaths) {
|
for (const dbPath of possiblePaths) {
|
||||||
@@ -56,10 +71,22 @@ async function main() {
|
|||||||
if (!dbPath) {
|
if (!dbPath) {
|
||||||
console.error('❌ Ошибка: База данных не найдена!');
|
console.error('❌ Ошибка: База данных не найдена!');
|
||||||
console.log('\nИскали в следующих местах:');
|
console.log('\nИскали в следующих местах:');
|
||||||
console.log(' - ' + path.join(process.cwd(), 'data', 'schedule-app.db'));
|
|
||||||
console.log(' - ' + path.join(process.cwd(), '.next', 'standalone', 'data', 'schedule-app.db'));
|
// Определяем корень проекта для отображения
|
||||||
console.log(' - /opt/kspguti-schedule/data/schedule-app.db');
|
let projectRoot = process.cwd();
|
||||||
console.log(' - /opt/kspguti-schedule/.next/standalone/data/schedule-app.db');
|
if (projectRoot.includes('.next/standalone')) {
|
||||||
|
const match = projectRoot.match(/^(.+?)\/\.next\/standalone/);
|
||||||
|
if (match && match[1]) {
|
||||||
|
projectRoot = match[1];
|
||||||
|
} else {
|
||||||
|
projectRoot = path.resolve(projectRoot, '..', '..');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(' - ' + path.join(projectRoot, 'db', 'schedule-app.db'));
|
||||||
|
console.log(' - /opt/kspguti-schedule/db/schedule-app.db');
|
||||||
|
console.log(' - ' + path.join(process.cwd(), 'db', 'schedule-app.db'));
|
||||||
|
console.log('\n💡 Подсказка: База данных должна находиться в папке db/ в корне проекта');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,16 +5,85 @@ import bcrypt from 'bcrypt'
|
|||||||
import type { GroupInfo, GroupsData } from './groups-loader'
|
import type { GroupInfo, GroupsData } from './groups-loader'
|
||||||
import type { AppSettings } from './settings-loader'
|
import type { AppSettings } from './settings-loader'
|
||||||
|
|
||||||
// Путь к файлу базы данных
|
// Определяем корень проекта для хранения базы данных
|
||||||
const DB_PATH = path.join(process.cwd(), 'data', 'schedule-app.db')
|
function getDatabaseDir(): string {
|
||||||
|
// Если указан путь через переменную окружения, используем его
|
||||||
|
if (process.env.DATABASE_DIR) {
|
||||||
|
return process.env.DATABASE_DIR
|
||||||
|
}
|
||||||
|
|
||||||
|
// В production режиме (standalone) используем стандартный путь
|
||||||
|
const cwd = process.cwd()
|
||||||
|
|
||||||
|
// Если мы в .next/standalone, поднимаемся на 2 уровня вверх к корню проекта
|
||||||
|
if (cwd.includes('.next/standalone')) {
|
||||||
|
// В standalone режиме process.cwd() = /opt/kspguti-schedule/.next/standalone
|
||||||
|
// Нужно подняться до /opt/kspguti-schedule
|
||||||
|
const standaloneMatch = cwd.match(/^(.+?)\/\.next\/standalone/)
|
||||||
|
if (standaloneMatch && standaloneMatch[1]) {
|
||||||
|
return standaloneMatch[1]
|
||||||
|
}
|
||||||
|
// Альтернативный способ: подняться на 2 уровня вверх
|
||||||
|
return path.resolve(cwd, '..', '..')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем стандартный путь для production
|
||||||
|
if (fs.existsSync('/opt/kspguti-schedule')) {
|
||||||
|
return '/opt/kspguti-schedule'
|
||||||
|
}
|
||||||
|
|
||||||
|
// В development используем текущую директорию
|
||||||
|
return cwd
|
||||||
|
}
|
||||||
|
|
||||||
|
// Путь к директории базы данных
|
||||||
|
const DATABASE_DIR = getDatabaseDir()
|
||||||
|
const DB_PATH = path.join(DATABASE_DIR, 'db', 'schedule-app.db')
|
||||||
const DEFAULT_PASSWORD = 'ksadmin'
|
const DEFAULT_PASSWORD = 'ksadmin'
|
||||||
|
|
||||||
// Создаем директорию data, если её нет
|
// Путь к старой базе данных (для миграции)
|
||||||
|
const OLD_DB_PATH = path.join(DATABASE_DIR, 'data', 'schedule-app.db')
|
||||||
|
|
||||||
|
// Создаем директорию db, если её нет
|
||||||
const dbDir = path.dirname(DB_PATH)
|
const dbDir = path.dirname(DB_PATH)
|
||||||
if (!fs.existsSync(dbDir)) {
|
if (!fs.existsSync(dbDir)) {
|
||||||
fs.mkdirSync(dbDir, { recursive: true })
|
fs.mkdirSync(dbDir, { recursive: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Миграция базы данных из data/ в db/ (если старая база существует)
|
||||||
|
function migrateDatabaseLocation(): void {
|
||||||
|
// Если новая база уже существует, миграция не нужна
|
||||||
|
if (fs.existsSync(DB_PATH)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если старая база существует, перемещаем её
|
||||||
|
if (fs.existsSync(OLD_DB_PATH)) {
|
||||||
|
try {
|
||||||
|
console.log('Migrating database from data/ to db/...')
|
||||||
|
fs.renameSync(OLD_DB_PATH, DB_PATH)
|
||||||
|
|
||||||
|
// Также перемещаем вспомогательные файлы SQLite (WAL mode)
|
||||||
|
const oldShmPath = OLD_DB_PATH + '-shm'
|
||||||
|
const oldWalPath = OLD_DB_PATH + '-wal'
|
||||||
|
const newShmPath = DB_PATH + '-shm'
|
||||||
|
const newWalPath = DB_PATH + '-wal'
|
||||||
|
|
||||||
|
if (fs.existsSync(oldShmPath)) {
|
||||||
|
fs.renameSync(oldShmPath, newShmPath)
|
||||||
|
}
|
||||||
|
if (fs.existsSync(oldWalPath)) {
|
||||||
|
fs.renameSync(oldWalPath, newWalPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Database successfully migrated to db/ directory')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error migrating database:', error)
|
||||||
|
// Не падаем, просто продолжаем работу
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Инициализация базы данных
|
// Инициализация базы данных
|
||||||
let db: Database.Database | null = null
|
let db: Database.Database | null = null
|
||||||
|
|
||||||
@@ -23,6 +92,9 @@ function getDatabase(): Database.Database {
|
|||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Выполняем миграцию расположения базы данных перед открытием
|
||||||
|
migrateDatabaseLocation()
|
||||||
|
|
||||||
db = new Database(DB_PATH)
|
db = new Database(DB_PATH)
|
||||||
|
|
||||||
// Применяем современные настройки SQLite
|
// Применяем современные настройки SQLite
|
||||||
|
|||||||
Reference in New Issue
Block a user