Skip to content

Commit b494b6e

Browse files
committed
feat: customize local environment name #313
1 parent 4c74bc8 commit b494b6e

File tree

13 files changed

+77
-36
lines changed

13 files changed

+77
-36
lines changed

api/system/router.go

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ func InitPublicRouter(r *gin.RouterGroup) {
1111
}
1212

1313
func InitPrivateRouter(r *gin.RouterGroup) {
14+
r.GET("settings/server/name", GetServerName)
1415
r.GET("settings", GetSettings)
1516
r.POST("settings", SaveSettings)
1617

api/system/settings.go

+10-18
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ import (
66
"github.com/0xJacky/Nginx-UI/settings"
77
"github.com/gin-gonic/gin"
88
"net/http"
9-
"reflect"
109
)
1110

11+
func GetServerName(c *gin.Context) {
12+
c.JSON(http.StatusOK, gin.H{
13+
"name": settings.ServerSettings.Name,
14+
})
15+
}
16+
1217
func GetSettings(c *gin.Context) {
1318
c.JSON(http.StatusOK, gin.H{
1419
"server": settings.ServerSettings,
@@ -35,10 +40,10 @@ func SaveSettings(c *gin.Context) {
3540
go cron.RestartLogrotate()
3641
}
3742

38-
fillSettings(&settings.ServerSettings, &json.Server)
39-
fillSettings(&settings.NginxSettings, &json.Nginx)
40-
fillSettings(&settings.OpenAISettings, &json.Openai)
41-
fillSettings(&settings.LogrotateSettings, &json.Logrotate)
43+
settings.ProtectedFill(&settings.ServerSettings, &json.Server)
44+
settings.ProtectedFill(&settings.NginxSettings, &json.Nginx)
45+
settings.ProtectedFill(&settings.OpenAISettings, &json.Openai)
46+
settings.ProtectedFill(&settings.LogrotateSettings, &json.Logrotate)
4247

4348
err := settings.Save()
4449
if err != nil {
@@ -48,16 +53,3 @@ func SaveSettings(c *gin.Context) {
4853

4954
GetSettings(c)
5055
}
51-
52-
func fillSettings(targetSettings interface{}, newSettings interface{}) {
53-
s := reflect.TypeOf(targetSettings).Elem()
54-
vt := reflect.ValueOf(targetSettings).Elem()
55-
vn := reflect.ValueOf(newSettings).Elem()
56-
57-
// copy the values from new to target settings if it is not protected
58-
for i := 0; i < s.NumField(); i++ {
59-
if s.Field(i).Tag.Get("protected") != "true" {
60-
vt.Field(i).Set(vn.Field(i))
61-
}
62-
}
63-
}

app.example.ini

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ HttpHost = 0.0.0.0
1515
CertRenewalInterval = 7
1616
RecursiveNameservers =
1717
SkipInstallation = false
18+
Name =
1819

1920
[nginx]
2021
AccessLogPath = /var/log/nginx/access.log

app/src/api/settings.ts

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ const settings = {
88
save(data: any) {
99
return http.post('/settings', data)
1010
},
11+
12+
get_server_name() {
13+
return http.get('/settings/server/name')
14+
},
1115
}
1216

1317
export default settings

app/src/components/EnvIndicator/EnvIndicator.vue

+8-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { storeToRefs } from 'pinia'
44
import { useRouter } from 'vue-router'
55
import { computed, watch } from 'vue'
66
import { useSettingsStore } from '@/pinia'
7+
import settings from '@/api/settings'
78
89
const settingsStore = useSettingsStore()
910
@@ -25,6 +26,12 @@ watch(node_id, async () => {
2526
await router.push('/dashboard')
2627
location.reload()
2728
})
29+
30+
const { server_name } = storeToRefs(useSettingsStore())
31+
32+
settings.get_server_name().then(r => {
33+
server_name.value = r.name
34+
})
2835
</script>
2936

3037
<template>
@@ -35,7 +42,7 @@ watch(node_id, async () => {
3542
v-if="is_local"
3643
class="env-name"
3744
>
38-
{{ $gettext('Local') }}
45+
{{ server_name || $gettext('Local') }}
3946
</span>
4047
<span
4148
v-else

app/src/pinia/moudule/settings.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export const useSettingsStore = defineStore('settings', {
99
id: 0,
1010
name: 'Local',
1111
},
12+
server_name: '',
1213
}),
1314
getters: {
1415
is_remote(): boolean {

app/src/views/preference/BasicSettings.vue

+3
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ const errors: Record<string, Record<string, string>> = inject('errors') as Recor
113113
</template>
114114
</Draggable>
115115
</AFormItem>
116+
<AFormItem :label="$gettext('Server Name')">
117+
<AInput v-model:value="data.server.name" />
118+
</AFormItem>
116119
</AForm>
117120
</template>
118121

app/src/views/preference/OpenAISettings.vue

+9-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@ const models = shallowRef([
2323

2424
<template>
2525
<AForm layout="vertical">
26-
<AFormItem :label="$gettext('Model')">
26+
<AFormItem
27+
:label="$gettext('Model')"
28+
:validate-status="errors?.openai?.model ? 'error' : ''"
29+
:help="errors?.openai?.model === 'alpha_num_dash_dot'
30+
? $gettext('The model name should only contain letters, numbers, dashes, and dots.')
31+
: ''"
32+
>
2733
<AAutoComplete
2834
v-model:value="data.openai.model"
2935
:options="models"
@@ -33,7 +39,7 @@ const models = shallowRef([
3339
:label="$gettext('API Base Url')"
3440
:validate-status="errors?.openai?.base_url ? 'error' : ''"
3541
:help="errors?.openai?.base_url === 'url'
36-
? $gettext('The url is not valid')
42+
? $gettext('The url is invalid.')
3743
: ''"
3844
>
3945
<AInput
@@ -45,7 +51,7 @@ const models = shallowRef([
4551
:label="$gettext('API Proxy')"
4652
:validate-status="errors?.openai?.proxy ? 'error' : ''"
4753
:help="errors?.openai?.proxy === 'url'
48-
? $gettext('The url is not valid')
54+
? $gettext('The url is invalid.')
4955
: ''"
5056
>
5157
<AInput

app/src/views/preference/Preference.vue

+4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
<script setup lang="ts">
22
import { message } from 'ant-design-vue'
33
import type { Ref } from 'vue'
4+
import { storeToRefs } from 'pinia'
45
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
56
import settings from '@/api/settings'
67
import BasicSettings from '@/views/preference/BasicSettings.vue'
78
import OpenAISettings from '@/views/preference/OpenAISettings.vue'
89
import NginxSettings from '@/views/preference/NginxSettings.vue'
910
import type { Settings } from '@/views/preference/typedef'
1011
import LogrotateSettings from '@/views/preference/LogrotateSettings.vue'
12+
import { useSettingsStore } from '@/pinia'
1113
1214
const data = ref<Settings>({
1315
server: {
@@ -49,12 +51,14 @@ settings.get().then(r => {
4951
data.value = r
5052
})
5153
54+
const { server_name } = storeToRefs(useSettingsStore())
5255
const errors = ref({}) as Ref<Record<string, Record<string, string>>>
5356
5457
async function save() {
5558
// fix type
5659
data.value.server.http_challenge_port = data.value.server.http_challenge_port.toString()
5760
settings.save(data.value).then(r => {
61+
server_name.value = r?.server?.name ?? ''
5862
data.value = r
5963
message.success($gettext('Save successfully'))
6064
errors.value = {}

app/src/views/preference/typedef.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface Settings {
1212
ca_dir: string
1313
cert_renewal_interval: number
1414
recursive_nameservers: string[]
15+
name: string
1516
}
1617
nginx: {
1718
access_log_path: string

settings/server.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ type Server struct {
2020
GithubProxy string `json:"github_proxy" binding:"omitempty,url"`
2121
CertRenewalInterval int `json:"cert_renewal_interval" binding:"min=7,max=21"`
2222
RecursiveNameservers []string `json:"recursive_nameservers" binding:"omitempty,dive,hostname_port"`
23-
SkipInstallation bool `json:"skip_installation"`
23+
SkipInstallation bool `json:"skip_installation" protected:"true"`
24+
Name string `json:"name" binding:"omitempty,alpha_num_dash_dot"`
2425
}
2526

2627
func (s *Server) GetCADir() string {

settings/settings.go

+31-13
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import (
66
"gopkg.in/ini.v1"
77
"log"
88
"os"
9-
"strings"
9+
"reflect"
10+
"strings"
1011
"time"
1112
)
1213

@@ -69,19 +70,7 @@ func MapTo() {
6970
}
7071
}
7172

72-
func mapTo(section string, v interface{}) {
73-
err := Conf.Section(section).MapTo(v)
74-
if err != nil {
75-
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
76-
}
77-
}
7873

79-
func reflectFrom(section string, v interface{}) {
80-
err := Conf.Section(section).ReflectFrom(v)
81-
if err != nil {
82-
log.Fatalf("Cfg.ReflectFrom %s err: %v", section, err)
83-
}
84-
}
8574

8675
func Save() (err error) {
8776
for k, v := range sections {
@@ -95,6 +84,33 @@ func Save() (err error) {
9584
return
9685
}
9786

87+
func ProtectedFill(targetSettings interface{}, newSettings interface{}) {
88+
s := reflect.TypeOf(targetSettings).Elem()
89+
vt := reflect.ValueOf(targetSettings).Elem()
90+
vn := reflect.ValueOf(newSettings).Elem()
91+
92+
// copy the values from new to target settings if it is not protected
93+
for i := 0; i < s.NumField(); i++ {
94+
if s.Field(i).Tag.Get("protected") != "true" {
95+
vt.Field(i).Set(vn.Field(i))
96+
}
97+
}
98+
}
99+
100+
func mapTo(section string, v interface{}) {
101+
err := Conf.Section(section).MapTo(v)
102+
if err != nil {
103+
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
104+
}
105+
}
106+
107+
func reflectFrom(section string, v interface{}) {
108+
err := Conf.Section(section).ReflectFrom(v)
109+
if err != nil {
110+
log.Fatalf("Cfg.ReflectFrom %s err: %v", section, err)
111+
}
112+
}
113+
98114
func parseEnv(ptr interface{}, prefix string) {
99115
err := env.ParseWithOptions(ptr, env.Options{
100116
Prefix: EnvPrefix + prefix,
@@ -105,3 +121,5 @@ func parseEnv(ptr interface{}, prefix string) {
105121
log.Fatalf("settings.parseEnv: %v\n", err)
106122
}
107123
}
124+
125+

settings/settings_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func TestSetup(t *testing.T) {
2626
_ = os.Setenv("NGINX_UI_SERVER_CERT_RENEWAL_INTERVAL", "14")
2727
_ = os.Setenv("NGINX_UI_SERVER_RECURSIVE_NAMESERVERS", "8.8.8.8")
2828
_ = os.Setenv("NGINX_UI_SERVER_SKIP_INSTALLATION", "true")
29+
_ = os.Setenv("NGINX_UI_SERVER_NAME", "test")
2930

3031
_ = os.Setenv("NGINX_UI_NGINX_ACCESS_LOG_PATH", "/tmp/nginx/access.log")
3132
_ = os.Setenv("NGINX_UI_NGINX_ERROR_LOG_PATH", "/tmp/nginx/error.log")
@@ -70,6 +71,7 @@ func TestSetup(t *testing.T) {
7071
assert.Equal(t, 14, ServerSettings.CertRenewalInterval)
7172
assert.Equal(t, []string{"8.8.8.8"}, ServerSettings.RecursiveNameservers)
7273
assert.Equal(t, true, ServerSettings.SkipInstallation)
74+
assert.Equal(t, "test", ServerSettings.Name)
7375

7476
assert.Equal(t, "/tmp/nginx/access.log", NginxSettings.AccessLogPath)
7577
assert.Equal(t, "/tmp/nginx/error.log", NginxSettings.ErrorLogPath)

0 commit comments

Comments
 (0)