Настройка запуска на Ubuntu + tmux и доступ извне (Арсен.)

- Добавлены инструкции `docs/UBUNTU_SETUP.md` и секции в README.
- Добавлены скрипты `scripts/setup-postgres-ubuntu.sh` и `scripts/start-tmux.sh` (tmux: front/back).
- Для доступа снаружи: Vite `allowedHosts: true`, бэкенд слушает `0.0.0.0`.
- Добавлен сид демо-пользователя портала `demo` / `demo123` с ролью DIRECTOR (как `its`).
- `.env` файлы добавлены в `.gitignore`, чтобы не коммитить секреты.

Выполнил: Арсен.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-10 11:55:20 +05:00
parent de94ad707b
commit 4993816a95
10 changed files with 305 additions and 9 deletions

View File

@@ -12,6 +12,13 @@ const DEFAULT_ADMIN_LOGIN = 'its';
const DEFAULT_ADMIN_PASSWORD = 'iiEasy348ax@';
const DEFAULT_ADMIN_ROLE = 'DIRECTOR';
// Демо-пользователь с теми же правами, что и its (DIRECTOR)
const DEMO_EMPLOYEE_ID = 'e-demo';
const DEMO_EMPLOYEE_NAME = 'Demo';
const DEMO_LOGIN = 'demo';
const DEMO_PASSWORD = 'demo123';
const DEMO_ROLE = 'DIRECTOR';
/**
* Инициализация базы данных PostgreSQL
* Создает БД при первом запуске и проверяет целостность при последующих запусках
@@ -220,6 +227,9 @@ async function initializeDatabase() {
// Администратор портала по умолчанию (логин its) — создаётся, если ещё нет
await applyDefaultAdminSeed(client);
// Демо-пользователь (demo / demo123) с правами DIRECTOR — создаётся при каждом старте, если ещё нет
await applyDemoUserSeed(client);
return {
success: true,
initialized: !integrityCheck.isInitialized,
@@ -2572,6 +2582,55 @@ async function applyDefaultAdminSeed(client) {
}
}
/**
* Демо-пользователь портала (логин demo, пароль demo123) с правами DIRECTOR, как у its.
*/
async function applyDemoUserSeed(client) {
try {
const existingUser = await client.query(
'SELECT id FROM portal_users WHERE login = $1',
[DEMO_LOGIN]
);
if (existingUser.rows.length > 0) {
return;
}
const employeeExists = await client.query(
'SELECT id FROM employees WHERE id = $1',
[DEMO_EMPLOYEE_ID]
);
if (employeeExists.rows.length === 0) {
await client.query(
`INSERT INTO employees (id, name, position, phone, status, salary, assigned_district_id)
VALUES ($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (id) DO NOTHING`,
[
DEMO_EMPLOYEE_ID,
DEMO_EMPLOYEE_NAME,
'Демо-пользователь',
'+70000000001',
'active',
0,
null,
]
);
console.log('[dbInit] Создан сотрудник для демо:', DEMO_EMPLOYEE_NAME);
}
const passwordHash = await bcrypt.hash(DEMO_PASSWORD, 10);
await client.query(
`INSERT INTO portal_users (employee_id, login, role, password_hash, is_active)
VALUES ($1, $2, $3, $4, true)
ON CONFLICT (login) DO NOTHING`,
[DEMO_EMPLOYEE_ID, DEMO_LOGIN, DEMO_ROLE, passwordHash]
);
const check = await client.query('SELECT id FROM portal_users WHERE login = $1', [DEMO_LOGIN]);
if (check.rows.length > 0) {
console.log('[dbInit] Создан демо-пользователь портала: логин', DEMO_LOGIN, ', роль', DEMO_ROLE);
}
} catch (error) {
console.warn('[dbInit] Ошибка при создании демо-пользователя:', error.message);
}
}
/**
* Таблица настроек интеграций (DaData и др.)
*/