2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 03:07:20 +08:00

Merge remote-tracking branch 'origin/main'

This commit is contained in:
2025-06-17 09:06:23 +08:00
17 changed files with 909 additions and 902 deletions

View File

@@ -33,7 +33,7 @@ jobs:
run: |
~/go/bin/xgotext -default backend -pkg-tree ./cmd/web -out ./pkg/embed/locales
cd web && pnpm run gettext:extract
- uses: stefanzweifel/git-auto-commit-action@v5
- uses: stefanzweifel/git-auto-commit-action@v6
name: Commit changes
with:
commit_message: "chore(l10n): update pot files"

View File

@@ -21,7 +21,7 @@ jobs:
run: |
~/go/bin/mockery
git pull
- uses: stefanzweifel/git-auto-commit-action@v5
- uses: stefanzweifel/git-auto-commit-action@v6
name: Commit changes
with:
commit_message: "chore: update mocks"

18
go.mod
View File

@@ -15,7 +15,7 @@ require (
github.com/go-rat/sessions v1.1.0
github.com/go-rat/utils v1.1.5
github.com/go-resty/resty/v2 v2.16.5
github.com/go-sql-driver/mysql v1.9.2
github.com/go-sql-driver/mysql v1.9.3
github.com/golang-cz/httplog v0.0.2
github.com/gomodule/redigo v1.9.2
github.com/google/wire v0.6.0
@@ -25,7 +25,7 @@ require (
github.com/hashicorp/go-version v1.7.0
github.com/knadh/koanf/parsers/yaml v1.0.0
github.com/knadh/koanf/providers/file v1.2.0
github.com/knadh/koanf/v2 v2.2.0
github.com/knadh/koanf/v2 v2.2.1
github.com/leonelquinteros/gotext v1.7.2
github.com/lib/pq v1.10.9
github.com/libdns/alidns v1.0.4
@@ -45,20 +45,20 @@ require (
github.com/libdns/tencentcloud v1.2.0
github.com/libdns/vercel v0.0.2
github.com/mholt/acmez/v3 v3.1.2
github.com/ncruces/go-sqlite3 v0.26.0
github.com/ncruces/go-sqlite3 v0.26.1
github.com/ncruces/go-sqlite3/gormlite v0.24.0
github.com/orandin/slog-gorm v1.4.0
github.com/pquerna/otp v1.5.0
github.com/robfig/cron/v3 v3.0.1
github.com/samber/lo v1.50.0
github.com/samber/lo v1.51.0
github.com/sethvargo/go-limiter v1.0.1-0.20250412144437-fa26982c7e1a
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/spf13/cast v1.9.2
github.com/stretchr/testify v1.10.0
github.com/tufanbarisyildirim/gonginx v0.0.0-20250429180229-7e931b1d4276
github.com/urfave/cli/v3 v3.3.3
golang.org/x/crypto v0.38.0
golang.org/x/net v0.40.0
github.com/urfave/cli/v3 v3.3.8
golang.org/x/crypto v0.39.0
golang.org/x/net v0.41.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
gorm.io/gorm v1.30.0
@@ -100,9 +100,9 @@ require (
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
golang.org/x/sync v0.14.0 // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect
golang.org/x/text v0.26.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)

42
go.sum
View File

@@ -85,8 +85,8 @@ github.com/go-rat/utils v1.1.5 h1:nB5qNU4TxqG9BJe7PdeDzznmh6lk+GIWb7hZcvAY4FQ=
github.com/go-rat/utils v1.1.5/go.mod h1:SUy4Xw44VkZvo2FaURgiIiJlL6Kukll85fVKMp/50+8=
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
@@ -187,8 +187,8 @@ github.com/knadh/koanf/parsers/yaml v1.0.0 h1:PXyeHCRhAMKyfLJaoTWsqUTxIFeDMmdAKz
github.com/knadh/koanf/parsers/yaml v1.0.0/go.mod h1:Q63VAOh/s6XaQs6a0TB2w9GFUuuPGvfYrCSWb9eWAQU=
github.com/knadh/koanf/providers/file v1.2.0 h1:hrUJ6Y9YOA49aNu/RSYzOTFlqzXSCpmYIDXI7OJU6+U=
github.com/knadh/koanf/providers/file v1.2.0/go.mod h1:bp1PM5f83Q+TOUu10J/0ApLBd9uIzg+n9UgthfY+nRA=
github.com/knadh/koanf/v2 v2.2.0 h1:FZFwd9bUjpb8DyCWARUBy5ovuhDs1lI87dOEn2K8UVU=
github.com/knadh/koanf/v2 v2.2.0/go.mod h1:PSFru3ufQgTsI7IF+95rf9s8XA1+aHxKuO/W+dPoHEY=
github.com/knadh/koanf/v2 v2.2.1 h1:jaleChtw85y3UdBnI0wCqcg1sj1gPoz6D3caGNHtrNE=
github.com/knadh/koanf/v2 v2.2.1/go.mod h1:PSFru3ufQgTsI7IF+95rf9s8XA1+aHxKuO/W+dPoHEY=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -261,14 +261,12 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/ncruces/go-sqlite3 v0.26.0 h1:dY6ASfuhSEbtSge6kJwjyJVC7bXCpgEVOycmdboKJek=
github.com/ncruces/go-sqlite3 v0.26.0/go.mod h1:46HIzeCQQ+aNleAxCli+vpA2tfh7ttSnw24kQahBc1o=
github.com/ncruces/go-sqlite3 v0.26.1 h1:lBXmbmucH1Bsj57NUQR6T84UoMN7jnNImhF+ibEITJU=
github.com/ncruces/go-sqlite3 v0.26.1/go.mod h1:XFTPtFIo1DmGCh+XVP8KGn9b/o2f+z0WZuT09x2N6eo=
github.com/ncruces/go-sqlite3/gormlite v0.24.0 h1:81sHeq3CCdhjoqAB650n5wEdRlLO9VBvosArskcN3+c=
github.com/ncruces/go-sqlite3/gormlite v0.24.0/go.mod h1:vXfVWdBfg7qOgqQqHpzUWl9LLswD0h+8mK4oouaV2oc=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/orandin/slog-gorm v1.4.0 h1:FgA8hJufF9/jeNSYoEXmHPPBwET2gwlF3B85JdpsTUU=
github.com/orandin/slog-gorm v1.4.0/go.mod h1:MoZ51+b7xE9lwGNPYEhxcUtRNrYzjdcKvA8QXQQGEPA=
@@ -301,8 +299,8 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samber/lo v1.50.0 h1:XrG0xOeHs+4FQ8gJR97zDz5uOFMW7OwFWiFVzqopKgY=
github.com/samber/lo v1.50.0/go.mod h1:RjZyNk6WSnUFRKK6EyOhsRJMqft3G+pg7dCWHQCWvsc=
github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI=
github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sethvargo/go-limiter v1.0.1-0.20250412144437-fa26982c7e1a h1:CdCoDHVynJVAQWN7ZQrAUOp0SV5TmRwNOSkF5KedDko=
github.com/sethvargo/go-limiter v1.0.1-0.20250412144437-fa26982c7e1a/go.mod h1:01b6tW25Ap+MeLYBuD4aHunMrJoNO5PVUFdS9rac3II=
@@ -352,8 +350,8 @@ github.com/tnb-labs/acmez/v3 v3.0.0-20250416074048-0e9f6b5f8ec5 h1:eeJt90c4buPPC
github.com/tnb-labs/acmez/v3 v3.0.0-20250416074048-0e9f6b5f8ec5/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
github.com/tufanbarisyildirim/gonginx v0.0.0-20250429180229-7e931b1d4276 h1:928VpvLiMWSulfjhKUYj57f70HhOE1ImsQHaeDC2jVc=
github.com/tufanbarisyildirim/gonginx v0.0.0-20250429180229-7e931b1d4276/go.mod h1:ALbEe81QPWOZjDKCKNWodG2iqCMtregG8+ebQgjx2+4=
github.com/urfave/cli/v3 v3.3.3 h1:byCBaVdIXuLPIDm5CYZRVG6NvT7tv1ECqdU4YzlEa3I=
github.com/urfave/cli/v3 v3.3.3/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E=
github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
@@ -376,8 +374,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -424,8 +422,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -438,8 +436,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -483,8 +481,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
@@ -539,8 +537,8 @@ google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=

View File

@@ -65,6 +65,7 @@ func MustLogin(t *gotext.Locale, session *sessions.Manager, userToken biz.UserTo
ip, _, _ := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr))
clientHash := fmt.Sprintf("%x", sha256.Sum256([]byte(ip)))
if safeClientHash != clientHash || safeClientHash == "" {
sess.Forget("user_id") // 清除 user_id否则会来回跳转
Abort(w, http.StatusUnauthorized, t.Get("client ip/ua changed, please login again"))
return
}

View File

@@ -3,7 +3,6 @@ package service
import (
"net/http"
"slices"
"strings"
"github.com/go-rat/chix"
@@ -179,15 +178,11 @@ func (s *FirewallService) CreateIPRule(w http.ResponseWriter, r *http.Request) {
return
}
// rich ruleaddress 不支持多个地址,需要单独添加
addresses := strings.Split(req.Address, ",")
for address := range slices.Values(addresses) {
if err = s.firewall.RichRules(firewall.FireInfo{
Family: req.Family, Address: address, Protocol: firewall.Protocol(req.Protocol), Strategy: firewall.Strategy(req.Strategy), Direction: firewall.Direction(req.Direction),
}, firewall.OperationAdd); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
if err = s.firewall.RichRules(firewall.FireInfo{
Family: req.Family, Address: req.Address, Protocol: firewall.Protocol(req.Protocol), Strategy: firewall.Strategy(req.Strategy), Direction: firewall.Direction(req.Direction),
}, firewall.OperationAdd); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
Success(w, nil)

View File

@@ -1332,7 +1332,7 @@ msgstr ""
msgid "check server connection failed"
msgstr ""
#: internal/http/middleware/must_login.go:68
#: internal/http/middleware/must_login.go:69
msgid "client ip/ua changed, please login again"
msgstr ""
@@ -1727,7 +1727,7 @@ msgstr ""
msgid "invalid 2FA code"
msgstr ""
#: internal/http/middleware/entrance.go:108
#: internal/http/middleware/entrance.go:107
msgid "invalid access entrance"
msgstr ""
@@ -1758,7 +1758,7 @@ msgstr ""
msgid "invalid signature"
msgstr ""
#: internal/http/middleware/must_login.go:77
#: internal/http/middleware/must_login.go:78
msgid "invalid user id, please login again"
msgstr ""

View File

@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-File-ID: 922\n"
"Project-Id-Version: ratpanel\n"
"Language-Team: Chinese Simplified\n"
"PO-Revision-Date: 2025-05-31 12:39\n"
"PO-Revision-Date: 2025-06-08 07:34\n"
#: internal/data/website.go:270
#: internal/data/website.go:643
@@ -1735,7 +1735,7 @@ msgstr "获取服务端口失败,请检查是否安装"
msgid "invalid 2FA code"
msgstr "无效的两步验证代码"
#: internal/http/middleware/entrance.go:108
#: internal/http/middleware/entrance.go:107
msgid "invalid access entrance"
msgstr "无效的访问入口"

View File

@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-File-ID: 922\n"
"Project-Id-Version: ratpanel\n"
"Language-Team: Chinese Traditional\n"
"PO-Revision-Date: 2025-05-31 12:39\n"
"PO-Revision-Date: 2025-06-08 07:34\n"
#: internal/data/website.go:270
#: internal/data/website.go:643
@@ -1735,7 +1735,7 @@ msgstr "獲取服務端口失敗,請檢查是否安裝"
msgid "invalid 2FA code"
msgstr "無效的兩步驗證代碼"
#: internal/http/middleware/entrance.go:108
#: internal/http/middleware/entrance.go:107
msgid "invalid access entrance"
msgstr "無效的訪問入口"

View File

@@ -207,6 +207,11 @@ func (r *Firewall) Port(rule FireInfo, operation Operation) error {
}
func (r *Firewall) RichRules(rule FireInfo, operation Operation) error {
// 出站规则下,必须指定具体的地址,否则会添加成入站规则
if rule.Direction == "out" && rule.Address == "" {
return fmt.Errorf("outbound rules must specify an address")
}
protocols := strings.Split(string(rule.Protocol), "/")
for protocol := range slices.Values(protocols) {
var ruleBuilder strings.Builder

View File

@@ -34,6 +34,7 @@
"github.com/libdns/cloudflare",
"github.com/libdns/tencentcloud",
"github.com/libdns/duckdns",
"github.com/libdns/gcore"
"github.com/libdns/gcore",
"github.com/libdns/cloudns"
]
}

1274
web/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -149,7 +149,6 @@ msgstr ""
#: src/views/database/CreateUserModal.vue:28
#: src/views/file/ToolBar.vue:45
#: src/views/firewall/CreateForwardModal.vue:41
#: src/views/firewall/CreateModal.vue:84
#: src/views/setting/CreateModal.vue:19
#: src/views/setting/TokenModal.vue:127
#: src/views/ssh/CreateModal.vue:38
@@ -214,8 +213,8 @@ msgstr ""
#: src/views/file/ToolBar.vue:261
#: src/views/file/ToolBar.vue:282
#: src/views/firewall/CreateForwardModal.vue:88
#: src/views/firewall/CreateIpModal.vue:122
#: src/views/firewall/CreateModal.vue:147
#: src/views/firewall/CreateIpModal.vue:118
#: src/views/firewall/CreateModal.vue:142
#: src/views/setting/CreateModal.vue:64
#: src/views/setting/PasswordModal.vue:44
#: src/views/setting/TwoFaModal.vue:87
@@ -3423,7 +3422,7 @@ msgstr ""
#: src/views/firewall/CreateForwardModal.vue:58
#: src/views/firewall/CreateIpModal.vue:97
#: src/views/firewall/CreateModal.vue:101
#: src/views/firewall/CreateModal.vue:99
#: src/views/firewall/ForwardView.vue:15
#: src/views/firewall/IpRuleView.vue:15
#: src/views/firewall/RuleView.vue:15
@@ -3480,18 +3479,19 @@ msgid "Outbound"
msgstr ""
#: src/views/firewall/CreateIpModal.vue:78
#: src/views/firewall/CreateModal.vue:80
msgid "%{ address } created successfully"
msgstr ""
#: src/views/firewall/CreateIpModal.vue:89
#: src/views/firewall/CreateModal.vue:93
#: src/views/firewall/CreateModal.vue:91
#: src/views/firewall/IpRuleView.vue:208
#: src/views/firewall/RuleView.vue:245
msgid "Create Rule"
msgstr ""
#: src/views/firewall/CreateIpModal.vue:100
#: src/views/firewall/CreateModal.vue:104
#: src/views/firewall/CreateModal.vue:102
#: src/views/firewall/IpRuleView.vue:32
#: src/views/firewall/RuleView.vue:32
msgid "Network Protocol"
@@ -3501,34 +3501,34 @@ msgstr ""
msgid "IP Address"
msgstr ""
#: src/views/firewall/CreateIpModal.vue:108
#: src/views/firewall/CreateModal.vue:133
msgid "Optional IP or IP range: 127.0.0.1 or 172.16.0.0/24 (multiple separated by commas)"
#: src/views/firewall/CreateIpModal.vue:107
#: src/views/firewall/CreateModal.vue:131
msgid "IP or IP range: 172.16.0.1 or 172.16.0.0/16"
msgstr ""
#: src/views/firewall/CreateIpModal.vue:114
#: src/views/firewall/CreateModal.vue:139
#: src/views/firewall/CreateIpModal.vue:110
#: src/views/firewall/CreateModal.vue:134
#: src/views/firewall/IpRuleView.vue:49
#: src/views/firewall/RuleView.vue:83
msgid "Strategy"
msgstr ""
#: src/views/firewall/CreateIpModal.vue:117
#: src/views/firewall/CreateModal.vue:142
#: src/views/firewall/CreateIpModal.vue:113
#: src/views/firewall/CreateModal.vue:137
#: src/views/firewall/IpRuleView.vue:85
#: src/views/firewall/RuleView.vue:119
msgid "Direction"
msgstr ""
#: src/views/firewall/CreateModal.vue:109
#: src/views/firewall/CreateModal.vue:107
msgid "Start Port"
msgstr ""
#: src/views/firewall/CreateModal.vue:119
#: src/views/firewall/CreateModal.vue:117
msgid "End Port"
msgstr ""
#: src/views/firewall/CreateModal.vue:129
#: src/views/firewall/CreateModal.vue:127
#: src/views/firewall/IpRuleView.vue:110
#: src/views/firewall/RuleView.vue:144
msgid "Target"

View File

@@ -10,7 +10,7 @@ msgstr ""
"Project-Id-Version: ratpanel\n"
"Language-Team: Chinese Simplified\n"
"Language: zh_CN\n"
"PO-Revision-Date: 2025-05-31 11:30\n"
"PO-Revision-Date: 2025-06-08 07:54\n"
#: src/components/common/AppFooter.vue:13
#: src/views/dashboard/IndexView.vue:439
@@ -151,7 +151,7 @@ msgstr "无效的名称"
#: src/views/cert/CreateCertModal.vue:50
#: src/views/cert/CreateDnsModal.vue:35
#: src/views/cert/UploadCertModal.vue:21
#: src/views/container/ComposeView.vue:246
#: src/views/container/ComposeView.vue:254
#: src/views/container/ContainerCreate.vue:106
#: src/views/container/NetworkView.vue:174
#: src/views/container/VolumeView.vue:128
@@ -159,7 +159,6 @@ msgstr "无效的名称"
#: src/views/database/CreateUserModal.vue:28
#: src/views/file/ToolBar.vue:45
#: src/views/firewall/CreateForwardModal.vue:41
#: src/views/firewall/CreateModal.vue:84
#: src/views/setting/CreateModal.vue:19
#: src/views/setting/TokenModal.vue:127
#: src/views/ssh/CreateModal.vue:38
@@ -191,7 +190,7 @@ msgid "Root Directory"
msgstr "根目录"
#: src/components/common/PathSelector.vue:335
#: src/views/app/VersionModal.vue:96
#: src/views/app/VersionModal.vue:97
#: src/views/apps/fail2ban/IndexView.vue:375
#: src/views/apps/pureftpd/IndexView.vue:249
#: src/views/apps/pureftpd/IndexView.vue:271
@@ -209,9 +208,9 @@ msgstr "根目录"
#: src/views/cert/DnsView.vue:373
#: src/views/cert/ObtainModal.vue:130
#: src/views/cert/UploadCertModal.vue:55
#: src/views/container/ComposeView.vue:340
#: src/views/container/ComposeView.vue:370
#: src/views/container/ContainerCreate.vue:370
#: src/views/container/ComposeView.vue:348
#: src/views/container/ComposeView.vue:378
#: src/views/container/ContainerCreate.vue:371
#: src/views/container/ContainerView.vue:485
#: src/views/container/ImageView.vue:217
#: src/views/container/NetworkView.vue:313
@@ -224,8 +223,8 @@ msgstr "根目录"
#: src/views/file/ToolBar.vue:261
#: src/views/file/ToolBar.vue:282
#: src/views/firewall/CreateForwardModal.vue:88
#: src/views/firewall/CreateIpModal.vue:122
#: src/views/firewall/CreateModal.vue:147
#: src/views/firewall/CreateIpModal.vue:118
#: src/views/firewall/CreateModal.vue:142
#: src/views/setting/CreateModal.vue:64
#: src/views/setting/PasswordModal.vue:44
#: src/views/setting/TwoFaModal.vue:87
@@ -288,6 +287,7 @@ msgid "Started successfully"
msgstr "启动成功"
#: src/components/common/ServiceStatus.vue:57
#: src/views/container/ComposeView.vue:168
msgid "Stopping..."
msgstr "停止中..."
@@ -364,7 +364,7 @@ msgstr "启动"
#: src/components/common/ServiceStatus.vue:158
#: src/views/apps/supervisor/IndexView.vue:145
#: src/views/container/ComposeView.vue:189
#: src/views/container/ComposeView.vue:197
#: src/views/container/ContainerView.vue:135
#: src/views/container/ContainerView.vue:413
msgid "Stop"
@@ -510,7 +510,7 @@ msgstr "备份"
#: src/locales/menu.ts:9
#: src/views/cert/CertView.vue:497
#: src/views/cert/CertView.vue:573
#: src/views/cert/CertView.vue:574
#: src/views/cert/UploadCertModal.vue:38
#: src/views/setting/SettingSafe.vue:54
#: src/views/website/EditView.vue:355
@@ -656,8 +656,8 @@ msgstr "在主页显示"
#: src/views/cert/CertView.vue:181
#: src/views/cert/DnsView.vue:64
#: src/views/container/ComposeView.vue:74
#: src/views/container/ContainerCreate.vue:174
#: src/views/container/ContainerCreate.vue:255
#: src/views/container/ContainerCreate.vue:175
#: src/views/container/ContainerCreate.vue:256
#: src/views/container/ContainerView.vue:91
#: src/views/container/ImageView.vue:69
#: src/views/container/NetworkView.vue:109
@@ -717,15 +717,15 @@ msgstr "更新缓存"
msgid "Before updating apps, it is strongly recommended to backup/snapshot first, so you can roll back immediately if there are any issues!"
msgstr "在更新应用前,强烈建议先进行备份/快照,这样如果出现任何问题,可以第一时间回滚!"
#: src/views/app/VersionModal.vue:73
#: src/views/app/VersionModal.vue:74
msgid "Channel"
msgstr "渠道"
#: src/views/app/VersionModal.vue:80
#: src/views/app/VersionModal.vue:81
msgid "Version"
msgstr "版本"
#: src/views/app/VersionModal.vue:83
#: src/views/app/VersionModal.vue:84
msgid "Please select a channel"
msgstr "请选择一个渠道"
@@ -847,9 +847,9 @@ msgstr "您确定要删除规则 %{ name } 吗?"
#: src/views/cert/AccountView.vue:127
#: src/views/cert/CertView.vue:314
#: src/views/cert/DnsView.vue:111
#: src/views/container/ComposeView.vue:220
#: src/views/container/ContainerCreate.vue:235
#: src/views/container/ContainerCreate.vue:286
#: src/views/container/ComposeView.vue:228
#: src/views/container/ContainerCreate.vue:236
#: src/views/container/ContainerCreate.vue:287
#: src/views/container/ContainerView.vue:160
#: src/views/container/ContainerView.vue:418
#: src/views/container/ImageView.vue:94
@@ -1052,9 +1052,9 @@ msgid "Load Status"
msgstr "负载状态"
#: src/views/apps/minio/IndexView.vue:39
#: src/views/container/ComposeView.vue:330
#: src/views/container/ComposeView.vue:360
#: src/views/container/ContainerCreate.vue:352
#: src/views/container/ComposeView.vue:338
#: src/views/container/ComposeView.vue:368
#: src/views/container/ContainerCreate.vue:353
msgid "Environment Variables"
msgstr "环境变量"
@@ -1675,7 +1675,7 @@ msgstr "正在向 CA 注册账户,请耐心等待"
#: src/views/cert/CertView.vue:348
#: src/views/cert/CertView.vue:365
#: src/views/cert/DnsView.vue:139
#: src/views/container/ComposeView.vue:264
#: src/views/container/ComposeView.vue:272
msgid "Update successful"
msgstr "更新成功"
@@ -1851,7 +1851,7 @@ msgid "Enter the content of the PEM certificate file"
msgstr "输入 PEM 证书文件的内容"
#: src/views/cert/CertView.vue:509
#: src/views/cert/CertView.vue:585
#: src/views/cert/CertView.vue:586
#: src/views/cert/UploadCertModal.vue:46
#: src/views/setting/SettingSafe.vue:61
#: src/views/ssh/CreateModal.vue:78
@@ -2150,17 +2150,17 @@ msgstr "您确定要启动编排 %{ name } 吗?"
msgid "Force pull images"
msgstr "强制拉取镜像"
#: src/views/container/ComposeView.vue:170
#: src/views/container/ComposeView.vue:175
#: src/views/container/ContainerView.vue:248
#: src/views/container/ContainerView.vue:319
msgid "Stop successful"
msgstr "停止成功"
#: src/views/container/ComposeView.vue:176
#: src/views/container/ComposeView.vue:184
msgid "Are you sure you want to stop compose %{ name }?"
msgstr "您确定要停止编排 %{ name } 吗?"
#: src/views/container/ComposeView.vue:201
#: src/views/container/ComposeView.vue:209
#: src/views/container/ContainerView.vue:283
#: src/views/container/ContainerView.vue:361
#: src/views/container/ImageView.vue:118
@@ -2169,38 +2169,38 @@ msgstr "您确定要停止编排 %{ name } 吗?"
msgid "Delete successful"
msgstr "删除成功"
#: src/views/container/ComposeView.vue:207
#: src/views/container/ComposeView.vue:215
msgid "Are you sure you want to delete compose %{ name }?"
msgstr "您确定要删除编排 %{ name } 吗?"
#: src/views/container/ComposeView.vue:286
#: src/views/container/ComposeView.vue:313
#: src/views/container/ComposeView.vue:294
#: src/views/container/ComposeView.vue:321
msgid "Create Compose"
msgstr "创建编排"
#: src/views/container/ComposeView.vue:320
#: src/views/container/ComposeView.vue:328
msgid "Compose Name"
msgstr "编排名称"
#: src/views/container/ComposeView.vue:323
#: src/views/container/ComposeView.vue:353
#: src/views/container/ComposeView.vue:331
#: src/views/container/ComposeView.vue:361
#: src/views/container/IndexView.vue:24
msgid "Compose"
msgstr "编排"
#: src/views/container/ComposeView.vue:334
#: src/views/container/ComposeView.vue:364
#: src/views/container/ContainerCreate.vue:356
#: src/views/container/ComposeView.vue:342
#: src/views/container/ComposeView.vue:372
#: src/views/container/ContainerCreate.vue:357
msgid "Variable Name"
msgstr "变量名"
#: src/views/container/ComposeView.vue:335
#: src/views/container/ComposeView.vue:365
#: src/views/container/ContainerCreate.vue:357
#: src/views/container/ComposeView.vue:343
#: src/views/container/ComposeView.vue:373
#: src/views/container/ContainerCreate.vue:358
msgid "Variable Value"
msgstr "变量值"
#: src/views/container/ComposeView.vue:346
#: src/views/container/ComposeView.vue:354
msgid "Edit Compose"
msgstr "编辑编排"
@@ -2221,82 +2221,82 @@ msgstr "除非停止"
msgid "Create Container"
msgstr "创建容器"
#: src/views/container/ContainerCreate.vue:137
#: src/views/container/ContainerCreate.vue:138
#: src/views/container/ContainerView.vue:25
msgid "Container Name"
msgstr "容器名称"
#: src/views/container/ContainerCreate.vue:140
#: src/views/container/ContainerCreate.vue:141
#: src/views/container/ContainerView.vue:52
#: src/views/container/ImageView.vue:36
msgid "Image"
msgstr "镜像"
#: src/views/container/ContainerCreate.vue:143
#: src/views/container/ContainerCreate.vue:144
msgid "Ports"
msgstr "端口"
#: src/views/container/ContainerCreate.vue:149
#: src/views/container/ContainerCreate.vue:150
msgid "Map Ports"
msgstr "映射端口"
#: src/views/container/ContainerCreate.vue:156
#: src/views/container/ContainerCreate.vue:157
msgid "Expose All"
msgstr "全部暴露"
#: src/views/container/ContainerCreate.vue:161
#: src/views/container/ContainerCreate.vue:162
msgid "Port Mapping"
msgstr "端口映射"
#: src/views/container/ContainerCreate.vue:169
#: src/views/container/ContainerCreate.vue:170
msgid "Host (Start)"
msgstr "主机(起始)"
#: src/views/container/ContainerCreate.vue:170
#: src/views/container/ContainerCreate.vue:171
msgid "Host (End)"
msgstr "主机(结束)"
#: src/views/container/ContainerCreate.vue:171
#: src/views/container/ContainerCreate.vue:172
msgid "Container (Start)"
msgstr "容器(起始)"
#: src/views/container/ContainerCreate.vue:172
#: src/views/container/ContainerCreate.vue:173
msgid "Container (End)"
msgstr "容器(结束)"
#: src/views/container/ContainerCreate.vue:173
#: src/views/container/ContainerCreate.vue:174
msgid "Protocol"
msgstr "协议"
#: src/views/container/ContainerCreate.vue:184
#: src/views/container/ContainerCreate.vue:185
msgid "Optional"
msgstr "可选"
#: src/views/container/ContainerCreate.vue:241
#: src/views/container/ContainerCreate.vue:292
#: src/views/container/ContainerCreate.vue:242
#: src/views/container/ContainerCreate.vue:293
msgid "Add"
msgstr "添加"
#: src/views/container/ContainerCreate.vue:244
#: src/views/container/ContainerCreate.vue:245
#: src/views/dashboard/IndexView.vue:141
#: src/views/dashboard/IndexView.vue:797
#: src/views/monitor/IndexView.vue:286
msgid "Network"
msgstr "网络"
#: src/views/container/ContainerCreate.vue:247
#: src/views/container/ContainerCreate.vue:248
msgid "Mount"
msgstr "挂载"
#: src/views/container/ContainerCreate.vue:252
#: src/views/container/ContainerCreate.vue:253
msgid "Host Directory"
msgstr "主机目录"
#: src/views/container/ContainerCreate.vue:253
#: src/views/container/ContainerCreate.vue:254
msgid "Container Directory"
msgstr "容器目录"
#: src/views/container/ContainerCreate.vue:254
#: src/views/container/ContainerCreate.vue:255
#: src/views/file/ListTable.vue:73
#: src/views/file/ListTable.vue:145
#: src/views/file/ListTable.vue:300
@@ -2305,25 +2305,25 @@ msgstr "容器目录"
msgid "Permission"
msgstr "权限"
#: src/views/container/ContainerCreate.vue:273
#: src/views/container/ContainerCreate.vue:274
msgid "Read-Write"
msgstr "读写"
#: src/views/container/ContainerCreate.vue:281
#: src/views/container/ContainerCreate.vue:282
msgid "Read-Only"
msgstr "只读"
#: src/views/container/ContainerCreate.vue:295
#: src/views/container/ContainerCreate.vue:296
#: src/views/container/ContainerCreate.vue:297
msgid "Command"
msgstr "命令"
#: src/views/container/ContainerCreate.vue:298
#: src/views/container/ContainerCreate.vue:301
#: src/views/container/ContainerCreate.vue:299
#: src/views/container/ContainerCreate.vue:302
msgid "Entrypoint"
msgstr "入口点"
#: src/views/container/ContainerCreate.vue:306
#: src/views/container/ContainerCreate.vue:307
#: src/views/dashboard/IndexView.vue:533
#: src/views/monitor/IndexView.vue:205
#: src/views/monitor/IndexView.vue:216
@@ -2333,48 +2333,48 @@ msgstr "入口点"
msgid "Memory"
msgstr "内存"
#: src/views/container/ContainerCreate.vue:316
#: src/views/container/ContainerCreate.vue:317
msgid "CPU Shares"
msgstr "CPU 份额"
#: src/views/container/ContainerCreate.vue:323
#: src/views/container/ContainerCreate.vue:324
msgid "TTY (-t)"
msgstr "TTY (-t)"
#: src/views/container/ContainerCreate.vue:328
#: src/views/container/ContainerCreate.vue:329
msgid "STDIN (-i)"
msgstr "STDIN (-i)"
#: src/views/container/ContainerCreate.vue:333
#: src/views/container/ContainerCreate.vue:334
msgid "Auto Remove"
msgstr "自动移除"
#: src/views/container/ContainerCreate.vue:338
#: src/views/container/ContainerCreate.vue:339
msgid "Privileged Mode"
msgstr "特权模式"
#: src/views/container/ContainerCreate.vue:343
#: src/views/container/ContainerCreate.vue:344
msgid "Restart Policy"
msgstr "重启策略"
#: src/views/container/ContainerCreate.vue:346
#: src/views/container/ContainerCreate.vue:349
#: src/views/container/ContainerCreate.vue:347
#: src/views/container/ContainerCreate.vue:350
msgid "Select restart policy"
msgstr "选择重启策略"
#: src/views/container/ContainerCreate.vue:360
#: src/views/container/ContainerCreate.vue:361
#: src/views/container/NetworkView.vue:295
#: src/views/container/VolumeView.vue:195
msgid "Labels"
msgstr "标签"
#: src/views/container/ContainerCreate.vue:364
#: src/views/container/ContainerCreate.vue:365
#: src/views/container/NetworkView.vue:299
#: src/views/container/VolumeView.vue:199
msgid "Label Name"
msgstr "标签名称"
#: src/views/container/ContainerCreate.vue:365
#: src/views/container/ContainerCreate.vue:366
#: src/views/container/NetworkView.vue:300
#: src/views/container/VolumeView.vue:200
msgid "Label Value"
@@ -3432,7 +3432,7 @@ msgstr "创建转发"
#: src/views/firewall/CreateForwardModal.vue:58
#: src/views/firewall/CreateIpModal.vue:97
#: src/views/firewall/CreateModal.vue:101
#: src/views/firewall/CreateModal.vue:99
#: src/views/firewall/ForwardView.vue:15
#: src/views/firewall/IpRuleView.vue:15
#: src/views/firewall/RuleView.vue:15
@@ -3489,18 +3489,19 @@ msgid "Outbound"
msgstr "出站"
#: src/views/firewall/CreateIpModal.vue:78
#: src/views/firewall/CreateModal.vue:80
msgid "%{ address } created successfully"
msgstr "%{ address } 创建成功"
#: src/views/firewall/CreateIpModal.vue:89
#: src/views/firewall/CreateModal.vue:93
#: src/views/firewall/CreateModal.vue:91
#: src/views/firewall/IpRuleView.vue:208
#: src/views/firewall/RuleView.vue:245
msgid "Create Rule"
msgstr "创建规则"
#: src/views/firewall/CreateIpModal.vue:100
#: src/views/firewall/CreateModal.vue:104
#: src/views/firewall/CreateModal.vue:102
#: src/views/firewall/IpRuleView.vue:32
#: src/views/firewall/RuleView.vue:32
msgid "Network Protocol"
@@ -3510,34 +3511,34 @@ msgstr "网络协议"
msgid "IP Address"
msgstr "IP 地址"
#: src/views/firewall/CreateIpModal.vue:108
#: src/views/firewall/CreateModal.vue:133
msgid "Optional IP or IP range: 127.0.0.1 or 172.16.0.0/24 (multiple separated by commas)"
msgstr "可选 IP 或 IP 范围127.0.0.1 或 172.16.0.0/24多个用逗号分隔"
#: src/views/firewall/CreateIpModal.vue:107
#: src/views/firewall/CreateModal.vue:131
msgid "IP or IP range: 172.16.0.1 or 172.16.0.0/16"
msgstr "IP 或 IP 范围172.16.0.1 或 172.16.0.0/16"
#: src/views/firewall/CreateIpModal.vue:114
#: src/views/firewall/CreateModal.vue:139
#: src/views/firewall/CreateIpModal.vue:110
#: src/views/firewall/CreateModal.vue:134
#: src/views/firewall/IpRuleView.vue:49
#: src/views/firewall/RuleView.vue:83
msgid "Strategy"
msgstr "策略"
#: src/views/firewall/CreateIpModal.vue:117
#: src/views/firewall/CreateModal.vue:142
#: src/views/firewall/CreateIpModal.vue:113
#: src/views/firewall/CreateModal.vue:137
#: src/views/firewall/IpRuleView.vue:85
#: src/views/firewall/RuleView.vue:119
msgid "Direction"
msgstr "方向"
#: src/views/firewall/CreateModal.vue:109
#: src/views/firewall/CreateModal.vue:107
msgid "Start Port"
msgstr "起始端口"
#: src/views/firewall/CreateModal.vue:119
#: src/views/firewall/CreateModal.vue:117
msgid "End Port"
msgstr "结束端口"
#: src/views/firewall/CreateModal.vue:129
#: src/views/firewall/CreateModal.vue:127
#: src/views/firewall/IpRuleView.vue:110
#: src/views/firewall/RuleView.vue:144
msgid "Target"

View File

@@ -10,7 +10,7 @@ msgstr ""
"Project-Id-Version: ratpanel\n"
"Language-Team: Chinese Traditional\n"
"Language: zh_TW\n"
"PO-Revision-Date: 2025-05-31 11:30\n"
"PO-Revision-Date: 2025-06-08 07:54\n"
#: src/components/common/AppFooter.vue:13
#: src/views/dashboard/IndexView.vue:439
@@ -151,7 +151,7 @@ msgstr "無效的名稱"
#: src/views/cert/CreateCertModal.vue:50
#: src/views/cert/CreateDnsModal.vue:35
#: src/views/cert/UploadCertModal.vue:21
#: src/views/container/ComposeView.vue:246
#: src/views/container/ComposeView.vue:254
#: src/views/container/ContainerCreate.vue:106
#: src/views/container/NetworkView.vue:174
#: src/views/container/VolumeView.vue:128
@@ -159,7 +159,6 @@ msgstr "無效的名稱"
#: src/views/database/CreateUserModal.vue:28
#: src/views/file/ToolBar.vue:45
#: src/views/firewall/CreateForwardModal.vue:41
#: src/views/firewall/CreateModal.vue:84
#: src/views/setting/CreateModal.vue:19
#: src/views/setting/TokenModal.vue:127
#: src/views/ssh/CreateModal.vue:38
@@ -191,7 +190,7 @@ msgid "Root Directory"
msgstr "根目錄"
#: src/components/common/PathSelector.vue:335
#: src/views/app/VersionModal.vue:96
#: src/views/app/VersionModal.vue:97
#: src/views/apps/fail2ban/IndexView.vue:375
#: src/views/apps/pureftpd/IndexView.vue:249
#: src/views/apps/pureftpd/IndexView.vue:271
@@ -209,9 +208,9 @@ msgstr "根目錄"
#: src/views/cert/DnsView.vue:373
#: src/views/cert/ObtainModal.vue:130
#: src/views/cert/UploadCertModal.vue:55
#: src/views/container/ComposeView.vue:340
#: src/views/container/ComposeView.vue:370
#: src/views/container/ContainerCreate.vue:370
#: src/views/container/ComposeView.vue:348
#: src/views/container/ComposeView.vue:378
#: src/views/container/ContainerCreate.vue:371
#: src/views/container/ContainerView.vue:485
#: src/views/container/ImageView.vue:217
#: src/views/container/NetworkView.vue:313
@@ -224,8 +223,8 @@ msgstr "根目錄"
#: src/views/file/ToolBar.vue:261
#: src/views/file/ToolBar.vue:282
#: src/views/firewall/CreateForwardModal.vue:88
#: src/views/firewall/CreateIpModal.vue:122
#: src/views/firewall/CreateModal.vue:147
#: src/views/firewall/CreateIpModal.vue:118
#: src/views/firewall/CreateModal.vue:142
#: src/views/setting/CreateModal.vue:64
#: src/views/setting/PasswordModal.vue:44
#: src/views/setting/TwoFaModal.vue:87
@@ -288,6 +287,7 @@ msgid "Started successfully"
msgstr "啟動成功"
#: src/components/common/ServiceStatus.vue:57
#: src/views/container/ComposeView.vue:168
msgid "Stopping..."
msgstr "停止中..."
@@ -364,7 +364,7 @@ msgstr "開始"
#: src/components/common/ServiceStatus.vue:158
#: src/views/apps/supervisor/IndexView.vue:145
#: src/views/container/ComposeView.vue:189
#: src/views/container/ComposeView.vue:197
#: src/views/container/ContainerView.vue:135
#: src/views/container/ContainerView.vue:413
msgid "Stop"
@@ -510,7 +510,7 @@ msgstr "備份"
#: src/locales/menu.ts:9
#: src/views/cert/CertView.vue:497
#: src/views/cert/CertView.vue:573
#: src/views/cert/CertView.vue:574
#: src/views/cert/UploadCertModal.vue:38
#: src/views/setting/SettingSafe.vue:54
#: src/views/website/EditView.vue:355
@@ -656,8 +656,8 @@ msgstr "在主頁顯示"
#: src/views/cert/CertView.vue:181
#: src/views/cert/DnsView.vue:64
#: src/views/container/ComposeView.vue:74
#: src/views/container/ContainerCreate.vue:174
#: src/views/container/ContainerCreate.vue:255
#: src/views/container/ContainerCreate.vue:175
#: src/views/container/ContainerCreate.vue:256
#: src/views/container/ContainerView.vue:91
#: src/views/container/ImageView.vue:69
#: src/views/container/NetworkView.vue:109
@@ -717,15 +717,15 @@ msgstr "更新快取"
msgid "Before updating apps, it is strongly recommended to backup/snapshot first, so you can roll back immediately if there are any issues!"
msgstr "在更新應用程式之前,強烈建議先進行備份/快照,這樣如果出現任何問題,可以立即回滾!"
#: src/views/app/VersionModal.vue:73
#: src/views/app/VersionModal.vue:74
msgid "Channel"
msgstr "渠道"
#: src/views/app/VersionModal.vue:80
#: src/views/app/VersionModal.vue:81
msgid "Version"
msgstr "版本"
#: src/views/app/VersionModal.vue:83
#: src/views/app/VersionModal.vue:84
msgid "Please select a channel"
msgstr "請選擇一個渠道"
@@ -847,9 +847,9 @@ msgstr "您確定要刪除規則 %{ name } 嗎?"
#: src/views/cert/AccountView.vue:127
#: src/views/cert/CertView.vue:314
#: src/views/cert/DnsView.vue:111
#: src/views/container/ComposeView.vue:220
#: src/views/container/ContainerCreate.vue:235
#: src/views/container/ContainerCreate.vue:286
#: src/views/container/ComposeView.vue:228
#: src/views/container/ContainerCreate.vue:236
#: src/views/container/ContainerCreate.vue:287
#: src/views/container/ContainerView.vue:160
#: src/views/container/ContainerView.vue:418
#: src/views/container/ImageView.vue:94
@@ -1052,9 +1052,9 @@ msgid "Load Status"
msgstr "負載狀態"
#: src/views/apps/minio/IndexView.vue:39
#: src/views/container/ComposeView.vue:330
#: src/views/container/ComposeView.vue:360
#: src/views/container/ContainerCreate.vue:352
#: src/views/container/ComposeView.vue:338
#: src/views/container/ComposeView.vue:368
#: src/views/container/ContainerCreate.vue:353
msgid "Environment Variables"
msgstr "環境變數"
@@ -1675,7 +1675,7 @@ msgstr "正在向 CA 註冊賬戶,請耐心等待"
#: src/views/cert/CertView.vue:348
#: src/views/cert/CertView.vue:365
#: src/views/cert/DnsView.vue:139
#: src/views/container/ComposeView.vue:264
#: src/views/container/ComposeView.vue:272
msgid "Update successful"
msgstr "更新成功"
@@ -1851,7 +1851,7 @@ msgid "Enter the content of the PEM certificate file"
msgstr "輸入 PEM 證書文件的內容"
#: src/views/cert/CertView.vue:509
#: src/views/cert/CertView.vue:585
#: src/views/cert/CertView.vue:586
#: src/views/cert/UploadCertModal.vue:46
#: src/views/setting/SettingSafe.vue:61
#: src/views/ssh/CreateModal.vue:78
@@ -2150,17 +2150,17 @@ msgstr "您確定要啟動編排 %{ name } 嗎?"
msgid "Force pull images"
msgstr "強制拉取鏡像"
#: src/views/container/ComposeView.vue:170
#: src/views/container/ComposeView.vue:175
#: src/views/container/ContainerView.vue:248
#: src/views/container/ContainerView.vue:319
msgid "Stop successful"
msgstr "停止成功"
#: src/views/container/ComposeView.vue:176
#: src/views/container/ComposeView.vue:184
msgid "Are you sure you want to stop compose %{ name }?"
msgstr "您確定要停止編排 %{ name } 嗎?"
#: src/views/container/ComposeView.vue:201
#: src/views/container/ComposeView.vue:209
#: src/views/container/ContainerView.vue:283
#: src/views/container/ContainerView.vue:361
#: src/views/container/ImageView.vue:118
@@ -2169,38 +2169,38 @@ msgstr "您確定要停止編排 %{ name } 嗎?"
msgid "Delete successful"
msgstr "刪除成功"
#: src/views/container/ComposeView.vue:207
#: src/views/container/ComposeView.vue:215
msgid "Are you sure you want to delete compose %{ name }?"
msgstr "您確定要刪除編排 %{ name } 嗎?"
#: src/views/container/ComposeView.vue:286
#: src/views/container/ComposeView.vue:313
#: src/views/container/ComposeView.vue:294
#: src/views/container/ComposeView.vue:321
msgid "Create Compose"
msgstr "創建編排"
#: src/views/container/ComposeView.vue:320
#: src/views/container/ComposeView.vue:328
msgid "Compose Name"
msgstr "編排名稱"
#: src/views/container/ComposeView.vue:323
#: src/views/container/ComposeView.vue:353
#: src/views/container/ComposeView.vue:331
#: src/views/container/ComposeView.vue:361
#: src/views/container/IndexView.vue:24
msgid "Compose"
msgstr "編排"
#: src/views/container/ComposeView.vue:334
#: src/views/container/ComposeView.vue:364
#: src/views/container/ContainerCreate.vue:356
#: src/views/container/ComposeView.vue:342
#: src/views/container/ComposeView.vue:372
#: src/views/container/ContainerCreate.vue:357
msgid "Variable Name"
msgstr "變數名稱"
#: src/views/container/ComposeView.vue:335
#: src/views/container/ComposeView.vue:365
#: src/views/container/ContainerCreate.vue:357
#: src/views/container/ComposeView.vue:343
#: src/views/container/ComposeView.vue:373
#: src/views/container/ContainerCreate.vue:358
msgid "Variable Value"
msgstr "變數值"
#: src/views/container/ComposeView.vue:346
#: src/views/container/ComposeView.vue:354
msgid "Edit Compose"
msgstr "編輯編排"
@@ -2221,82 +2221,82 @@ msgstr "除非停止"
msgid "Create Container"
msgstr "創建容器"
#: src/views/container/ContainerCreate.vue:137
#: src/views/container/ContainerCreate.vue:138
#: src/views/container/ContainerView.vue:25
msgid "Container Name"
msgstr "容器名稱"
#: src/views/container/ContainerCreate.vue:140
#: src/views/container/ContainerCreate.vue:141
#: src/views/container/ContainerView.vue:52
#: src/views/container/ImageView.vue:36
msgid "Image"
msgstr "鏡像"
#: src/views/container/ContainerCreate.vue:143
#: src/views/container/ContainerCreate.vue:144
msgid "Ports"
msgstr "端口"
#: src/views/container/ContainerCreate.vue:149
#: src/views/container/ContainerCreate.vue:150
msgid "Map Ports"
msgstr "映射端口"
#: src/views/container/ContainerCreate.vue:156
#: src/views/container/ContainerCreate.vue:157
msgid "Expose All"
msgstr "全部暴露"
#: src/views/container/ContainerCreate.vue:161
#: src/views/container/ContainerCreate.vue:162
msgid "Port Mapping"
msgstr "端口映射"
#: src/views/container/ContainerCreate.vue:169
#: src/views/container/ContainerCreate.vue:170
msgid "Host (Start)"
msgstr "主機(起始)"
#: src/views/container/ContainerCreate.vue:170
#: src/views/container/ContainerCreate.vue:171
msgid "Host (End)"
msgstr "主機(結束)"
#: src/views/container/ContainerCreate.vue:171
#: src/views/container/ContainerCreate.vue:172
msgid "Container (Start)"
msgstr "容器(起始)"
#: src/views/container/ContainerCreate.vue:172
#: src/views/container/ContainerCreate.vue:173
msgid "Container (End)"
msgstr "容器(結束)"
#: src/views/container/ContainerCreate.vue:173
#: src/views/container/ContainerCreate.vue:174
msgid "Protocol"
msgstr "協議"
#: src/views/container/ContainerCreate.vue:184
#: src/views/container/ContainerCreate.vue:185
msgid "Optional"
msgstr "可選"
#: src/views/container/ContainerCreate.vue:241
#: src/views/container/ContainerCreate.vue:292
#: src/views/container/ContainerCreate.vue:242
#: src/views/container/ContainerCreate.vue:293
msgid "Add"
msgstr "添加"
#: src/views/container/ContainerCreate.vue:244
#: src/views/container/ContainerCreate.vue:245
#: src/views/dashboard/IndexView.vue:141
#: src/views/dashboard/IndexView.vue:797
#: src/views/monitor/IndexView.vue:286
msgid "Network"
msgstr "網絡"
#: src/views/container/ContainerCreate.vue:247
#: src/views/container/ContainerCreate.vue:248
msgid "Mount"
msgstr "掛載"
#: src/views/container/ContainerCreate.vue:252
#: src/views/container/ContainerCreate.vue:253
msgid "Host Directory"
msgstr "主機目錄"
#: src/views/container/ContainerCreate.vue:253
#: src/views/container/ContainerCreate.vue:254
msgid "Container Directory"
msgstr "容器目錄"
#: src/views/container/ContainerCreate.vue:254
#: src/views/container/ContainerCreate.vue:255
#: src/views/file/ListTable.vue:73
#: src/views/file/ListTable.vue:145
#: src/views/file/ListTable.vue:300
@@ -2305,25 +2305,25 @@ msgstr "容器目錄"
msgid "Permission"
msgstr "權限"
#: src/views/container/ContainerCreate.vue:273
#: src/views/container/ContainerCreate.vue:274
msgid "Read-Write"
msgstr "讀寫"
#: src/views/container/ContainerCreate.vue:281
#: src/views/container/ContainerCreate.vue:282
msgid "Read-Only"
msgstr "唯讀"
#: src/views/container/ContainerCreate.vue:295
#: src/views/container/ContainerCreate.vue:296
#: src/views/container/ContainerCreate.vue:297
msgid "Command"
msgstr "命令"
#: src/views/container/ContainerCreate.vue:298
#: src/views/container/ContainerCreate.vue:301
#: src/views/container/ContainerCreate.vue:299
#: src/views/container/ContainerCreate.vue:302
msgid "Entrypoint"
msgstr "進入點"
#: src/views/container/ContainerCreate.vue:306
#: src/views/container/ContainerCreate.vue:307
#: src/views/dashboard/IndexView.vue:533
#: src/views/monitor/IndexView.vue:205
#: src/views/monitor/IndexView.vue:216
@@ -2333,48 +2333,48 @@ msgstr "進入點"
msgid "Memory"
msgstr "記憶體"
#: src/views/container/ContainerCreate.vue:316
#: src/views/container/ContainerCreate.vue:317
msgid "CPU Shares"
msgstr "CPU 份額"
#: src/views/container/ContainerCreate.vue:323
#: src/views/container/ContainerCreate.vue:324
msgid "TTY (-t)"
msgstr "TTY (-t)"
#: src/views/container/ContainerCreate.vue:328
#: src/views/container/ContainerCreate.vue:329
msgid "STDIN (-i)"
msgstr "STDIN (-i)"
#: src/views/container/ContainerCreate.vue:333
#: src/views/container/ContainerCreate.vue:334
msgid "Auto Remove"
msgstr "自動移除"
#: src/views/container/ContainerCreate.vue:338
#: src/views/container/ContainerCreate.vue:339
msgid "Privileged Mode"
msgstr "特權模式"
#: src/views/container/ContainerCreate.vue:343
#: src/views/container/ContainerCreate.vue:344
msgid "Restart Policy"
msgstr "重啟策略"
#: src/views/container/ContainerCreate.vue:346
#: src/views/container/ContainerCreate.vue:349
#: src/views/container/ContainerCreate.vue:347
#: src/views/container/ContainerCreate.vue:350
msgid "Select restart policy"
msgstr "選擇重啟策略"
#: src/views/container/ContainerCreate.vue:360
#: src/views/container/ContainerCreate.vue:361
#: src/views/container/NetworkView.vue:295
#: src/views/container/VolumeView.vue:195
msgid "Labels"
msgstr "標籤"
#: src/views/container/ContainerCreate.vue:364
#: src/views/container/ContainerCreate.vue:365
#: src/views/container/NetworkView.vue:299
#: src/views/container/VolumeView.vue:199
msgid "Label Name"
msgstr "標籤名稱"
#: src/views/container/ContainerCreate.vue:365
#: src/views/container/ContainerCreate.vue:366
#: src/views/container/NetworkView.vue:300
#: src/views/container/VolumeView.vue:200
msgid "Label Value"
@@ -3432,7 +3432,7 @@ msgstr "創建轉發"
#: src/views/firewall/CreateForwardModal.vue:58
#: src/views/firewall/CreateIpModal.vue:97
#: src/views/firewall/CreateModal.vue:101
#: src/views/firewall/CreateModal.vue:99
#: src/views/firewall/ForwardView.vue:15
#: src/views/firewall/IpRuleView.vue:15
#: src/views/firewall/RuleView.vue:15
@@ -3489,18 +3489,19 @@ msgid "Outbound"
msgstr "出站"
#: src/views/firewall/CreateIpModal.vue:78
#: src/views/firewall/CreateModal.vue:80
msgid "%{ address } created successfully"
msgstr "%{ address } 創建成功"
#: src/views/firewall/CreateIpModal.vue:89
#: src/views/firewall/CreateModal.vue:93
#: src/views/firewall/CreateModal.vue:91
#: src/views/firewall/IpRuleView.vue:208
#: src/views/firewall/RuleView.vue:245
msgid "Create Rule"
msgstr "創建規則"
#: src/views/firewall/CreateIpModal.vue:100
#: src/views/firewall/CreateModal.vue:104
#: src/views/firewall/CreateModal.vue:102
#: src/views/firewall/IpRuleView.vue:32
#: src/views/firewall/RuleView.vue:32
msgid "Network Protocol"
@@ -3510,34 +3511,34 @@ msgstr "網路協議"
msgid "IP Address"
msgstr "IP 地址"
#: src/views/firewall/CreateIpModal.vue:108
#: src/views/firewall/CreateModal.vue:133
msgid "Optional IP or IP range: 127.0.0.1 or 172.16.0.0/24 (multiple separated by commas)"
msgstr "可選 IP 或 IP 範圍127.0.0.1 或 172.16.0.0/24多個用逗號分隔"
#: src/views/firewall/CreateIpModal.vue:107
#: src/views/firewall/CreateModal.vue:131
msgid "IP or IP range: 172.16.0.1 or 172.16.0.0/16"
msgstr "IP 或 IP 範圍172.16.0.1 或 172.16.0.0/16"
#: src/views/firewall/CreateIpModal.vue:114
#: src/views/firewall/CreateModal.vue:139
#: src/views/firewall/CreateIpModal.vue:110
#: src/views/firewall/CreateModal.vue:134
#: src/views/firewall/IpRuleView.vue:49
#: src/views/firewall/RuleView.vue:83
msgid "Strategy"
msgstr "策略"
#: src/views/firewall/CreateIpModal.vue:117
#: src/views/firewall/CreateModal.vue:142
#: src/views/firewall/CreateIpModal.vue:113
#: src/views/firewall/CreateModal.vue:137
#: src/views/firewall/IpRuleView.vue:85
#: src/views/firewall/RuleView.vue:119
msgid "Direction"
msgstr "方向"
#: src/views/firewall/CreateModal.vue:109
#: src/views/firewall/CreateModal.vue:107
msgid "Start Port"
msgstr "起始端口"
#: src/views/firewall/CreateModal.vue:119
#: src/views/firewall/CreateModal.vue:117
msgid "End Port"
msgstr "結束連接埠"
#: src/views/firewall/CreateModal.vue:129
#: src/views/firewall/CreateModal.vue:127
#: src/views/firewall/IpRuleView.vue:110
#: src/views/firewall/RuleView.vue:144
msgid "Target"

View File

@@ -104,11 +104,7 @@ const handleCreate = async () => {
<n-dynamic-input
v-model:value="createModel.address"
show-sort-button
:placeholder="
$gettext(
'Optional IP or IP range: 127.0.0.1 or 172.16.0.0/24 (multiple separated by commas)'
)
"
:placeholder="$gettext('IP or IP range: 172.16.0.1 or 172.16.0.0/16')"
/>
</n-form-item>
<n-form-item path="strategy" :label="$gettext('Strategy')">

View File

@@ -64,25 +64,23 @@ const createModel = ref({
protocol: 'tcp',
port_start: 80,
port_end: 80,
address: '',
address: [],
strategy: 'accept',
direction: 'in'
})
const handleCreate = async () => {
useRequest(firewall.createRule(createModel.value)).onSuccess(() => {
show.value = false
createModel.value = {
family: 'ipv4',
protocol: 'tcp',
port_start: 80,
port_end: 80,
address: '',
strategy: 'accept',
direction: 'in'
}
window.$message.success($gettext('Created successfully'))
})
for (const address of createModel.value.address) {
useRequest(
firewall.createRule({
...createModel.value,
address
})
).onSuccess(() => {
window.$message.success($gettext('%{ address } created successfully', { address: address }))
show.value = false
})
}
}
</script>
@@ -127,13 +125,10 @@ const handleCreate = async () => {
</n-col>
</n-row>
<n-form-item path="address" :label="$gettext('Target')">
<n-input
<n-dynamic-input
v-model:value="createModel.address"
:placeholder="
$gettext(
'Optional IP or IP range: 127.0.0.1 or 172.16.0.0/24 (multiple separated by commas)'
)
"
show-sort-button
:placeholder="$gettext('IP or IP range: 172.16.0.1 or 172.16.0.0/16')"
/>
</n-form-item>
<n-form-item path="strategy" :label="$gettext('Strategy')">