Skip to content

Commit 9b06974

Browse files
committed
feat: multi user template
1 parent 8755b65 commit 9b06974

File tree

7 files changed

+62
-14
lines changed

7 files changed

+62
-14
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
| 用户前台 [@hamster1963](https://github.com/hamster1963) | 管理后台 [@uubulb](https://github.com/uubulb) |
2828
|---|---|
2929
| ![user](.github/user-frontend.20241128.png) | ![admin](.github/admin-frontend.20241128.png) |
30-
| [hamster1963/nezha-dash-react](https://github.com/hamster1963/nezha-dash-react) | [nezhahq/admin-frontend](https://github.com/nezhahq/admin-frontend) |
30+
| [hamster1963/nezha-dash](https://github.com/hamster1963/nezha-dash) | [nezhahq/admin-frontend](https://github.com/nezhahq/admin-frontend) |
3131

3232
## Supported Languages
3333

cmd/dashboard/controller/controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,11 @@ func fallbackToFrontend(adminFrontend, userFrontend fs.FS) func(*gin.Context) {
249249
}
250250
return
251251
}
252-
localFilePath := path.Join("user-dist", c.Request.URL.Path)
252+
localFilePath := path.Join(singleton.Conf.UserTemplate, c.Request.URL.Path)
253253
if checkLocalFileOrFs(c, userFrontend, localFilePath) {
254254
return
255255
}
256-
if !checkLocalFileOrFs(c, userFrontend, "user-dist/index.html") {
256+
if !checkLocalFileOrFs(c, userFrontend, singleton.Conf.UserTemplate+"/index.html") {
257257
c.JSON(http.StatusOK, newErrorResponse(errors.New("404 Not Found")))
258258
}
259259
}

cmd/dashboard/controller/setting.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package controller
22

33
import (
4+
"errors"
5+
46
"github.com/gin-gonic/gin"
57

68
"github.com/nezhahq/nezha/model"
@@ -21,8 +23,9 @@ func listConfig(c *gin.Context) (model.SettingResponse, error) {
2123
authorized := isMember // TODO || isViewPasswordVerfied
2224

2325
conf := model.SettingResponse{
24-
Config: *singleton.Conf,
25-
Version: singleton.Version,
26+
Config: *singleton.Conf,
27+
Version: singleton.Version,
28+
UserTemplates: singleton.UserTemplates,
2629
}
2730

2831
if !authorized {
@@ -55,7 +58,16 @@ func updateConfig(c *gin.Context) (any, error) {
5558
if err := c.ShouldBindJSON(&sf); err != nil {
5659
return nil, err
5760
}
58-
61+
var userTemplateValid bool
62+
for _, v := range singleton.UserTemplates {
63+
if v.Path == sf.UserTemplate {
64+
userTemplateValid = true
65+
break
66+
}
67+
}
68+
if !userTemplateValid {
69+
return nil, errors.New("invalid user template")
70+
}
5971
singleton.Conf.Language = sf.Language
6072
singleton.Conf.EnableIPChangeNotification = sf.EnableIPChangeNotification
6173
singleton.Conf.EnablePlainIPInNotification = sf.EnablePlainIPInNotification
@@ -69,6 +81,7 @@ func updateConfig(c *gin.Context) (any, error) {
6981
singleton.Conf.CustomCodeDashboard = sf.CustomCodeDashboard
7082
singleton.Conf.RealIPHeader = sf.RealIPHeader
7183
singleton.Conf.TLS = sf.TLS
84+
singleton.Conf.UserTemplate = sf.UserTemplate
7285

7386
if err := singleton.Conf.Save(); err != nil {
7487
return nil, newGormError("%v", err)

cmd/dashboard/controller/user.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func updateProfile(c *gin.Context) (any, error) {
8282
// @Router /user [get]
8383
func listUser(c *gin.Context) ([]model.User, error) {
8484
var users []model.User
85-
if err := singleton.DB.Find(&users).Error; err != nil {
85+
if err := singleton.DB.Omit("password").Find(&users).Error; err != nil {
8686
return nil, err
8787
}
8888
return users, nil

model/config.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type Config struct {
2727

2828
Language string `mapstructure:"language" json:"language"` // 系统语言,默认 zh_CN
2929
SiteName string `mapstructure:"site_name" json:"site_name"`
30+
UserTemplate string `mapstructure:"user_template" json:"user_template,omitempty"`
3031
JWTSecretKey string `mapstructure:"jwt_secret_key" json:"jwt_secret_key,omitempty"`
3132
AgentSecretKey string `mapstructure:"agent_secret_key" json:"agent_secret_key,omitempty"`
3233
ListenPort uint `mapstructure:"listen_port" json:"listen_port,omitempty"`
@@ -55,7 +56,7 @@ type Config struct {
5556
}
5657

5758
// Read 读取配置文件并应用
58-
func (c *Config) Read(path string) error {
59+
func (c *Config) Read(path string, userTemplates []UserTemplate) error {
5960
c.k = koanf.New(".")
6061
c.filePath = path
6162

@@ -87,6 +88,16 @@ func (c *Config) Read(path string) error {
8788
if c.Location == "" {
8889
c.Location = "Asia/Shanghai"
8990
}
91+
var userTemplateValid bool
92+
for _, v := range userTemplates {
93+
if v.Path == c.UserTemplate {
94+
userTemplateValid = true
95+
break
96+
}
97+
}
98+
if c.UserTemplate == "" || !userTemplateValid {
99+
c.UserTemplate = "user-dist"
100+
}
90101
if c.AvgPingCount == 0 {
91102
c.AvgPingCount = 2
92103
}

model/setting_api.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,24 @@ type SettingForm struct {
1111
CustomCode string `json:"custom_code,omitempty" validate:"optional"`
1212
CustomCodeDashboard string `json:"custom_code_dashboard,omitempty" validate:"optional"`
1313
RealIPHeader string `json:"real_ip_header,omitempty" validate:"optional"` // 真实IP
14+
UserTemplate string `json:"user_template,omitempty" validate:"optional"`
1415

1516
TLS bool `json:"tls,omitempty" validate:"optional"`
1617
EnableIPChangeNotification bool `json:"enable_ip_change_notification,omitempty" validate:"optional"`
1718
EnablePlainIPInNotification bool `json:"enable_plain_ip_in_notification,omitempty" validate:"optional"`
1819
}
1920

21+
type UserTemplate struct {
22+
Path string `json:"path,omitempty"`
23+
Name string `json:"name,omitempty"`
24+
GitHub string `json:"github,omitempty"`
25+
Author string `json:"author,omitempty"`
26+
Community bool `json:"community,omitempty"`
27+
}
28+
2029
type SettingResponse struct {
2130
Config
2231

23-
Version string `json:"version,omitempty"`
32+
Version string `json:"version,omitempty"`
33+
UserTemplates []UserTemplate `json:"user_templates,omitempty"`
2434
}

service/singleton/singleton.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,24 @@ import (
1515
var Version = "debug"
1616

1717
var (
18-
Conf *model.Config
19-
Cache *cache.Cache
20-
DB *gorm.DB
21-
Loc *time.Location
18+
Conf *model.Config
19+
Cache *cache.Cache
20+
DB *gorm.DB
21+
Loc *time.Location
22+
UserTemplates = []model.UserTemplate{
23+
{
24+
Path: "user-dist",
25+
Name: "Official",
26+
GitHub: "https://github.com/hamster1963/nezha-dash",
27+
Author: "hamster1963",
28+
}, {
29+
Path: "nazhua-dist",
30+
Name: "Nazhua",
31+
GitHub: "https://github.com/hi2shark/nazhua",
32+
Author: "hi2hi",
33+
Community: true,
34+
},
35+
}
2236
)
2337

2438
func InitTimezoneAndCache() {
@@ -44,7 +58,7 @@ func LoadSingleton() {
4458
// InitConfigFromPath 从给出的文件路径中加载配置
4559
func InitConfigFromPath(path string) {
4660
Conf = &model.Config{}
47-
err := Conf.Read(path)
61+
err := Conf.Read(path, UserTemplates)
4862
if err != nil {
4963
panic(err)
5064
}

0 commit comments

Comments
 (0)