diff --git a/backend/app/api/v1/entry.go b/backend/app/api/v1/entry.go index 70c2a30b8..31ace100e 100644 --- a/backend/app/api/v1/entry.go +++ b/backend/app/api/v1/entry.go @@ -15,4 +15,5 @@ var ( commandService = service.ServiceGroupApp.CommandService operationService = service.ServiceGroupApp.OperationService fileService = service.ServiceGroupApp.FileService + settingService = service.ServiceGroupApp.SettingService ) diff --git a/backend/app/api/v1/setting.go b/backend/app/api/v1/setting.go new file mode 100644 index 000000000..e862a7a05 --- /dev/null +++ b/backend/app/api/v1/setting.go @@ -0,0 +1,36 @@ +package v1 + +import ( + "github.com/1Panel-dev/1Panel/app/api/v1/helper" + "github.com/1Panel-dev/1Panel/app/dto" + "github.com/1Panel-dev/1Panel/constant" + "github.com/1Panel-dev/1Panel/global" + "github.com/gin-gonic/gin" +) + +func (b *BaseApi) GetSettingInfo(c *gin.Context) { + setting, err := settingService.GetSettingInfo() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, setting) +} + +func (b *BaseApi) UpdateInfo(c *gin.Context) { + var req dto.SettingUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + + if err := settingService.Update(req.Key, req.Value); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} diff --git a/backend/app/dto/setting.go b/backend/app/dto/setting.go new file mode 100644 index 000000000..d00361ad9 --- /dev/null +++ b/backend/app/dto/setting.go @@ -0,0 +1,31 @@ +package dto + +type SettingInfo struct { + UserName string `json:"userName"` + Password string `json:"password"` + Email string `json:"email"` + + SessionTimeout string `json:"sessionTimeout"` + + PanelName string `json:"panelName"` + Theme string `json:"theme"` + Language string `json:"language"` + + ServerPort string `json:"serverPort"` + SecurityEntrance string `json:"securityEntrance"` + ComplexityVerification string `json:"complexityVerification"` + MFAStatus string `json:"mfaStatus"` + + MonitorStatus string `json:"monitorStatus"` + MonitorStoreDays string `json:"monitorStoreDays"` + + MessageType string `json:"messageType"` + EmailVars string `json:"emailVars"` + WeChatVars string `json:"weChatVars"` + DingVars string `json:"dingVars"` +} + +type SettingUpdate struct { + Key string `json:"key" validate:"required"` + Value string `json:"value"` +} diff --git a/backend/app/model/setting.go b/backend/app/model/setting.go new file mode 100644 index 000000000..f49d0692c --- /dev/null +++ b/backend/app/model/setting.go @@ -0,0 +1,10 @@ +package model + +import "gorm.io/gorm" + +type Setting struct { + gorm.Model + Key string `json:"key" gorm:"type:varchar(256);not null;"` + Value string `json:"value" gorm:"type:varchar(256)"` + About string `json:"about" gorm:"type:longText"` +} diff --git a/backend/app/repo/entry.go b/backend/app/repo/entry.go index 084ed7ae8..5bc9060de 100644 --- a/backend/app/repo/entry.go +++ b/backend/app/repo/entry.go @@ -7,6 +7,7 @@ type RepoGroup struct { CommandRepo OperationRepo CommonRepo + SettingRepo } var RepoGroupApp = new(RepoGroup) diff --git a/backend/app/repo/setting.go b/backend/app/repo/setting.go new file mode 100644 index 000000000..27ba6aa36 --- /dev/null +++ b/backend/app/repo/setting.go @@ -0,0 +1,31 @@ +package repo + +import ( + "github.com/1Panel-dev/1Panel/app/model" + "github.com/1Panel-dev/1Panel/global" +) + +type SettingRepo struct{} + +type ISettingRepo interface { + Get(opts ...DBOption) ([]model.Setting, error) + Update(key, value string) error +} + +func NewISettingService() ISettingRepo { + return &SettingRepo{} +} + +func (u *SettingRepo) Get(opts ...DBOption) ([]model.Setting, error) { + var settings []model.Setting + db := global.DB.Model(&model.Setting{}) + for _, opt := range opts { + db = opt(db) + } + err := db.Find(&settings).Error + return settings, err +} + +func (u *SettingRepo) Update(key, value string) error { + return global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error +} diff --git a/backend/app/service/entry.go b/backend/app/service/entry.go index 742388ac0..fbf3c36c3 100644 --- a/backend/app/service/entry.go +++ b/backend/app/service/entry.go @@ -9,6 +9,7 @@ type ServiceGroup struct { CommandService OperationService FileService + SettingService } var ServiceGroupApp = new(ServiceGroup) @@ -20,4 +21,5 @@ var ( commandRepo = repo.RepoGroupApp.CommandRepo operationRepo = repo.RepoGroupApp.OperationRepo commonRepo = repo.RepoGroupApp.CommonRepo + settingRepo = repo.RepoGroupApp.SettingRepo ) diff --git a/backend/app/service/setting.go b/backend/app/service/setting.go new file mode 100644 index 000000000..877bbfbef --- /dev/null +++ b/backend/app/service/setting.go @@ -0,0 +1,43 @@ +package service + +import ( + "encoding/json" + + "github.com/1Panel-dev/1Panel/app/dto" + "github.com/1Panel-dev/1Panel/constant" +) + +type SettingService struct{} + +type ISettingService interface { + GetSettingInfo() (*dto.SettingInfo, error) + Update(key, value string) error +} + +func NewISettingService() ISettingService { + return &SettingService{} +} + +func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) { + setting, err := settingRepo.Get() + if err != nil { + return nil, constant.ErrRecordNotFound + } + settingMap := make(map[string]string) + for _, set := range setting { + settingMap[set.Key] = set.Value + } + var info dto.SettingInfo + arr, err := json.Marshal(settingMap) + if err != nil { + return nil, err + } + if err := json.Unmarshal(arr, &info); err != nil { + return nil, err + } + return &info, err +} + +func (u *SettingService) Update(key, value string) error { + return settingRepo.Update(key, value) +} diff --git a/backend/init/migration/migrate.go b/backend/init/migration/migrate.go index b6d4f7f72..4030df53c 100644 --- a/backend/init/migration/migrate.go +++ b/backend/init/migration/migrate.go @@ -13,7 +13,8 @@ func Init() { migrations.AddData, migrations.AddTableOperationLog, migrations.AddTableHost, - migrations.AddTablemonitor, + migrations.AddTableMonitor, + migrations.AddTableSetting, }) if err := m.Migrate(); err != nil { global.LOG.Error(err) diff --git a/backend/init/migration/migrations/init.go b/backend/init/migration/migrations/init.go index be571dde6..99271fd3a 100644 --- a/backend/init/migration/migrations/init.go +++ b/backend/init/migration/migrations/init.go @@ -54,9 +54,75 @@ var AddTableHost = &gormigrate.Migration{ }, } -var AddTablemonitor = &gormigrate.Migration{ +var AddTableMonitor = &gormigrate.Migration{ ID: "20200905-add-table-monitor", Migrate: func(tx *gorm.DB) error { return tx.AutoMigrate(&model.MonitorBase{}, &model.MonitorIO{}, &model.MonitorNetwork{}) }, } + +var AddTableSetting = &gormigrate.Migration{ + ID: "20200908-add-table-setting", + Migrate: func(tx *gorm.DB) error { + if err := tx.AutoMigrate(&model.Setting{}); err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "UserName", Value: "admin"}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "Password", Value: "5WYEZ4XcitdomVvAyimt9WwJwBJJSbTTHncZoqyOraQ="}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "Email", Value: ""}).Error; err != nil { + return err + } + + if err := tx.Create(&model.Setting{Key: "PanelName", Value: "1Panel"}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "Language", Value: "ch"}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "Theme", Value: "auto"}).Error; err != nil { + return err + } + + if err := tx.Create(&model.Setting{Key: "SessionTimeout", Value: "86400"}).Error; err != nil { + return err + } + + if err := tx.Create(&model.Setting{Key: "ServerPort", Value: "4004"}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "SecurityEntrance", Value: "/89dc6ae8"}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "ComplexityVerification", Value: "enable"}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "MFAStatus", Value: "disable"}).Error; err != nil { + return err + } + + if err := tx.Create(&model.Setting{Key: "MonitorStatus", Value: "enable"}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "MonitorStoreDays", Value: "30"}).Error; err != nil { + return err + } + + if err := tx.Create(&model.Setting{Key: "MessageType", Value: "none"}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "EmailVars", Value: ""}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "WeChatVars", Value: ""}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "DingVars", Value: ""}).Error; err != nil { + return err + } + return nil + }, +} diff --git a/backend/init/router/router.go b/backend/init/router/router.go index b3b2f88a2..5b5f22d58 100644 --- a/backend/init/router/router.go +++ b/backend/init/router/router.go @@ -46,6 +46,7 @@ func Routers() *gin.Engine { systemRouter.InitMonitorRouter(PrivateGroup) systemRouter.InitOperationLogRouter(PrivateGroup) systemRouter.InitFileRouter(PrivateGroup) + systemRouter.InitSettingRouter(PrivateGroup) } return Router diff --git a/backend/router/entry.go b/backend/router/entry.go index 0fd569033..0751e6866 100644 --- a/backend/router/entry.go +++ b/backend/router/entry.go @@ -9,6 +9,7 @@ type RouterGroup struct { MonitorRouter OperationLogRouter FileRouter + SettingRouter } var RouterGroupApp = new(RouterGroup) diff --git a/backend/router/ro_setting.go b/backend/router/ro_setting.go new file mode 100644 index 000000000..4ce0363a0 --- /dev/null +++ b/backend/router/ro_setting.go @@ -0,0 +1,17 @@ +package router + +import ( + v1 "github.com/1Panel-dev/1Panel/app/api/v1" + "github.com/1Panel-dev/1Panel/middleware" + "github.com/gin-gonic/gin" +) + +type SettingRouter struct{} + +func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) { + monitorRouter := Router.Group("settings").Use(middleware.JwtAuth()).Use(middleware.SessionAuth()) + baseApi := v1.ApiGroupApp.BaseApi + { + monitorRouter.POST("/search", baseApi.GetSettingInfo) + } +} diff --git a/frontend/src/api/interface/setting.ts b/frontend/src/api/interface/setting.ts new file mode 100644 index 000000000..21b26ef75 --- /dev/null +++ b/frontend/src/api/interface/setting.ts @@ -0,0 +1,26 @@ +export namespace Setting { + export interface SettingInfo { + userName: string; + password: string; + email: string; + + sessionTimeout: string; + + panelName: string; + theme: string; + language: string; + + serverPort: string; + securityEntrance: string; + complexityVerification: string; + mfaStatus: string; + + monitorStatus: string; + monitorStoreDays: string; + + messageType: string; + emailVars: string; + weChatVars: string; + dingVars: string; + } +} diff --git a/frontend/src/api/modules/setting.ts b/frontend/src/api/modules/setting.ts new file mode 100644 index 000000000..842f20ad5 --- /dev/null +++ b/frontend/src/api/modules/setting.ts @@ -0,0 +1,6 @@ +import http from '@/api'; +import { Setting } from '../interface/setting'; + +export const getSettingInfo = () => { + return http.post(`/settings/search`); +}; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 3cd847b34..8dbb41f7c 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -100,6 +100,7 @@ export default { monitor: 'Monitor', operations: 'Operation Records', files: 'File Management', + settings: 'Setting', }, home: { welcome: 'Welcome', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 8b0769ed7..be6b85a50 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -100,6 +100,7 @@ export default { monitor: '监控', operations: '操作记录', files: '文件管理', + settings: '系统设置', }, home: { welcome: '欢迎使用', diff --git a/frontend/src/routers/modules/setting.ts b/frontend/src/routers/modules/setting.ts new file mode 100644 index 000000000..9840bb773 --- /dev/null +++ b/frontend/src/routers/modules/setting.ts @@ -0,0 +1,25 @@ +import { Layout } from '@/routers/constant'; + +const settingRouter = { + sort: 3, + path: '/settings', + component: Layout, + redirect: '/setting', + meta: { + title: 'menu.settings', + icon: 'Setting', + }, + children: [ + { + path: '/setting', + name: 'Setting', + component: () => import('@/views/setting/index.vue'), + meta: { + requiresAuth: true, + key: 'Setting', + }, + }, + ], +}; + +export default settingRouter; diff --git a/frontend/src/views/setting/index.vue b/frontend/src/views/setting/index.vue new file mode 100644 index 000000000..d2fde4124 --- /dev/null +++ b/frontend/src/views/setting/index.vue @@ -0,0 +1,150 @@ + + + + +