mirror of
https://github.com/gl-inet/glkvm-cloud.git
synced 2026-10-04 12:41:42 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e6da02f711 |
@@ -71,6 +71,9 @@ GLKVM_ACCESS_IP=
|
||||
# rttys
|
||||
RTTYS_TOKEN=DeviceTokenYouCanChangeMe
|
||||
RTTYS_PASS=StrongP@ssw0rd
|
||||
# Admin username (leave empty to default to "admin")
|
||||
# Only letters and digits are allowed (e.g. admin, Admin01). No spaces or special characters.
|
||||
RTTYS_ADMIN_NAME=
|
||||
RTTYS_DEVICE_PORT=5912
|
||||
RTTYS_WEBUI_PORT=443
|
||||
RTTYS_HTTP_PROXY_PORT=10443
|
||||
|
||||
@@ -70,6 +70,9 @@ GLKVM_ACCESS_IP=
|
||||
# rttys
|
||||
RTTYS_TOKEN=DeviceTokenYouCanChangeMe
|
||||
RTTYS_PASS=StrongP@ssw0rd
|
||||
# Admin username (leave empty to default to "admin")
|
||||
# Only letters and digits are allowed (e.g. admin, Admin01). No spaces or special characters.
|
||||
RTTYS_ADMIN_NAME=
|
||||
RTTYS_DEVICE_PORT=5912
|
||||
RTTYS_WEBUI_PORT=443
|
||||
RTTYS_HTTP_PROXY_PORT=10443
|
||||
|
||||
@@ -12,6 +12,7 @@ services:
|
||||
# ---- rttys ----
|
||||
RTTYS_TOKEN: ${RTTYS_TOKEN:-DeviceTokenYouCanChangeMe}
|
||||
RTTYS_PASS: ${RTTYS_PASS:-StrongP@ssw0rd}
|
||||
RTTYS_ADMIN_NAME: ${RTTYS_ADMIN_NAME:-}
|
||||
|
||||
# Ports inside container (mirrored to host via `ports` below)
|
||||
RTTYS_DEVICE_PORT: ${RTTYS_DEVICE_PORT:-5912} # addr-dev
|
||||
|
||||
@@ -60,7 +60,7 @@ case "$1" in
|
||||
: "${TURN_PORT:=3478}"
|
||||
|
||||
render /tpl/rttys.conf.tmpl /home/rttys.conf \
|
||||
RTTYS_TOKEN RTTYS_PASS \
|
||||
RTTYS_TOKEN RTTYS_PASS RTTYS_ADMIN_NAME \
|
||||
GLKVM_ACCESS_IP TURN_PORT TURN_USER TURN_PASS \
|
||||
RTTYS_DEVICE_PORT RTTYS_WEBUI_PORT RTTYS_HTTP_PROXY_PORT \
|
||||
LDAP_ENABLED LDAP_SERVER LDAP_PORT LDAP_USE_TLS \
|
||||
|
||||
@@ -4,6 +4,9 @@ token: {{RTTYS_TOKEN}}
|
||||
# Web management password
|
||||
password: {{RTTYS_PASS}}
|
||||
|
||||
# Admin username (leave empty to default to "admin")
|
||||
admin-name: {{RTTYS_ADMIN_NAME}}
|
||||
|
||||
# WebRTC
|
||||
webrtc-ip: {{GLKVM_ACCESS_IP}}
|
||||
webrtc-port: {{TURN_PORT}}
|
||||
|
||||
+16
-4
@@ -80,7 +80,7 @@ func InitAppContainer(r *gin.Engine) (*AppContainer, error) {
|
||||
if err := sqlite.InitSchema(ctx, appDB.SQL(), "/home/database/schema.sql"); err != nil {
|
||||
log.Fatal().Err(err).Msg("init schema failed")
|
||||
}
|
||||
if err := ensureAdminUser(ctx, appDB.Gorm(), cfg.Password); err != nil {
|
||||
if err := ensureAdminUser(ctx, appDB.Gorm(), cfg.AdminName, cfg.Password); err != nil {
|
||||
log.Fatal().Err(err).Msg("ensure admin user failed")
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ func InitAppContainer(r *gin.Engine) (*AppContainer, error) {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func ensureAdminUser(ctx context.Context, db *gorm.DB, plainPassword string) error {
|
||||
func ensureAdminUser(ctx context.Context, db *gorm.DB, adminName, plainPassword string) error {
|
||||
if db == nil {
|
||||
return fmt.Errorf("db is nil")
|
||||
}
|
||||
@@ -126,15 +126,27 @@ func ensureAdminUser(ctx context.Context, db *gorm.DB, plainPassword string) err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// First, rename the existing system admin user to the configured name (if changed).
|
||||
// This handles the case where the admin username was previously "admin" (or another name)
|
||||
// and the user now wants a different username via RTTYS_ADMIN_NAME.
|
||||
if err := db.WithContext(ctx).Exec(
|
||||
`UPDATE users SET username = ? WHERE is_system = 1 AND role = 'admin' AND username != ?`,
|
||||
adminName, adminName,
|
||||
).Error; err != nil {
|
||||
return fmt.Errorf("rename system admin user: %w", err)
|
||||
}
|
||||
|
||||
// Upsert: create the admin user if not exists, or update password/role/status.
|
||||
return db.WithContext(ctx).Exec(
|
||||
`INSERT INTO users (username, description, password_hash, role, status, is_system)
|
||||
VALUES ('admin', 'Admin', ?, 'admin', 'active', 1)
|
||||
VALUES (?, 'Admin', ?, 'admin', 'active', 1)
|
||||
ON CONFLICT(username) DO UPDATE SET
|
||||
password_hash=excluded.password_hash,
|
||||
role='admin',
|
||||
status='active',
|
||||
is_system=1`,
|
||||
hash,
|
||||
adminName, hash,
|
||||
).Error
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ package xconfig
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -45,6 +46,7 @@ type Config struct {
|
||||
UserHookUrl string
|
||||
LocalAuth bool
|
||||
Password string
|
||||
AdminName string
|
||||
AllowOrigins bool
|
||||
PprofAddr string
|
||||
AuthSessionTTL time.Duration
|
||||
@@ -168,6 +170,7 @@ func parseYamlCfg(cfg *Config, conf string) error {
|
||||
getConfigOpt(yamlCfg, "user-hook-url", &cfg.UserHookUrl)
|
||||
getConfigOpt(yamlCfg, "local-auth", &cfg.LocalAuth)
|
||||
getConfigOpt(yamlCfg, "password", &cfg.Password)
|
||||
getConfigOpt(yamlCfg, "admin-name", &cfg.AdminName)
|
||||
getConfigOpt(yamlCfg, "allow-origins", &cfg.AllowOrigins)
|
||||
|
||||
if err := getDurationOpt(yamlCfg, "auth-session-ttl", &cfg.AuthSessionTTL); err != nil {
|
||||
@@ -237,6 +240,16 @@ func parseYamlCfg(cfg *Config, conf string) error {
|
||||
}
|
||||
|
||||
func applyEnvCfg(cfg *Config) error {
|
||||
if v := strings.TrimSpace(os.Getenv("RTTYS_ADMIN_NAME")); v != "" {
|
||||
cfg.AdminName = v
|
||||
}
|
||||
if cfg.AdminName == "" {
|
||||
cfg.AdminName = "admin"
|
||||
}
|
||||
if !regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString(cfg.AdminName) {
|
||||
return fmt.Errorf("invalid RTTYS_ADMIN_NAME %q: only letters and digits are allowed", cfg.AdminName)
|
||||
}
|
||||
|
||||
if v := strings.TrimSpace(os.Getenv("RTTYS_LOG")); v != "" {
|
||||
cfg.LogPath = v
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user