Кабинет: веб-установщик и управление пользователями в ядре
- установщик в самом кабинете: до настройки любая страница ведёт в /install; три шага — проверка сервера (каталог данных, https), связь с ядром (режим, адрес, ключ; связь проверяется до сохранения, в режиме ожидания страница ждёт подключения ядра), администратор кабинета (заводится в ядре через /api/lk/admin/bootstrap, только пока администраторов нет); настройки в data/lk.json 0600, окружение перекрывает файл; после установки установщик закрыт - настройки кабинета можно менять на ходу: Server за мьютексом, один mux на всё время - ключ модуля больше не кладётся в архив: его вводят в установщике; на странице настроек ключ показан целиком 10 минут после создания, потом маска - ядро: карточка «Пользователи кабинета» в настройках — список, заведение, смена пароля (гасит сессии), блокировка, права сотрудника, разрешение поручений, удаление; письма не отправляются - инструкция /admin/help/lk дополнена шагами установщика и разделом о подходящем хостинге - тесты: TestInstaller, TestNotConfigured, TestSetupPageLKUsersAndLink; установщик проверен вживую вторым экземпляром против боевого ядра Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,18 @@ func lkNewAPIKey() (string, error) {
|
||||
return "lk-" + hex.EncodeToString(b), nil
|
||||
}
|
||||
|
||||
// lkKeyRevealUntil — до какого момента ключ на странице настроек показывается целиком:
|
||||
// сразу после создания администратору нужно переписать его в установщик кабинета.
|
||||
var lkKeyRevealUntil time.Time
|
||||
|
||||
// lkKeyForPage — ключ для страницы настроек: целиком сразу после создания, потом маска.
|
||||
func lkKeyForPage(key string) string {
|
||||
if key != "" && time.Now().Before(lkKeyRevealUntil) {
|
||||
return key
|
||||
}
|
||||
return maskSecret(key)
|
||||
}
|
||||
|
||||
// maskSecret — показать ключ так, чтобы его нельзя было списать со скриншота,
|
||||
// но можно было сверить с тем, что стоит у кабинета.
|
||||
func maskSecret(v string) string {
|
||||
@@ -84,18 +96,26 @@ func lkDistFiles(s Settings, coreURL string) ([]struct {
|
||||
// ядро подключается к кабинету само по имени этого сервера.
|
||||
mode, urlLine = "agent", "# BJ_URL не нужен: ядро подключается к кабинету само"
|
||||
}
|
||||
env := fmt.Sprintf(`# Настройки кабинета клиента (bj-lk). Файл читает служба, права 0600.
|
||||
// Ключ в архив НЕ кладём: его вводят в веб-установщике кабинета. Так архив можно
|
||||
// хранить и пересылать, а секрет живёт только в двух местах — в ядре и в файле
|
||||
// настроек кабинета с правами 0600.
|
||||
env := fmt.Sprintf(`# Настройки кабинета клиента (bj-lk) для установки службой. Файл читает служба, права 0600.
|
||||
# Проще — ничего здесь не менять: после запуска откройте адрес кабинета в браузере,
|
||||
# запустится установщик и сам спросит способ связи и ключ.
|
||||
# Режим связи с ядром: direct — кабинет обращается к ядру; agent — ядро подключается сюда.
|
||||
BJ_MODE=%s
|
||||
# Адрес ядра bj, к которому обращается кабинет (только для режима direct):
|
||||
%s
|
||||
# Ключ доступа модуля — тот же, что в настройках ядра, раздел «Личный кабинет».
|
||||
BJ_KEY=%s
|
||||
# Ключ доступа модуля — из настроек ядра, раздел «Личный кабинет». Оставьте пустым,
|
||||
# чтобы ввести его в установщике; заполните — если ставите без браузера.
|
||||
BJ_KEY=
|
||||
# Адрес и порт, на которых кабинет слушает (за ним обычно стоит nginx с TLS):
|
||||
LISTEN=127.0.0.1:8099
|
||||
# Заголовок кабинета:
|
||||
LK_TITLE=%s
|
||||
`, mode, urlLine, s.LK.APIKey, title)
|
||||
# Каталог данных (файл настроек установщика):
|
||||
LK_DATA=/var/lib/bj-lk
|
||||
`, mode, urlLine, title)
|
||||
|
||||
unit := `[Unit]
|
||||
Description=Личный кабинет клиента депозитария (bj-lk)
|
||||
@@ -116,7 +136,7 @@ NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
PrivateTmp=true
|
||||
ReadWritePaths=/var/log/bj-lk
|
||||
ReadWritePaths=/var/log/bj-lk /var/lib/bj-lk
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -129,6 +149,7 @@ DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
id bjlk >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin bjlk
|
||||
install -d -m 755 /opt/bj-lk
|
||||
install -d -m 750 -o bjlk -g bjlk /var/log/bj-lk
|
||||
install -d -m 700 -o bjlk -g bjlk /var/lib/bj-lk
|
||||
install -d -m 750 /etc/bj-lk
|
||||
install -m 755 "$DIR/bj-lk" /opt/bj-lk/bj-lk
|
||||
if [ -f /etc/bj-lk/lk.env ]; then
|
||||
@@ -142,7 +163,8 @@ systemctl enable --now bj-lk
|
||||
sleep 2
|
||||
systemctl --no-pager --full status bj-lk | head -n 12
|
||||
echo
|
||||
echo "Проверка: curl -s http://127.0.0.1:8099/health"
|
||||
echo "Дальше откройте адрес кабинета в браузере — запустится установщик."
|
||||
echo "Проверка службы: curl -s http://127.0.0.1:8099/health"
|
||||
`
|
||||
|
||||
readme := fmt.Sprintf(`Личный кабинет клиента депозитария (bj-lk)
|
||||
@@ -160,10 +182,19 @@ echo "Проверка: curl -s http://127.0.0.1:8099/health"
|
||||
install.sh — установка одной командой
|
||||
README.txt — этот файл
|
||||
|
||||
Установка:
|
||||
Установка — как у обычного веб-приложения:
|
||||
1. Распакуйте архив на сервере кабинета.
|
||||
2. sudo ./install.sh
|
||||
3. Проверьте: curl -s http://127.0.0.1:8099/health — должно вернуться "ok":true.
|
||||
2. sudo ./install.sh — заводит службу; либо просто запустите ./bj-lk в своём
|
||||
каталоге, если хостинг позволяет держать программу запущенной.
|
||||
3. Откройте адрес кабинета в браузере. Запустится установщик: проверит сервер,
|
||||
спросит способ связи с ядром и ключ доступа, проверит связь и предложит
|
||||
завести администратора кабинета. Настройки он сохранит в файл lk.json
|
||||
(каталог LK_DATA, права 0600). Ключа в этом архиве нет — берите его из
|
||||
настроек ядра, раздел «Личный кабинет».
|
||||
4. Проверка службы: curl -s http://127.0.0.1:8099/health — "ok":true.
|
||||
|
||||
Установка без браузера: заполните BJ_KEY (и BJ_URL для режима direct) в lk.env и
|
||||
перезапустите службу — окружение перекрывает файл установщика.
|
||||
|
||||
Настройки (файл /etc/bj-lk/lk.env):
|
||||
BJ_URL — адрес ядра bj: %s
|
||||
@@ -200,14 +231,13 @@ echo "Проверка: curl -s http://127.0.0.1:8099/health"
|
||||
• наружу открыт только 443 сервера кабинета;
|
||||
• в режиме direct кабинет обращается к ядру на %s — разрешите этот доступ
|
||||
в межсетевом экране; в режиме agent входящий доступ к ядру не нужен вовсе;
|
||||
• ключ доступа хранится только в /etc/bj-lk/lk.env (права 0600, владелец root);
|
||||
• ключ можно сменить в настройках ядра, после чего заменить его в lk.env и
|
||||
перезапустить службу;
|
||||
• ключ доступа хранится только в файле настроек кабинета (lk.json или lk.env,
|
||||
права 0600); в этом архиве его нет;
|
||||
• ключ можно сменить в настройках ядра, после чего удалить lk.json и пройти
|
||||
установщик заново (или вписать новый ключ в lk.env) и перезапустить службу;
|
||||
• кабинет не хранит данные клиентов: ни базы, ни файлов — всё берётся у ядра
|
||||
на время запроса. Шрифты и оформление вшиты в программу, сторонние сайты
|
||||
страница не запрашивает;
|
||||
• ВАЖНО: в этом архиве лежит боевой ключ доступа. После установки удалите
|
||||
архив с рабочего компьютера и не пересылайте его почтой или в мессенджере.
|
||||
|
||||
Обновления. Кабинет обновляется отдельно от ядра: новую версию скачивайте на
|
||||
странице настроек ядра, раздел «Личный кабинет», и ставьте тем же install.sh —
|
||||
@@ -290,7 +320,8 @@ func (h *setupHandlers) lkSaveDist(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
s.APIKey = key
|
||||
msg = "Создан новый ключ доступа кабинета. Скачайте дистрибутив заново или впишите ключ в /etc/bj-lk/lk.env и перезапустите службу кабинета."
|
||||
lkKeyRevealUntil = time.Now().Add(10 * time.Minute) // показать целиком один раз, чтобы переписать в установщик
|
||||
msg = "Создан новый ключ доступа кабинета. Он показан целиком ниже в течение 10 минут — введите его в установщике кабинета (или в lk.env) и перезапустите службу кабинета, если она уже работала."
|
||||
case "clearkey":
|
||||
s.APIKey = ""
|
||||
msg = "Ключ удалён: кабинет больше не сможет обращаться к ядру."
|
||||
|
||||
Reference in New Issue
Block a user