Compare commits

...

4 Commits

Author SHA1 Message Date
黑歌
da1af18878
Merge 6b72e7394d into 312086abe5 2025-01-20 22:14:24 +08:00
naiba
312086abe5 feat: upgrade frontend
Some checks are pending
CodeQL / Analyze (go) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Contributors / contributors (push) Waiting to run
Sync / sync-to-jihulab (push) Waiting to run
2025-01-20 22:14:06 +08:00
Weblate (bot)
7ebe492d78
Translated using Weblate (Tamil) (#962)
Currently translated at 100.0% (57 of 57 strings)

Translated using Weblate (Tamil)

Currently translated at 100.0% (57 of 57 strings)

Translated using Weblate (Tamil)

Currently translated at 100.0% (57 of 57 strings)

Added translation using Weblate (Tamil)




Translate-URL: https://hosted.weblate.org/projects/nezha/nezha-dashboard/ta/
Translation: Nezha/Nezha Dashboard

Co-authored-by: UUBulb <uub@kuzu.uk>
Co-authored-by: தமிழ்நேரம் <anishprabu.t@gmail.com>
2025-01-20 22:09:11 +08:00
dysf888
6b72e7394d feat: Telegram Widget Login 2025-01-14 19:33:31 +08:00
4 changed files with 441 additions and 4 deletions

View File

@ -2,9 +2,13 @@ package controller
import ( import (
"context" "context"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"sort"
"strconv" "strconv"
"strings" "strings"
@ -52,7 +56,10 @@ func oauth2redirect(c *gin.Context) (*model.Oauth2LoginResponse, error) {
return nil, singleton.Localizer.ErrorT("provider not found") return nil, singleton.Localizer.ErrorT("provider not found")
} }
o2conf := o2confRaw.Setup(getRedirectURL(c)) o2conf := o2confRaw.Setup(getRedirectURL(c))
if provider == "Telegram" {
// 直接返回配置中的 AuthURL
return &model.Oauth2LoginResponse{Redirect: o2confRaw.Endpoint.AuthURL}, nil
}
randomString, err := utils.GenerateRandomString(32) randomString, err := utils.GenerateRandomString(32)
if err != nil { if err != nil {
return nil, err return nil, err
@ -117,6 +124,69 @@ func unbindOauth2(c *gin.Context) (any, error) {
// @Router /api/v1/oauth2/callback [get] // @Router /api/v1/oauth2/callback [get]
func oauth2callback(jwtConfig *jwt.GinJWTMiddleware) func(c *gin.Context) (any, error) { func oauth2callback(jwtConfig *jwt.GinJWTMiddleware) func(c *gin.Context) (any, error) {
return func(c *gin.Context) (any, error) { return func(c *gin.Context) (any, error) {
// 通过判断请求参数来确定是否是 Telegram 回调
if c.Query("id") != "" && c.Query("auth_date") != "" && c.Query("hash") != "" {
queryParams := make(map[string]string)
for k, v := range c.Request.URL.Query() {
if len(v) > 0 {
queryParams[k] = v[0]
}
}
o2confRaw, has := singleton.Conf.Oauth2["Telegram"]
if !has {
return nil, singleton.Localizer.ErrorT("provider not found")
}
// 验证 Telegram Hash数据
if valid, err := verifyTelegramAuth(queryParams, o2confRaw.ClientID); err != nil {
return nil, err
} else if !valid {
return nil, singleton.Localizer.ErrorT("invalid Telegram auth data")
}
var bind model.Oauth2Bind
provider := "telegram"
openId := queryParams["id"]
u, authorized := c.Get(model.CtxKeyAuthorizedUser)
if authorized {
user := u.(*model.User)
result := singleton.DB.Where("provider = ? AND open_id = ?", provider, openId).Limit(1).Find(&bind)
if result.Error != nil && result.Error != gorm.ErrRecordNotFound {
return nil, newGormError("%v", result.Error)
}
bind.UserID = user.ID
bind.Provider = provider
bind.OpenID = openId
if result.Error == gorm.ErrRecordNotFound {
result = singleton.DB.Create(&bind)
} else {
result = singleton.DB.Save(&bind)
}
if result.Error != nil {
return nil, newGormError("%v", result.Error)
}
c.Redirect(http.StatusFound, "/dashboard/profile?oauth2=true")
} else {
if err := singleton.DB.Where("provider = ? AND open_id = ?", provider, openId).First(&bind).Error; err != nil {
return nil, singleton.Localizer.ErrorT("oauth2 user not binded yet")
}
tokenString, _, err := jwtConfig.TokenGenerator(fmt.Sprintf("%d", bind.UserID))
if err != nil {
return nil, err
}
jwtConfig.SetCookie(c, tokenString)
c.Redirect(http.StatusFound, "/dashboard/login?oauth2=true")
}
return nil, errNoop
}
// 其他 OAuth2 提供商的原有逻辑
callbackData := &model.Oauth2Callback{ callbackData := &model.Oauth2Callback{
State: c.Query("state"), State: c.Query("state"),
Code: c.Query("code"), Code: c.Query("code"),
@ -188,7 +258,68 @@ func oauth2callback(jwtConfig *jwt.GinJWTMiddleware) func(c *gin.Context) (any,
} }
} }
func verifyTelegramAuth(data map[string]string, botToken string) (bool, error) {
// 只保留需要验证的字段
requiredFields := []string{"id", "first_name", "last_name", "username", "photo_url", "auth_date"}
checkData := make(map[string]string)
// 只复制需要的字段
for _, field := range requiredFields {
if value, exists := data[field]; exists {
checkData[field] = value
}
}
var dataCheckString string
keys := make([]string, 0, len(checkData))
for k := range checkData {
if k != "hash" {
keys = append(keys, k)
}
}
sort.Strings(keys)
for _, k := range keys {
if len(dataCheckString) > 0 {
dataCheckString += "\n"
}
dataCheckString += fmt.Sprintf("%s=%s", k, checkData[k])
}
// 先对 bot token 进行 SHA256 哈希作为密钥
secretKeyHash := sha256.Sum256([]byte(botToken))
// 使用哈希后的密钥计算 HMAC
h := hmac.New(sha256.New, secretKeyHash[:])
h.Write([]byte(dataCheckString))
hash := hex.EncodeToString(h.Sum(nil))
return hash == data["hash"], nil
}
func exchangeOpenId(c *gin.Context, o2confRaw *model.Oauth2Config, callbackData *model.Oauth2Callback) (string, error) { func exchangeOpenId(c *gin.Context, o2confRaw *model.Oauth2Config, callbackData *model.Oauth2Callback) (string, error) {
// 处理Telegram Widget OAuth
if strings.ToLower(c.Param("provider")) == "telegram" {
// 解析查询参数
queryParams := make(map[string]string)
for k, v := range c.Request.URL.Query() {
if len(v) > 0 {
queryParams[k] = v[0]
}
}
// 验证数据
if valid, err := verifyTelegramAuth(queryParams, o2confRaw.ClientID); err != nil {
return "", err
} else if !valid {
return "", singleton.Localizer.ErrorT("invalid Telegram auth data")
}
// 返回Telegram用户ID
return queryParams["id"], nil
}
// 原有OAuth2处理逻辑
o2conf := o2confRaw.Setup(getRedirectURL(c)) o2conf := o2confRaw.Setup(getRedirectURL(c))
ctx := context.Background() ctx := context.Background()

Binary file not shown.

View File

@ -0,0 +1,306 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-31 21:25+0800\n"
"PO-Revision-Date: 2025-01-20 06:45+0000\n"
"Last-Translator: UUBulb <uub@kuzu.uk>\n"
"Language-Team: Tamil <https://hosted.weblate.org/projects/nezha/"
"nezha-dashboard/ta/>\n"
"Language: ta_IN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.10-dev\n"
#: cmd/dashboard/controller/alertrule.go:104
#, c-format
msgid "alert id %d does not exist"
msgstr "எச்சரிக்கை ஐடி %d இல்லை"
#: cmd/dashboard/controller/alertrule.go:108
#: cmd/dashboard/controller/alertrule.go:156
#: cmd/dashboard/controller/alertrule.go:176
#: cmd/dashboard/controller/controller.go:216
#: cmd/dashboard/controller/cron.go:58 cmd/dashboard/controller/cron.go:124
#: cmd/dashboard/controller/cron.go:136 cmd/dashboard/controller/cron.go:195
#: cmd/dashboard/controller/cron.go:224 cmd/dashboard/controller/ddns.go:131
#: cmd/dashboard/controller/ddns.go:192 cmd/dashboard/controller/fm.go:43
#: cmd/dashboard/controller/nat.go:59 cmd/dashboard/controller/nat.go:110
#: cmd/dashboard/controller/nat.go:121 cmd/dashboard/controller/nat.go:160
#: cmd/dashboard/controller/notification.go:112
#: cmd/dashboard/controller/notification.go:166
#: cmd/dashboard/controller/notification_group.go:76
#: cmd/dashboard/controller/notification_group.go:152
#: cmd/dashboard/controller/notification_group.go:164
#: cmd/dashboard/controller/notification_group.go:233
#: cmd/dashboard/controller/server.go:65 cmd/dashboard/controller/server.go:77
#: cmd/dashboard/controller/server.go:128
#: cmd/dashboard/controller/server.go:192
#: cmd/dashboard/controller/server_group.go:75
#: cmd/dashboard/controller/server_group.go:150
#: cmd/dashboard/controller/server_group.go:229
#: cmd/dashboard/controller/service.go:273
#: cmd/dashboard/controller/service.go:344
#: cmd/dashboard/controller/service.go:371
#: cmd/dashboard/controller/terminal.go:41
msgid "permission denied"
msgstr "இசைவு மறுக்கப்பட்டது"
#: cmd/dashboard/controller/alertrule.go:184
msgid "duration need to be at least 3"
msgstr "காலம் குறைந்தது 3 ஆக இருக்க வேண்டும்"
#: cmd/dashboard/controller/alertrule.go:188
msgid "cycle_interval need to be at least 1"
msgstr "cycle_interval குறைந்தது 1 ஆக இருக்க வேண்டும்"
#: cmd/dashboard/controller/alertrule.go:191
msgid "cycle_start is not set"
msgstr "cycle_start அமைக்கப்படவில்லை"
#: cmd/dashboard/controller/alertrule.go:194
msgid "cycle_start is a future value"
msgstr "cycle_start என்பது எதிர்கால மதிப்பு"
#: cmd/dashboard/controller/alertrule.go:199
msgid "need to configure at least a single rule"
msgstr "குறைந்தபட்சம் ஒரு விதியையாவது கட்டமைக்க வேண்டும்"
#: cmd/dashboard/controller/controller.go:210
#: cmd/dashboard/controller/oauth2.go:152
#: cmd/dashboard/controller/server_group.go:162
#: cmd/dashboard/controller/service.go:96 cmd/dashboard/controller/user.go:27
#: cmd/dashboard/controller/user.go:63
msgid "unauthorized"
msgstr "அங்கீகரிக்கப்படாதது"
#: cmd/dashboard/controller/controller.go:233
msgid "database error"
msgstr "தரவுத்தள பிழை"
#: cmd/dashboard/controller/cron.go:75 cmd/dashboard/controller/cron.go:149
msgid "scheduled tasks cannot be triggered by alarms"
msgstr "திட்டமிடப்பட்ட பணிகளை அலாரங்களால் தூண்ட முடியாது"
#: cmd/dashboard/controller/cron.go:132 cmd/dashboard/controller/cron.go:190
#, c-format
msgid "task id %d does not exist"
msgstr "பணி ஐடி %d இல்லை"
#: cmd/dashboard/controller/ddns.go:57 cmd/dashboard/controller/ddns.go:122
msgid "the retry count must be an integer between 1 and 10"
msgstr "மறுபயன்பாட்டு எண்ணிக்கை 1 முதல் 10 வரை ஒரு முழு எண்ணாக இருக்க வேண்டும்"
#: cmd/dashboard/controller/ddns.go:81 cmd/dashboard/controller/ddns.go:154
msgid "error parsing %s: %v"
msgstr "பிழை பாகுபடுத்தல் %s: %v"
#: cmd/dashboard/controller/ddns.go:127 cmd/dashboard/controller/nat.go:117
#, c-format
msgid "profile id %d does not exist"
msgstr "சுயவிவர ஐடி %d இல்லை"
#: cmd/dashboard/controller/fm.go:39 cmd/dashboard/controller/terminal.go:37
msgid "server not found or not connected"
msgstr "சேவையகம் கண்டுபிடிக்கப்படவில்லை அல்லது இணைக்கப்படவில்லை"
#: cmd/dashboard/controller/notification.go:69
#: cmd/dashboard/controller/notification.go:131
msgid "a test message"
msgstr "ஒரு சோதனை செய்தி"
#: cmd/dashboard/controller/notification.go:108
#, c-format
msgid "notification id %d does not exist"
msgstr "அறிவிப்பு ஐடி %d இல்லை"
#: cmd/dashboard/controller/notification_group.go:94
#: cmd/dashboard/controller/notification_group.go:175
msgid "have invalid notification id"
msgstr "தவறான அறிவிப்பு ஐடி உள்ளது"
#: cmd/dashboard/controller/notification_group.go:160
#: cmd/dashboard/controller/server_group.go:158
#, c-format
msgid "group id %d does not exist"
msgstr "குழு ஐடி %d இல்லை"
#: cmd/dashboard/controller/oauth2.go:42 cmd/dashboard/controller/oauth2.go:83
msgid "provider is required"
msgstr "வழங்குநர் தேவை"
#: cmd/dashboard/controller/oauth2.go:52 cmd/dashboard/controller/oauth2.go:87
#: cmd/dashboard/controller/oauth2.go:132
msgid "provider not found"
msgstr "வழங்குநர் கண்டுபிடிக்கப்படவில்லை"
#: cmd/dashboard/controller/oauth2.go:100
msgid "operation not permitted"
msgstr "செயல்பாடு அனுமதிக்கப்படவில்லை"
#: cmd/dashboard/controller/oauth2.go:138
msgid "code is required"
msgstr "குறியீடு தேவை"
#: cmd/dashboard/controller/oauth2.go:174
msgid "oauth2 user not binded yet"
msgstr "OAuth2 பயனர் இன்னும் பிணைக்கப்படவில்லை"
#: cmd/dashboard/controller/oauth2.go:215
#: cmd/dashboard/controller/oauth2.go:221
#: cmd/dashboard/controller/oauth2.go:226
msgid "invalid state key"
msgstr "தவறான மாநில விசை"
#: cmd/dashboard/controller/server.go:73
#, c-format
msgid "server id %d does not exist"
msgstr "சேவையக ஐடி %d இல்லை"
#: cmd/dashboard/controller/server_group.go:92
#: cmd/dashboard/controller/server_group.go:172
msgid "have invalid server id"
msgstr "தவறான சேவையக ஐடி உள்ளது"
#: cmd/dashboard/controller/service.go:89
#: cmd/dashboard/controller/service.go:165
msgid "server not found"
msgstr "சேவையகம் கிடைக்கவில்லை"
#: cmd/dashboard/controller/service.go:269
#, c-format
msgid "service id %d does not exist"
msgstr "சேவை ஐடி %d இல்லை"
#: cmd/dashboard/controller/user.go:68
msgid "incorrect password"
msgstr "தவறான கடவுச்சொல்"
#: cmd/dashboard/controller/user.go:82
msgid "you don't have any oauth2 bindings"
msgstr "உங்களிடம் OAuth2 பிணைப்புகள் எதுவும் இல்லை"
#: cmd/dashboard/controller/user.go:130
msgid "password length must be greater than 6"
msgstr "கடவுச்சொல் நீளம் 6 ஐ விட அதிகமாக இருக்க வேண்டும்"
#: cmd/dashboard/controller/user.go:133
msgid "username can't be empty"
msgstr "பயனர்பெயர் காலியாக இருக்க முடியாது"
#: cmd/dashboard/controller/user.go:136
msgid "invalid role"
msgstr "தவறான பங்கு"
#: cmd/dashboard/controller/user.go:175
msgid "can't delete yourself"
msgstr "உங்களை நீங்களே நீக்க முடியாது"
#: service/rpc/io_stream.go:128
msgid "timeout: no connection established"
msgstr "நேரம் முடிந்தது: எந்த தொடர்பும் நிறுவப்படவில்லை"
#: service/rpc/io_stream.go:131
msgid "timeout: user connection not established"
msgstr "நேரம் முடிந்தது: பயனர் இணைப்பு நிறுவப்படவில்லை"
#: service/rpc/io_stream.go:134
msgid "timeout: agent connection not established"
msgstr "நேரம் முடிந்தது: முகவர் இணைப்பு நிறுவப்படவில்லை"
#: service/rpc/nezha.go:69
msgid "Scheduled Task Executed Successfully"
msgstr "திட்டமிடப்பட்ட பணி வெற்றிகரமாக செயல்படுத்தப்பட்டது"
#: service/rpc/nezha.go:73
msgid "Scheduled Task Executed Failed"
msgstr "திட்டமிடப்பட்ட பணி செயல்படுத்தப்பட்டது தோல்வியடைந்தது"
#: service/rpc/nezha.go:245
msgid "IP Changed"
msgstr "ஐபி மாற்றப்பட்டது"
#: service/singleton/alertsentinel.go:170
msgid "Incident"
msgstr "நிகழ்வு"
#: service/singleton/alertsentinel.go:180
msgid "Resolved"
msgstr "தீர்க்கப்பட்டது"
#: service/singleton/crontask.go:54
msgid "Tasks failed to register: ["
msgstr "பணிகள் பதிவு செய்யத் தவறிவிட்டன: ["
#: service/singleton/crontask.go:61
msgid ""
"] These tasks will not execute properly. Fix them in the admin dashboard."
msgstr ""
"] இந்த பணிகள் சரியாக இயங்காது. நிர்வாக டாச்போர்டில் அவற்றை சரிசெய்யவும்."
#: service/singleton/crontask.go:144 service/singleton/crontask.go:169
#, c-format
msgid "[Task failed] %s: server %s is offline and cannot execute the task"
msgstr ""
"[பணி தோல்வியுற்றது] %s: சேவையகம் %s இணைப்பில்லாத மற்றும் பணியை செயல்படுத்த முடியாது"
#: service/singleton/servicesentinel.go:468
#, c-format
msgid "[Latency] %s %2f > %2f, Reporter: %s"
msgstr "[தாமதம்] %s %2f> %2f, நிருபர்: %s"
#: service/singleton/servicesentinel.go:475
#, c-format
msgid "[Latency] %s %2f < %2f, Reporter: %s"
msgstr "[தாமதம்] %s %2f < %2f, நிருபர்: %s"
#: service/singleton/servicesentinel.go:501
#, c-format
msgid "[%s] %s Reporter: %s, Error: %s"
msgstr "[ %s] %s நிருபர்: %s, பிழை: %s"
#: service/singleton/servicesentinel.go:544
#, c-format
msgid "[TLS] Fetch cert info failed, Reporter: %s, Error: %s"
msgstr "[TLS] சான்றிதழ் செய்தி தோல்வியுற்றது, நிருபர்: %s, பிழை: %s"
#: service/singleton/servicesentinel.go:584
#, c-format
msgid "The TLS certificate will expire within seven days. Expiration time: %s"
msgstr "டி.எல்.எச் சான்றிதழ் ஏழு நாட்களுக்குள் காலாவதியாகும். காலாவதி நேரம்: %s"
#: service/singleton/servicesentinel.go:597
#, c-format
msgid ""
"TLS certificate changed, old: issuer %s, expires at %s; new: issuer %s, "
"expires at %s"
msgstr ""
"டி.எல்.எச் சான்றிதழ் மாற்றப்பட்டது, பழையது: வழங்குபவர் %s, %s காலாவதியாகின்றன; புதியது:"
" வழங்குபவர் %s, %s இல் காலாவதியாகின்றன"
#: service/singleton/servicesentinel.go:633
msgid "No Data"
msgstr "தரவு இல்லை"
#: service/singleton/servicesentinel.go:635
msgid "Good"
msgstr "நல்லது"
#: service/singleton/servicesentinel.go:637
msgid "Low Availability"
msgstr "குறைந்த கிடைக்கும் தன்மை"
#: service/singleton/servicesentinel.go:639
msgid "Down"
msgstr "கீழே"
#: service/singleton/user.go:60
msgid "user id not specified"
msgstr "பயனர் ஐடி குறிப்பிடப்படவில்லை"

View File

@ -2,20 +2,20 @@
name: "OfficialAdmin" name: "OfficialAdmin"
repository: "https://github.com/nezhahq/admin-frontend" repository: "https://github.com/nezhahq/admin-frontend"
author: "nezhahq" author: "nezhahq"
version: "v1.5.13" version: "v1.6.0"
isadmin: true isadmin: true
isofficial: true isofficial: true
- path: "user-dist" - path: "user-dist"
name: "Official" name: "Official"
repository: "https://github.com/hamster1963/nezha-dash-v1" repository: "https://github.com/hamster1963/nezha-dash-v1"
author: "hamster1963" author: "hamster1963"
version: "v1.13.0" version: "v1.13.1"
isofficial: true isofficial: true
- path: "nezha-ascii-dist" - path: "nezha-ascii-dist"
name: "Nezha-ASCII" name: "Nezha-ASCII"
repository: "https://github.com/hamster1963/nezha-ascii" repository: "https://github.com/hamster1963/nezha-ascii"
author: "hamster1963" author: "hamster1963"
version: "v1.0.0" version: "v1.0.1"
- path: "nazhua-dist" - path: "nazhua-dist"
name: "Nazhua" name: "Nazhua"
repository: "https://github.com/hi2shark/nazhua" repository: "https://github.com/hi2shark/nazhua"