Compare commits

..

5 Commits

10 changed files with 177 additions and 32 deletions

3
.gitignore vendored
View File

@ -40,6 +40,9 @@ Desktop.ini
# Project Specific - Server
server/.env
server/.env.backup*
server/*.tmp
server/backups/
server/uploads/*
!server/uploads/.gitkeep
server/server.zip

View File

@ -0,0 +1,23 @@
# ==============================================
# [Common Settings]
# ==============================================
DB_HOST=sokuree.com
DB_USER=choibk
DB_PASSWORD=^Ocean1472bk
PORT=3005
# ==============================================
# [Development Environment] - Local Windows
# ==============================================
# 로컬 개발용 DB (분리됨: sokuree_platform_dev)
DB_NAME=sokuree_platform_dev
DB_PORT=3307
# Windows 환경 호환성 (tcp는 권한 오류 발생 가능)
CCTV_TRANSPORT_OVERRIDE=auto
# ==============================================
# [Production Environment] - Synology NAS
# ==============================================
# DB_NAME=sokuree_platform_prod
# DB_PORT=3307

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "smartims",
"version": "0.4.0.0",
"version": "0.4.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "smartims",
"version": "0.4.0.0",
"version": "0.4.0.1",
"dependencies": {
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",

View File

@ -1,7 +1,7 @@
{
"name": "smartims",
"private": true,
"version": "0.4.0.1",
"version": "0.4.2.7",
"type": "module",
"scripts": {
"dev": "vite",

View File

@ -446,7 +446,15 @@ const initTables = async () => {
await db.query(insert, ['cctv', 'CCTV', false, null]);
} else {
// One-time update: Rename 'monitoring' code to 'cctv' (migration)
await db.query("UPDATE system_modules SET code = 'cctv' WHERE code = 'monitoring'");
// Use subquery or check if cctv exists to avoid ER_DUP_ENTRY
const [cctvExists] = await db.query("SELECT 1 FROM system_modules WHERE code = 'cctv'");
if (cctvExists.length > 0) {
// If cctv already exists, just remove monitoring if it's there
await db.query("DELETE FROM system_modules WHERE code = 'monitoring'");
} else {
// If cctv doesn't exist, try renaming monitoring
await db.query("UPDATE system_modules SET code = 'cctv' WHERE code = 'monitoring'");
}
}
console.log('✅ Tables Initialized');
@ -459,13 +467,25 @@ initTables();
const packageJson = require('./package.json');
app.get('/api/health', (req, res) => {
// Light-weight health check
// Dynamic version check (Light-weight)
const kstOffset = 9 * 60 * 60 * 1000;
const kstDate = new Date(Date.now() + kstOffset);
let version = packageJson.version;
try {
const { execSync } = require('child_process');
// Check git tag in parent directory (Project root)
version = execSync('git describe --tags --abbrev=0', {
cwd: path.join(__dirname, '..'),
stdio: ['ignore', 'pipe', 'ignore']
}).toString().trim().replace(/^v/, '');
} catch (e) {
// Safe fallback to package.json
}
res.json({
status: 'ok',
version: packageJson.version,
version: version,
node_version: process.version,
platform: process.platform,
arch: process.arch,

View File

@ -1,12 +1,12 @@
{
"name": "server",
"version": "0.4.0.0",
"version": "0.4.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "server",
"version": "0.4.0.0",
"version": "0.4.0.1",
"license": "ISC",
"dependencies": {
"axios": "^1.13.2",

View File

@ -1,6 +1,6 @@
{
"name": "server",
"version": "0.4.0.1",
"version": "0.4.2.7",
"description": "",
"main": "index.js",
"scripts": {

View File

@ -489,13 +489,22 @@ const getGiteaAuth = async () => {
// 5. Get Version Info (Current, Remote & History from Tags)
router.get('/version/remote', isAuthenticated, hasRole('admin'), async (req, res) => {
try {
// Local version detection (No caching)
// Local version detection (Dynamic & Robust)
const projectRoot = path.join(__dirname, '../..');
let currentVersion = '0.0.0.0';
try {
const rootPkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf8'));
currentVersion = rootPkg.version;
const { execSync } = require('child_process');
currentVersion = execSync('git describe --tags --abbrev=0', {
cwd: projectRoot,
stdio: ['ignore', 'pipe', 'ignore']
}).toString().trim().replace(/^v/, '');
} catch (e) {
currentVersion = '0.4.2.1';
try {
const rootPkg = JSON.parse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8'));
currentVersion = rootPkg.version;
} catch (err) {
currentVersion = '0.4.2.7';
}
}
// Prepare git fetch command
@ -509,7 +518,7 @@ router.get('/version/remote', isAuthenticated, hasRole('admin'), async (req, res
fetchCmd = `git fetch ${auth.url} --tags --force --prune`;
}
exec(fetchCmd, (err, stdout, stderr) => {
exec(fetchCmd, { cwd: projectRoot }, (err, stdout, stderr) => {
if (err) {
console.error('Git fetch failed:', err);
const sanitizedError = stderr.replace(/:[^@]+@/g, ':****@');
@ -526,7 +535,7 @@ router.get('/version/remote', isAuthenticated, hasRole('admin'), async (req, res
const format = '%(refname:short)|%(contents:subject)|%(contents:body)|%(creatordate:iso8601)';
const historyCmd = `git for-each-ref refs/tags --sort=-creatordate --format="${format}" --count=50`;
exec(historyCmd, (err, stdout, stderr) => {
exec(historyCmd, { cwd: projectRoot }, (err, stdout, stderr) => {
const lines = stdout ? stdout.trim().split('\n') : [];
const allTags = lines.map(line => {
const [tag, subject, body, date] = line.split('|');
@ -613,7 +622,7 @@ router.post('/version/update', isAuthenticated, hasRole('admin'), async (req, re
// Build auth URL for git commands
let remoteUrl = auth.url;
if (auth.user && auth.pass) {
if (auth.user && auth.pass && auth.url.includes('https://')) {
remoteUrl = auth.url.replace('https://', `https://${encodeURIComponent(auth.user)}:${encodeURIComponent(auth.pass)}@`);
}
@ -632,18 +641,33 @@ router.post('/version/update', isAuthenticated, hasRole('admin'), async (req, re
scriptContent = `
@echo off
echo [Update] Starting update to ${targetTag}...
if not exist "${backupDir}" mkdir "${backupDir}"
echo [Update] Backing up Uploads & Config...
tar -czvf "${backupDir}/backup_images_${timestamp}.tar.gz" server/uploads/
if exist "server\\.env" copy "server\\.env" "${backupDir}\\env_backup_${timestamp}"
REM Ensure backup directory
set BACKUP_PATH=${backupDir}
if not exist "%BACKUP_PATH%" mkdir "%BACKUP_PATH%" 2>nul
if not exist "%BACKUP_PATH%" (
echo [Warning] Global backup failed, using local backup.
set BACKUP_PATH=.\\server\\backups
if not exist ".\\server\\backups" mkdir ".\\server\\backups"
)
echo [Update] Backing up Config...
if exist "server\\.env" (
copy /Y "server\\.env" "%BACKUP_PATH%\\.env.backup.${timestamp}"
copy /Y "server\\.env" "server\\.env.tmp"
)
echo [Update] Syncing Source Code...
git fetch "${remoteUrl}" +refs/tags/*:refs/tags/* --force --prune --prune-tags
git fetch "${remoteUrl}" --tags --force --prune
git checkout -f ${targetTag}
echo [Update] Restoring Config...
if exist "${backupDir}\\env_backup_${timestamp}" copy /Y "${backupDir}\\env_backup_${timestamp}" "server\\.env"
if exist "server\\.env.tmp" (
copy /Y "server\\.env.tmp" "server\\.env"
del "server\\.env.tmp"
) else if exist "%BACKUP_PATH%\\.env.backup.${timestamp}" (
copy /Y "%BACKUP_PATH%\\.env.backup.${timestamp}" "server\\.env"
)
echo [Update] Installing & Building...
call npm install
@ -651,8 +675,7 @@ call npm run build
cd server
call npm install
echo [Update] Restarting Server...
echo "Please restart your dev server manually if needed."
echo [Update] Done.
`;
} else {
// Linux/Synology Script
@ -660,22 +683,59 @@ echo "Please restart your dev server manually if needed."
scriptContent = `#!/bin/bash
exec > >(tee -a update.log) 2>&1
echo "[Update] Starting update to ${targetTag}..."
mkdir -p ${backupDir}
# Ensure backup directory
BACKUP_DIR="${backupDir}"
mkdir -p "$BACKUP_DIR" || {
echo "[Warning] Global backup failed, using local backup."
BACKUP_DIR="./server/backups"
mkdir -p "$BACKUP_DIR"
}
echo "[Update] Backing up Database..."
${dumpTool} -u ${dbUser} --password='${dbPass}' --port ${dbPort} ${dbName} > ${backupDir}/backup_db_${timestamp}.sql || echo "DB Backup Failed, continuing..."
if [ -f "${dumpTool}" ]; then
echo "[Info] MySQL dump tool found. Attempting database backup..."
${dumpTool} -u ${dbUser} --password='${dbPass}' --port ${dbPort} ${dbName} > "$BACKUP_DIR/backup_db_${timestamp}.sql" 2>/dev/null
if [ $? -eq 0 ]; then
echo "[Info] Database backup successful."
else
echo "[Warning] Database backup failed, continuing..."
fi
else
echo "[Warning] MySQL dump tool not found. Skipping DB backup."
fi
echo "[Update] Backing up Uploads & Config..."
tar -czvf ${backupDir}/backup_images_${timestamp}.tar.gz server/uploads/
cp server/.env ${backupDir}/.env.backup.${timestamp}
echo "[Update] Backing up Config..."
if [ -f "server/.env" ]; then
echo "[Info] Backing up 'server/.env' to '$BACKUP_DIR/.env.backup.${timestamp}' and 'server/.env.tmp'."
cp "server/.env" "$BACKUP_DIR/.env.backup.${timestamp}"
cp "server/.env" "server/.env.tmp"
else
echo "[Warning] 'server/.env' not found. Skipping config backup."
fi
echo "[Update] Syncing Source Code..."
git remote set-url origin "${remoteUrl}"
git fetch origin +refs/tags/*:refs/tags/* --force --prune --prune-tags
git fetch origin --tags --force --prune
if [ $? -ne 0 ]; then
echo "[Error] Git fetch failed. Exiting update."
exit 1
fi
echo "[Info] Git fetch successful."
git checkout -f ${targetTag}
if [ $? -ne 0 ]; then
echo "[Error] Git checkout to ${targetTag} failed. Exiting update."
exit 1
fi
echo "[Info] Git checkout to ${targetTag} successful."
echo "[Update] Restoring Config..."
cp ${backupDir}/.env.backup.${timestamp} server/.env
if [ -f "server/.env.tmp" ]; then
cp "server/.env.tmp" "server/.env"
rm "server/.env.tmp"
elif [ -f "$BACKUP_DIR/.env.backup.${timestamp}" ]; then
cp "$BACKUP_DIR/.env.backup.${timestamp}" "server/.env"
fi
echo "[Update] Installing & Building..."
npm install

View File

@ -333,7 +333,7 @@ export function BasicSettingsPage() {
{/* Section 2.5: Gitea Repository Update Settings */}
<Card className="overflow-hidden border-slate-200 shadow-sm">
<div className="p-6 border-b border-slate-50 bg-slate-50/50">
<div className="p-6 border-b border-slate-50 bg-slate-50/50 flex justify-between items-center">
<h2 className="text-lg font-bold text-slate-800 flex items-center gap-2">
<RefreshCcw size={20} className="text-emerald-600" />
(Gitea)

39
update_system.bat Normal file
View File

@ -0,0 +1,39 @@
@echo off
echo [Update] Starting update to v0.4.2.6...
REM Ensure backup directory
set BACKUP_PATH=./backup
if not exist "%BACKUP_PATH%" mkdir "%BACKUP_PATH%" 2>nul
if not exist "%BACKUP_PATH%" (
echo [Warning] Global backup failed, using local backup.
set BACKUP_PATH=.\server\backups
if not exist ".\server\backups" mkdir ".\server\backups"
)
echo [Update] Backing up Config...
if exist "server\.env" (
copy /Y "server\.env" "%BACKUP_PATH%\.env.backup.2026-01-26-00-58-22"
copy /Y "server\.env" "server\.env.tmp"
)
echo [Update] Syncing Source Code...
git fetch "https://gitea.qideun.com/SOKUREE/smart_ims.git" --tags --force --prune
git checkout -f v0.4.2.6
echo [Update] Restoring Config...
if exist "server\.env.tmp" (
copy /Y "server\.env.tmp" "server\.env"
del "server\.env.tmp"
) else if exist "%BACKUP_PATH%\.env.backup.2026-01-26-00-58-22" (
copy /Y "%BACKUP_PATH%\.env.backup.2026-01-26-00-58-22" "server\.env"
)
echo [Update] Installing & Building...
call npm install
call npm run build
cd server
call npm install
echo [Update] Done.