add: API Token相关的前端页面
This commit is contained in:
parent
fcd0ccae56
commit
914d7cbbae
@ -57,18 +57,21 @@ func (ma *memberAPI) serve() {
|
|||||||
|
|
||||||
type apiResult struct {
|
type apiResult struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
|
Note string `json:"note"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// getToken 获取 Token
|
// getToken 获取 Token
|
||||||
func (ma *memberAPI) getToken(c *gin.Context) {
|
func (ma *memberAPI) getToken(c *gin.Context) {
|
||||||
u := c.MustGet(model.CtxKeyAuthorizedUser).(*model.User)
|
u := c.MustGet(model.CtxKeyAuthorizedUser).(*model.User)
|
||||||
singleton.ApiLock.RLock()
|
singleton.ApiLock.RLock()
|
||||||
|
defer singleton.ApiLock.RUnlock()
|
||||||
|
|
||||||
tokenList := singleton.UserIDToApiTokenList[u.ID]
|
tokenList := singleton.UserIDToApiTokenList[u.ID]
|
||||||
singleton.ApiLock.RUnlock()
|
|
||||||
res := make([]*apiResult, len(tokenList))
|
res := make([]*apiResult, len(tokenList))
|
||||||
for i, token := range tokenList {
|
for i, token := range tokenList {
|
||||||
res[i] = &apiResult{
|
res[i] = &apiResult{
|
||||||
Token: token,
|
Token: token,
|
||||||
|
Note: singleton.ApiTokenList[token].Note,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
@ -78,12 +81,26 @@ func (ma *memberAPI) getToken(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TokenForm struct {
|
||||||
|
Note string
|
||||||
|
}
|
||||||
|
|
||||||
// issueNewToken 生成新的 token
|
// issueNewToken 生成新的 token
|
||||||
func (ma *memberAPI) issueNewToken(c *gin.Context) {
|
func (ma *memberAPI) issueNewToken(c *gin.Context) {
|
||||||
u := c.MustGet(model.CtxKeyAuthorizedUser).(*model.User)
|
u := c.MustGet(model.CtxKeyAuthorizedUser).(*model.User)
|
||||||
|
tf := &TokenForm{}
|
||||||
|
err := c.ShouldBindJSON(tf)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Response{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
Message: fmt.Sprintf("请求错误:%s", err),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
token := &model.ApiToken{
|
token := &model.ApiToken{
|
||||||
UserID: u.ID,
|
UserID: u.ID,
|
||||||
Token: utils.MD5(fmt.Sprintf("%d%d%s", time.Now().UnixNano(), u.ID, u.Login)),
|
Token: utils.MD5(fmt.Sprintf("%d%d%s", time.Now().UnixNano(), u.ID, u.Login)),
|
||||||
|
Note: tf.Note,
|
||||||
}
|
}
|
||||||
singleton.DB.Create(token)
|
singleton.DB.Create(token)
|
||||||
|
|
||||||
@ -97,6 +114,7 @@ func (ma *memberAPI) issueNewToken(c *gin.Context) {
|
|||||||
Message: "success",
|
Message: "success",
|
||||||
Result: map[string]string{
|
Result: map[string]string{
|
||||||
"token": token.Token,
|
"token": token.Token,
|
||||||
|
"note": token.Note,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,16 @@ func (mp *memberPage) serve() {
|
|||||||
mr.GET("/cron", mp.cron)
|
mr.GET("/cron", mp.cron)
|
||||||
mr.GET("/notification", mp.notification)
|
mr.GET("/notification", mp.notification)
|
||||||
mr.GET("/setting", mp.setting)
|
mr.GET("/setting", mp.setting)
|
||||||
|
mr.GET("/api", mp.api)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mp *memberPage) api(c *gin.Context) {
|
||||||
|
singleton.ApiLock.RLock()
|
||||||
|
defer singleton.ApiLock.RUnlock()
|
||||||
|
c.HTML(http.StatusOK, "dashboard/api", mygin.CommonEnvironment(c, gin.H{
|
||||||
|
"title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ApiManagement"}),
|
||||||
|
"Tokens": singleton.ApiTokenList,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mp *memberPage) server(c *gin.Context) {
|
func (mp *memberPage) server(c *gin.Context) {
|
||||||
|
@ -4,4 +4,5 @@ type ApiToken struct {
|
|||||||
Common
|
Common
|
||||||
UserID uint64 `json:"user_id"`
|
UserID uint64 `json:"user_id"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
|
Note string `json:"note"`
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ var adminPage = map[string]bool{
|
|||||||
"/setting": true,
|
"/setting": true,
|
||||||
"/notification": true,
|
"/notification": true,
|
||||||
"/cron": true,
|
"/cron": true,
|
||||||
|
"/api": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func CommonEnvironment(c *gin.Context, data map[string]interface{}) gin.H {
|
func CommonEnvironment(c *gin.Context, data map[string]interface{}) gin.H {
|
||||||
|
15
resource/l10n/en-US.toml
vendored
15
resource/l10n/en-US.toml
vendored
@ -469,6 +469,21 @@ other = "Services"
|
|||||||
[ScheduledTasks]
|
[ScheduledTasks]
|
||||||
other = "Scheduled Tasks"
|
other = "Scheduled Tasks"
|
||||||
|
|
||||||
|
[ApiManagement]
|
||||||
|
other="API"
|
||||||
|
|
||||||
|
[IssueNewApiToken]
|
||||||
|
other="Create Token"
|
||||||
|
|
||||||
|
[Token]
|
||||||
|
other="Token"
|
||||||
|
|
||||||
|
[DeleteToken]
|
||||||
|
other="Delete Token"
|
||||||
|
|
||||||
|
[ConfirmToDeleteThisToken]
|
||||||
|
other="Confirm Delete?"
|
||||||
|
|
||||||
[YouAreNotAuthorized]
|
[YouAreNotAuthorized]
|
||||||
other = "You are not authorized"
|
other = "You are not authorized"
|
||||||
|
|
||||||
|
15
resource/l10n/es-ES.toml
vendored
15
resource/l10n/es-ES.toml
vendored
@ -469,6 +469,21 @@ other = "Monitorización del servicio"
|
|||||||
[ScheduledTasks]
|
[ScheduledTasks]
|
||||||
other = "Tareas programadas"
|
other = "Tareas programadas"
|
||||||
|
|
||||||
|
[ApiManagement]
|
||||||
|
other="API"
|
||||||
|
|
||||||
|
[IssueNewApiToken]
|
||||||
|
other="Create Token"
|
||||||
|
|
||||||
|
[Token]
|
||||||
|
other="Token"
|
||||||
|
|
||||||
|
[DeleteToken]
|
||||||
|
other="Delete Token"
|
||||||
|
|
||||||
|
[ConfirmToDeleteThisToken]
|
||||||
|
other="Confirm Delete?"
|
||||||
|
|
||||||
[YouAreNotAuthorized]
|
[YouAreNotAuthorized]
|
||||||
other = "Esta página requiere un acceso"
|
other = "Esta página requiere un acceso"
|
||||||
|
|
||||||
|
15
resource/l10n/zh-CN.toml
vendored
15
resource/l10n/zh-CN.toml
vendored
@ -469,6 +469,21 @@ other = "服务监控"
|
|||||||
[ScheduledTasks]
|
[ScheduledTasks]
|
||||||
other = "计划任务"
|
other = "计划任务"
|
||||||
|
|
||||||
|
[ApiManagement]
|
||||||
|
other="API"
|
||||||
|
|
||||||
|
[IssueNewApiToken]
|
||||||
|
other="添加Token"
|
||||||
|
|
||||||
|
[Token]
|
||||||
|
other="Token"
|
||||||
|
|
||||||
|
[DeleteToken]
|
||||||
|
other="删除Token"
|
||||||
|
|
||||||
|
[ConfirmToDeleteThisToken]
|
||||||
|
other="确认删除Token"
|
||||||
|
|
||||||
[YouAreNotAuthorized]
|
[YouAreNotAuthorized]
|
||||||
other = "此页面需要登录"
|
other = "此页面需要登录"
|
||||||
|
|
||||||
|
@ -202,6 +202,18 @@ function post(path, params, method = 'post') {
|
|||||||
document.body.removeChild(form);
|
document.body.removeChild(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function issueNewApiToken(apiToken) {
|
||||||
|
const modal = $(".api.modal");
|
||||||
|
modal.children(".header").text((apiToken ? LANG.Edit : LANG.Add) + ' ' + "API Token");
|
||||||
|
modal
|
||||||
|
.find(".nezha-primary-btn.button")
|
||||||
|
.html(
|
||||||
|
apiToken ? LANG.Edit + '<i class="edit icon"></i>' : LANG.Add + '<i class="add icon"></i>'
|
||||||
|
);
|
||||||
|
modal.find("textarea[name=Note]").val(apiToken ? apiToken.Note : null);
|
||||||
|
showFormModal(".api.modal", "#apiForm", "/api/token");
|
||||||
|
}
|
||||||
|
|
||||||
function addOrEditServer(server, conf) {
|
function addOrEditServer(server, conf) {
|
||||||
const modal = $(".server.modal");
|
const modal = $(".server.modal");
|
||||||
modal.children(".header").text((server ? LANG.Edit : LANG.Add) + ' ' + LANG.Server);
|
modal.children(".header").text((server ? LANG.Edit : LANG.Add) + ' ' + LANG.Server);
|
||||||
|
1
resource/template/common/menu.html
vendored
1
resource/template/common/menu.html
vendored
@ -9,6 +9,7 @@
|
|||||||
<a class='item{{if eq .MatchedPath "/monitor"}} active{{end}}' href="/monitor"><i class="rss icon"></i>{{tr "Services"}}</a>
|
<a class='item{{if eq .MatchedPath "/monitor"}} active{{end}}' href="/monitor"><i class="rss icon"></i>{{tr "Services"}}</a>
|
||||||
<a class='item{{if eq .MatchedPath "/cron"}} active{{end}}' href="/cron"><i class="clock icon"></i>{{tr "Task"}}</a>
|
<a class='item{{if eq .MatchedPath "/cron"}} active{{end}}' href="/cron"><i class="clock icon"></i>{{tr "Task"}}</a>
|
||||||
<a class='item{{if eq .MatchedPath "/notification"}} active{{end}}' href="/notification"><i class="bell icon"></i>{{tr "Notification"}}</a>
|
<a class='item{{if eq .MatchedPath "/notification"}} active{{end}}' href="/notification"><i class="bell icon"></i>{{tr "Notification"}}</a>
|
||||||
|
<a class='item{{if eq .MatchedPath "/api"}} active{{end}}' href="/api"><i class="key icon"></i>API</a>
|
||||||
<a class='item{{if eq .MatchedPath "/setting"}} active{{end}}' href="/setting">
|
<a class='item{{if eq .MatchedPath "/setting"}} active{{end}}' href="/setting">
|
||||||
<i class="settings icon"></i>{{tr "Settings"}}
|
<i class="settings icon"></i>{{tr "Settings"}}
|
||||||
</a>
|
</a>
|
||||||
|
19
resource/template/component/api.html
vendored
Normal file
19
resource/template/component/api.html
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{{define "component/api"}}
|
||||||
|
<div class="ui tiny api modal transition hidden">
|
||||||
|
<div class="header">{{tr "IssueNewApiToken"}}</div>
|
||||||
|
<div class="content">
|
||||||
|
<form id="apiForm" class="ui form">
|
||||||
|
<input type="hidden" name="id">
|
||||||
|
<div class="field">
|
||||||
|
<label>{{tr "Note"}}</label>
|
||||||
|
<textarea name="Note"></textarea>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class=" actions">
|
||||||
|
<div class="ui negative button">{{tr "Cancel"}}</div>
|
||||||
|
<button class="ui positive nezha-primary-btn right labeled icon button">{{tr "Confirm"}}<i class="checkmark icon"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
41
resource/template/dashboard/api.html
Normal file
41
resource/template/dashboard/api.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{{define "dashboard/api"}}
|
||||||
|
{{template "common/header" .}}
|
||||||
|
{{template "common/menu" .}}
|
||||||
|
<div class="nb-container">
|
||||||
|
<div class="ui container">
|
||||||
|
<div class="ui grid">
|
||||||
|
<div class="right floated right aligned twelve wide column">
|
||||||
|
<button class="ui right labeled nezha-primary-btn icon button" onclick="issueNewApiToken()"><i class="add icon"></i>
|
||||||
|
{{tr "IssueNewApiToken"}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table class="ui very basic table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{tr "Token"}}</th>
|
||||||
|
<th>{{tr "Note"}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{range $token := .Tokens}}
|
||||||
|
<tr>
|
||||||
|
<td>{{$token.Token}}</td>
|
||||||
|
<td>{{$token.Note}}</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui mini icon buttons">
|
||||||
|
<button class="ui button"
|
||||||
|
onclick="showConfirm('{{tr "DeleteToken"}}','{{tr "ConfirmToDeleteThisToken"}}',deleteRequest,'/api/token/'+{{$token.Token}})">
|
||||||
|
<i class="trash alternate outline icon"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{template "component/api"}}
|
||||||
|
{{template "common/footer" .}}
|
||||||
|
{{end}}
|
Loading…
Reference in New Issue
Block a user