feat: now user are able to configure channels
This commit is contained in:
+14
-14
@@ -40,9 +40,9 @@ func TokenStoreInit() {
|
|||||||
}
|
}
|
||||||
if user.WeChatCorpAccountId != "" {
|
if user.WeChatCorpAccountId != "" {
|
||||||
item := &WeChatCorpAccountTokenStoreItem{
|
item := &WeChatCorpAccountTokenStoreItem{
|
||||||
CorpId: user.WeChatCorpAccountId,
|
CorpId: user.WeChatCorpAccountId,
|
||||||
CorpSecret: user.WeChatCorpAccountSecret,
|
AgentSecret: user.WeChatCorpAccountAgentSecret,
|
||||||
AgentId: user.WeChatCorpAccountAgentId,
|
AgentId: user.WeChatCorpAccountAgentId,
|
||||||
}
|
}
|
||||||
items = append(items, item)
|
items = append(items, item)
|
||||||
}
|
}
|
||||||
@@ -121,21 +121,21 @@ func TokenStoreUpdateUser(cleanUser *model.User, originUser *model.User) {
|
|||||||
if cleanUser.WeChatCorpAccountAgentId == originUser.WeChatCorpAccountAgentId {
|
if cleanUser.WeChatCorpAccountAgentId == originUser.WeChatCorpAccountAgentId {
|
||||||
cleanUser.WeChatCorpAccountAgentId = ""
|
cleanUser.WeChatCorpAccountAgentId = ""
|
||||||
}
|
}
|
||||||
if cleanUser.WeChatCorpAccountSecret == originUser.WeChatCorpAccountSecret {
|
if cleanUser.WeChatCorpAccountAgentSecret == originUser.WeChatCorpAccountAgentSecret {
|
||||||
cleanUser.WeChatCorpAccountSecret = ""
|
cleanUser.WeChatCorpAccountAgentSecret = ""
|
||||||
}
|
}
|
||||||
if cleanUser.WeChatCorpAccountId != "" || cleanUser.WeChatCorpAccountAgentId != "" || cleanUser.WeChatCorpAccountSecret != "" {
|
if cleanUser.WeChatCorpAccountId != "" || cleanUser.WeChatCorpAccountAgentId != "" || cleanUser.WeChatCorpAccountAgentSecret != "" {
|
||||||
oldWeChatCorpAccountTokenStoreItem := WeChatCorpAccountTokenStoreItem{
|
oldWeChatCorpAccountTokenStoreItem := WeChatCorpAccountTokenStoreItem{
|
||||||
CorpId: cleanUser.WeChatCorpAccountId,
|
CorpId: cleanUser.WeChatCorpAccountId,
|
||||||
CorpSecret: cleanUser.WeChatCorpAccountSecret,
|
AgentSecret: cleanUser.WeChatCorpAccountAgentSecret,
|
||||||
AgentId: cleanUser.WeChatCorpAccountAgentId,
|
AgentId: cleanUser.WeChatCorpAccountAgentId,
|
||||||
}
|
}
|
||||||
newWeChatCorpAccountTokenStoreItem := oldWeChatCorpAccountTokenStoreItem
|
newWeChatCorpAccountTokenStoreItem := oldWeChatCorpAccountTokenStoreItem
|
||||||
if cleanUser.WeChatCorpAccountId != "" {
|
if cleanUser.WeChatCorpAccountId != "" {
|
||||||
newWeChatCorpAccountTokenStoreItem.CorpId = cleanUser.WeChatCorpAccountId
|
newWeChatCorpAccountTokenStoreItem.CorpId = cleanUser.WeChatCorpAccountId
|
||||||
}
|
}
|
||||||
if cleanUser.WeChatCorpAccountSecret != "" {
|
if cleanUser.WeChatCorpAccountAgentSecret != "" {
|
||||||
newWeChatCorpAccountTokenStoreItem.CorpSecret = cleanUser.WeChatCorpAccountSecret
|
newWeChatCorpAccountTokenStoreItem.AgentSecret = cleanUser.WeChatCorpAccountAgentSecret
|
||||||
}
|
}
|
||||||
if cleanUser.WeChatCorpAccountAgentId != "" {
|
if cleanUser.WeChatCorpAccountAgentId != "" {
|
||||||
newWeChatCorpAccountTokenStoreItem.AgentId = cleanUser.WeChatCorpAccountAgentId
|
newWeChatCorpAccountTokenStoreItem.AgentId = cleanUser.WeChatCorpAccountAgentId
|
||||||
@@ -157,9 +157,9 @@ func TokenStoreRemoveUser(user *model.User) {
|
|||||||
TokenStoreRemoveItem(&testAccountTokenStoreItem)
|
TokenStoreRemoveItem(&testAccountTokenStoreItem)
|
||||||
}
|
}
|
||||||
corpAccountTokenStoreItem := WeChatCorpAccountTokenStoreItem{
|
corpAccountTokenStoreItem := WeChatCorpAccountTokenStoreItem{
|
||||||
CorpId: user.WeChatCorpAccountId,
|
CorpId: user.WeChatCorpAccountId,
|
||||||
CorpSecret: user.WeChatCorpAccountSecret,
|
AgentSecret: user.WeChatCorpAccountAgentSecret,
|
||||||
AgentId: user.WeChatCorpAccountAgentId,
|
AgentId: user.WeChatCorpAccountAgentId,
|
||||||
}
|
}
|
||||||
if !corpAccountTokenStoreItem.IsShared() {
|
if !corpAccountTokenStoreItem.IsShared() {
|
||||||
TokenStoreRemoveItem(&corpAccountTokenStoreItem)
|
TokenStoreRemoveItem(&corpAccountTokenStoreItem)
|
||||||
|
|||||||
@@ -20,18 +20,18 @@ type wechatCorpAccountResponse struct {
|
|||||||
|
|
||||||
type WeChatCorpAccountTokenStoreItem struct {
|
type WeChatCorpAccountTokenStoreItem struct {
|
||||||
CorpId string
|
CorpId string
|
||||||
CorpSecret string
|
AgentSecret string
|
||||||
AgentId string
|
AgentId string
|
||||||
AccessToken string
|
AccessToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *WeChatCorpAccountTokenStoreItem) Key() string {
|
func (i *WeChatCorpAccountTokenStoreItem) Key() string {
|
||||||
return i.CorpId + i.AgentId + i.CorpSecret
|
return i.CorpId + i.AgentId + i.AgentSecret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *WeChatCorpAccountTokenStoreItem) IsShared() bool {
|
func (i *WeChatCorpAccountTokenStoreItem) IsShared() bool {
|
||||||
return model.DB.Where("wechat_corp_account_id = ? and wechat_corp_account_secret = ? and wechat_corp_account_agent_id = ?",
|
return model.DB.Where("wechat_corp_account_id = ? and wechat_corp_account_agent_secret = ? and wechat_corp_account_agent_id = ?",
|
||||||
i.CorpId, i.CorpSecret, i.AgentId).Find(&model.User{}).RowsAffected != 1
|
i.CorpId, i.AgentSecret, i.AgentId).Find(&model.User{}).RowsAffected != 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *WeChatCorpAccountTokenStoreItem) Token() string {
|
func (i *WeChatCorpAccountTokenStoreItem) Token() string {
|
||||||
@@ -44,7 +44,7 @@ func (i *WeChatCorpAccountTokenStoreItem) Refresh() {
|
|||||||
Timeout: 5 * time.Second,
|
Timeout: 5 * time.Second,
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest("GET", fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s",
|
req, err := http.NewRequest("GET", fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s",
|
||||||
i.CorpId, i.CorpSecret), nil)
|
i.CorpId, i.AgentSecret), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SysError(err.Error())
|
common.SysError(err.Error())
|
||||||
return
|
return
|
||||||
@@ -119,7 +119,7 @@ func SendWeChatCorpMessage(message *Message, user *model.User) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf("%s%s%s", user.WeChatCorpAccountId, user.WeChatCorpAccountAgentId, user.WeChatCorpAccountSecret)
|
key := fmt.Sprintf("%s%s%s", user.WeChatCorpAccountId, user.WeChatCorpAccountAgentId, user.WeChatCorpAccountAgentSecret)
|
||||||
accessToken := TokenStoreGetToken(key)
|
accessToken := TokenStoreGetToken(key)
|
||||||
resp, err := http.Post(fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s", accessToken), "application/json",
|
resp, err := http.Post(fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s", accessToken), "application/json",
|
||||||
bytes.NewBuffer(jsonData))
|
bytes.NewBuffer(jsonData))
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ func GetPushMessage(c *gin.Context) {
|
|||||||
// Keep compatible with ServerChan
|
// Keep compatible with ServerChan
|
||||||
message.Description = c.Query("desp")
|
message.Description = c.Query("desp")
|
||||||
}
|
}
|
||||||
|
if message.Channel == "" {
|
||||||
|
// Keep compatible with old version
|
||||||
|
message.Channel = c.Query("type")
|
||||||
|
}
|
||||||
pushMessageHelper(c, &message)
|
pushMessageHelper(c, &message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"message-pusher/common"
|
"message-pusher/common"
|
||||||
"message-pusher/model"
|
"message-pusher/model"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetStatus(c *gin.Context) {
|
func GetStatus(c *gin.Context) {
|
||||||
@@ -167,3 +171,23 @@ func ResetPassword(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WeChatTestAccountVerification(c *gin.Context) {
|
||||||
|
user := model.User{Username: c.Param("username")}
|
||||||
|
user.FillUserByUsername()
|
||||||
|
// https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
|
||||||
|
signature := c.Query("signature")
|
||||||
|
timestamp := c.Query("timestamp")
|
||||||
|
nonce := c.Query("nonce")
|
||||||
|
echoStr := c.Query("echostr")
|
||||||
|
arr := []string{user.WeChatTestAccountVerificationToken, timestamp, nonce}
|
||||||
|
sort.Strings(arr)
|
||||||
|
str := strings.Join(arr, "")
|
||||||
|
hash := sha1.Sum([]byte(str))
|
||||||
|
hexStr := hex.EncodeToString(hash[:])
|
||||||
|
if signature == hexStr {
|
||||||
|
c.String(http.StatusOK, echoStr)
|
||||||
|
} else {
|
||||||
|
c.Status(http.StatusForbidden)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+13
-3
@@ -342,8 +342,15 @@ func UpdateUser(c *gin.Context) {
|
|||||||
if updatedUser.Password == "$I_LOVE_U" {
|
if updatedUser.Password == "$I_LOVE_U" {
|
||||||
updatedUser.Password = "" // rollback to what it should be
|
updatedUser.Password = "" // rollback to what it should be
|
||||||
}
|
}
|
||||||
updatePassword := updatedUser.Password != ""
|
// We only allow admin change those fields.
|
||||||
if err := updatedUser.Update(updatePassword); err != nil {
|
cleanUser := model.User{
|
||||||
|
Id: updatedUser.Id,
|
||||||
|
Username: updatedUser.Username,
|
||||||
|
Password: updatedUser.Password,
|
||||||
|
DisplayName: updatedUser.DisplayName,
|
||||||
|
}
|
||||||
|
updatePassword := cleanUser.Password != ""
|
||||||
|
if err := cleanUser.Update(updatePassword); err != nil {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
@@ -389,13 +396,16 @@ func UpdateSelf(c *gin.Context) {
|
|||||||
Id: c.GetInt("id"),
|
Id: c.GetInt("id"),
|
||||||
Username: user.Username,
|
Username: user.Username,
|
||||||
Password: user.Password,
|
Password: user.Password,
|
||||||
|
DisplayName: user.DisplayName,
|
||||||
|
Token: user.Token,
|
||||||
|
Channel: user.Channel,
|
||||||
WeChatTestAccountId: user.WeChatTestAccountId,
|
WeChatTestAccountId: user.WeChatTestAccountId,
|
||||||
WeChatTestAccountSecret: user.WeChatTestAccountSecret,
|
WeChatTestAccountSecret: user.WeChatTestAccountSecret,
|
||||||
WeChatTestAccountTemplateId: user.WeChatTestAccountTemplateId,
|
WeChatTestAccountTemplateId: user.WeChatTestAccountTemplateId,
|
||||||
WeChatTestAccountOpenId: user.WeChatTestAccountOpenId,
|
WeChatTestAccountOpenId: user.WeChatTestAccountOpenId,
|
||||||
WeChatTestAccountVerificationToken: user.WeChatTestAccountVerificationToken,
|
WeChatTestAccountVerificationToken: user.WeChatTestAccountVerificationToken,
|
||||||
WeChatCorpAccountId: user.WeChatCorpAccountId,
|
WeChatCorpAccountId: user.WeChatCorpAccountId,
|
||||||
WeChatCorpAccountSecret: user.WeChatCorpAccountSecret,
|
WeChatCorpAccountAgentSecret: user.WeChatCorpAccountAgentSecret,
|
||||||
WeChatCorpAccountAgentId: user.WeChatCorpAccountAgentId,
|
WeChatCorpAccountAgentId: user.WeChatCorpAccountAgentId,
|
||||||
WeChatCorpAccountUserId: user.WeChatCorpAccountUserId,
|
WeChatCorpAccountUserId: user.WeChatCorpAccountUserId,
|
||||||
WeChatCorpAccountClientType: user.WeChatCorpAccountClientType,
|
WeChatCorpAccountClientType: user.WeChatCorpAccountClientType,
|
||||||
|
|||||||
+10
-4
@@ -15,7 +15,7 @@ type User struct {
|
|||||||
DisplayName string `json:"display_name" gorm:"index" validate:"max=20"`
|
DisplayName string `json:"display_name" gorm:"index" validate:"max=20"`
|
||||||
Role int `json:"role" gorm:"type:int;default:1"` // admin, common
|
Role int `json:"role" gorm:"type:int;default:1"` // admin, common
|
||||||
Status int `json:"status" gorm:"type:int;default:1"` // enabled, disabled
|
Status int `json:"status" gorm:"type:int;default:1"` // enabled, disabled
|
||||||
Token string `json:"token" gorm:"index"`
|
Token string `json:"token"`
|
||||||
Email string `json:"email" gorm:"index" validate:"max=50"`
|
Email string `json:"email" gorm:"index" validate:"max=50"`
|
||||||
GitHubId string `json:"github_id" gorm:"column:github_id;index"`
|
GitHubId string `json:"github_id" gorm:"column:github_id;index"`
|
||||||
WeChatId string `json:"wechat_id" gorm:"column:wechat_id;index"`
|
WeChatId string `json:"wechat_id" gorm:"column:wechat_id;index"`
|
||||||
@@ -27,10 +27,10 @@ type User struct {
|
|||||||
WeChatTestAccountOpenId string `json:"wechat_test_account_open_id" gorm:"column:wechat_test_account_open_id"`
|
WeChatTestAccountOpenId string `json:"wechat_test_account_open_id" gorm:"column:wechat_test_account_open_id"`
|
||||||
WeChatTestAccountVerificationToken string `json:"wechat_test_account_verification_token" gorm:"column:wechat_test_account_verification_token"`
|
WeChatTestAccountVerificationToken string `json:"wechat_test_account_verification_token" gorm:"column:wechat_test_account_verification_token"`
|
||||||
WeChatCorpAccountId string `json:"wechat_corp_account_id" gorm:"column:wechat_corp_account_id"`
|
WeChatCorpAccountId string `json:"wechat_corp_account_id" gorm:"column:wechat_corp_account_id"`
|
||||||
WeChatCorpAccountSecret string `json:"wechat_corp_account_secret" gorm:"column:wechat_corp_account_secret"`
|
WeChatCorpAccountAgentSecret string `json:"wechat_corp_account_agent_secret" gorm:"column:wechat_corp_account_agent_secret"`
|
||||||
WeChatCorpAccountAgentId string `json:"wechat_corp_account_agent_id" gorm:"column:wechat_corp_account_agent_id"`
|
WeChatCorpAccountAgentId string `json:"wechat_corp_account_agent_id" gorm:"column:wechat_corp_account_agent_id"`
|
||||||
WeChatCorpAccountUserId string `json:"wechat_corp_account_user_id" gorm:"column:wechat_corp_account_user_id"`
|
WeChatCorpAccountUserId string `json:"wechat_corp_account_user_id" gorm:"column:wechat_corp_account_user_id"`
|
||||||
WeChatCorpAccountClientType string `json:"wechat_corp_account_client_type" gorm:"wechat_corp_account_client_type;default=plugin"`
|
WeChatCorpAccountClientType string `json:"wechat_corp_account_client_type" gorm:"column:wechat_corp_account_client_type;default=plugin"`
|
||||||
LarkWebhookURL string `json:"lark_webhook_url"`
|
LarkWebhookURL string `json:"lark_webhook_url"`
|
||||||
LarkWebhookSecret string `json:"lark_webhook_secret"`
|
LarkWebhookSecret string `json:"lark_webhook_secret"`
|
||||||
DingWebhookURL string `json:"ding_webhook_url"`
|
DingWebhookURL string `json:"ding_webhook_url"`
|
||||||
@@ -64,7 +64,13 @@ func GetUserById(id int, selectAll bool) (*User, error) {
|
|||||||
if selectAll {
|
if selectAll {
|
||||||
err = DB.First(&user, "id = ?", id).Error
|
err = DB.First(&user, "id = ?", id).Error
|
||||||
} else {
|
} else {
|
||||||
err = DB.Select([]string{"id", "username", "display_name", "role", "status", "email", "wechat_id", "github_id"}).First(&user, "id = ?", id).Error
|
err = DB.Select([]string{"id", "username", "display_name", "role", "status", "email", "wechat_id", "github_id",
|
||||||
|
"channel", "token",
|
||||||
|
"wechat_test_account_id", "wechat_test_account_template_id", "wechat_test_account_open_id",
|
||||||
|
"wechat_corp_account_id", "wechat_corp_account_agent_id", "wechat_corp_account_user_id", "wechat_corp_account_client_type",
|
||||||
|
"lark_webhook_url",
|
||||||
|
"ding_webhook_url",
|
||||||
|
}).First(&user, "id = ?", id).Error
|
||||||
}
|
}
|
||||||
return &user, err
|
return &user, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ func SetApiRouter(router *gin.Engine) {
|
|||||||
apiRouter.GET("/status", controller.GetStatus)
|
apiRouter.GET("/status", controller.GetStatus)
|
||||||
apiRouter.GET("/notice", controller.GetNotice)
|
apiRouter.GET("/notice", controller.GetNotice)
|
||||||
apiRouter.GET("/about", controller.GetAbout)
|
apiRouter.GET("/about", controller.GetAbout)
|
||||||
|
apiRouter.GET("/wechat_test_account_verification/:username", controller.WeChatTestAccountVerification)
|
||||||
apiRouter.GET("/verification", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendEmailVerification)
|
apiRouter.GET("/verification", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendEmailVerification)
|
||||||
apiRouter.GET("/reset_password", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendPasswordResetEmail)
|
apiRouter.GET("/reset_password", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendPasswordResetEmail)
|
||||||
apiRouter.POST("/user/reset", middleware.CriticalRateLimit(), controller.ResetPassword)
|
apiRouter.POST("/user/reset", middleware.CriticalRateLimit(), controller.ResetPassword)
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ const PersonalSetting = () => {
|
|||||||
<Button as={Link} to={`/user/edit/`}>
|
<Button as={Link} to={`/user/edit/`}>
|
||||||
更新个人信息
|
更新个人信息
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={generateToken}>生成访问令牌</Button>
|
{/*<Button onClick={generateToken}>生成访问令牌</Button>*/}
|
||||||
<Divider />
|
<Divider />
|
||||||
<Header as='h3'>账号绑定</Header>
|
<Header as='h3'>账号绑定</Header>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -0,0 +1,384 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Divider,
|
||||||
|
Form,
|
||||||
|
Grid,
|
||||||
|
Header,
|
||||||
|
Message,
|
||||||
|
} from 'semantic-ui-react';
|
||||||
|
import { API, showError, showSuccess } from '../helpers';
|
||||||
|
|
||||||
|
const PushSetting = () => {
|
||||||
|
let [inputs, setInputs] = useState({
|
||||||
|
id: '',
|
||||||
|
username: '',
|
||||||
|
channel: '',
|
||||||
|
token: '',
|
||||||
|
wechat_test_account_id: '',
|
||||||
|
wechat_test_account_secret: '',
|
||||||
|
wechat_test_account_template_id: '',
|
||||||
|
wechat_test_account_open_id: '',
|
||||||
|
wechat_test_account_verification_token: '',
|
||||||
|
wechat_corp_account_id: '',
|
||||||
|
wechat_corp_account_agent_secret: '',
|
||||||
|
wechat_corp_account_agent_id: '',
|
||||||
|
wechat_corp_account_user_id: '',
|
||||||
|
wechat_corp_account_client_type: '',
|
||||||
|
lark_webhook_url: '',
|
||||||
|
lark_webhook_secret: '',
|
||||||
|
ding_webhook_url: '',
|
||||||
|
ding_webhook_secret: '',
|
||||||
|
});
|
||||||
|
let [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const handleInputChange = (e, { name, value }) => {
|
||||||
|
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadUser = async () => {
|
||||||
|
let res = await API.get(`/api/user/self`);
|
||||||
|
const { success, message, data } = res.data;
|
||||||
|
if (success) {
|
||||||
|
if (data.channel === '') {
|
||||||
|
data.channel = 'email';
|
||||||
|
}
|
||||||
|
if (data.wechat_corp_account_client_type === '') {
|
||||||
|
data.wechat_corp_account_client_type = 'plugin';
|
||||||
|
}
|
||||||
|
if (data.token === ' ') {
|
||||||
|
data.token = '';
|
||||||
|
}
|
||||||
|
setInputs(data);
|
||||||
|
} else {
|
||||||
|
showError(message);
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadUser().then();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const submit = async (which) => {
|
||||||
|
let data = {};
|
||||||
|
switch (which) {
|
||||||
|
case 'general':
|
||||||
|
data.channel = inputs.channel;
|
||||||
|
data.token = inputs.token;
|
||||||
|
if (data.token === '') {
|
||||||
|
data.token = ' ';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'test':
|
||||||
|
data.wechat_test_account_id = inputs.wechat_test_account_id;
|
||||||
|
data.wechat_test_account_secret = inputs.wechat_test_account_secret;
|
||||||
|
data.wechat_test_account_template_id =
|
||||||
|
inputs.wechat_test_account_template_id;
|
||||||
|
data.wechat_test_account_open_id = inputs.wechat_test_account_open_id;
|
||||||
|
data.wechat_test_account_verification_token =
|
||||||
|
inputs.wechat_test_account_verification_token;
|
||||||
|
break;
|
||||||
|
case 'corp':
|
||||||
|
data.wechat_corp_account_id = inputs.wechat_corp_account_id;
|
||||||
|
data.wechat_corp_account_agent_secret =
|
||||||
|
inputs.wechat_corp_account_agent_secret;
|
||||||
|
data.wechat_corp_account_agent_id = inputs.wechat_corp_account_agent_id;
|
||||||
|
data.wechat_corp_account_user_id = inputs.wechat_corp_account_user_id;
|
||||||
|
data.wechat_corp_account_client_type =
|
||||||
|
inputs.wechat_corp_account_client_type;
|
||||||
|
break;
|
||||||
|
case 'lark':
|
||||||
|
data.lark_webhook_url = inputs.lark_webhook_url;
|
||||||
|
data.lark_webhook_secret = inputs.lark_webhook_secret;
|
||||||
|
break;
|
||||||
|
case 'ding':
|
||||||
|
data.ding_webhook_url = inputs.ding_webhook_url;
|
||||||
|
data.ding_webhook_secret = inputs.ding_webhook_secret;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
showError(`无效的参数:${which}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let res = await API.put(`/api/user/self`, data);
|
||||||
|
const { success, message } = res.data;
|
||||||
|
if (success) {
|
||||||
|
showSuccess('设置已更新!');
|
||||||
|
} else {
|
||||||
|
showError(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const test = async (type) => {
|
||||||
|
let res = await API.get(
|
||||||
|
`/push/${inputs.username}?token=${inputs.token}&channel=${type}&title=消息推送服务&description=配置成功!`
|
||||||
|
);
|
||||||
|
const { success, message } = res.data;
|
||||||
|
if (success) {
|
||||||
|
showSuccess('测试消息已发送');
|
||||||
|
} else {
|
||||||
|
showError(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid columns={1}>
|
||||||
|
<Grid.Column>
|
||||||
|
<Form loading={loading}>
|
||||||
|
<Header as='h3'>通用设置</Header>
|
||||||
|
<Message>注意:密钥类配置信息不会发送到前端显示。</Message>
|
||||||
|
<Form.Group widths={3}>
|
||||||
|
<Form.Select
|
||||||
|
label='默认推送方式'
|
||||||
|
name='channel'
|
||||||
|
options={[
|
||||||
|
{ key: 'email', text: '邮件', value: 'email' },
|
||||||
|
{ key: 'test', text: '微信测试号', value: 'test' },
|
||||||
|
{ key: 'corp', text: '企业微信', value: 'corp' },
|
||||||
|
{ key: 'lark', text: '飞书群机器人', value: 'lark' },
|
||||||
|
{ key: 'ding', text: '钉钉群机器人', value: 'ding' },
|
||||||
|
]}
|
||||||
|
value={inputs.channel}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
<Form.Input
|
||||||
|
label='推送 token'
|
||||||
|
placeholder='未设置则不检查 token'
|
||||||
|
value={inputs.token}
|
||||||
|
name='token'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Button onClick={() => submit('general')} loading={loading}>
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => test('')}>测试</Button>
|
||||||
|
<Divider />
|
||||||
|
<Header as='h3'>
|
||||||
|
邮箱设置(email)
|
||||||
|
<Header.Subheader>通过邮件进行推送</Header.Subheader>
|
||||||
|
</Header>
|
||||||
|
<Message>
|
||||||
|
邮件推送方式(email)需要设置邮箱,请前往个人设置页面绑定邮箱地址。
|
||||||
|
</Message>
|
||||||
|
<Button onClick={() => test('email')}>测试</Button>
|
||||||
|
<Divider />
|
||||||
|
<Header as='h3'>
|
||||||
|
微信测试号设置(test)
|
||||||
|
<Header.Subheader>
|
||||||
|
通过微信测试号进行推送,点击前往配置:
|
||||||
|
<a
|
||||||
|
target='_blank'
|
||||||
|
href='https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index'
|
||||||
|
>
|
||||||
|
微信公众平台接口测试帐号
|
||||||
|
</a>
|
||||||
|
</Header.Subheader>
|
||||||
|
</Header>
|
||||||
|
<Message>
|
||||||
|
接口配置信息中的 URL 填写:
|
||||||
|
<code>{`${window.location.origin}/api/wechat_test_account_verification/${inputs.username}`}</code>
|
||||||
|
<br />
|
||||||
|
Token 填一个随机字符串,然后填入下方的「接口配置验证 Token」中。
|
||||||
|
</Message>
|
||||||
|
<Form.Group widths={3}>
|
||||||
|
<Form.Input
|
||||||
|
label='测试号 ID'
|
||||||
|
name='wechat_test_account_id'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.wechat_test_account_id}
|
||||||
|
placeholder='测试号信息 -> appID'
|
||||||
|
/>
|
||||||
|
<Form.Input
|
||||||
|
label='测试号密钥'
|
||||||
|
name='wechat_test_account_secret'
|
||||||
|
type='password'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.wechat_test_account_secret}
|
||||||
|
placeholder='测试号信息 -> appsecret'
|
||||||
|
/>
|
||||||
|
<Form.Input
|
||||||
|
label='测试模板 ID'
|
||||||
|
name='wechat_test_account_template_id'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.wechat_test_account_template_id}
|
||||||
|
placeholder='模板消息接口 -> 模板 ID'
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Form.Group widths={3}>
|
||||||
|
<Form.Input
|
||||||
|
label='用户 Open ID'
|
||||||
|
name='wechat_test_account_open_id'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.wechat_test_account_open_id}
|
||||||
|
placeholder='测试号二维码 -> 用户列表 -> 微信号'
|
||||||
|
/>
|
||||||
|
<Form.Input
|
||||||
|
label='接口配置验证 Token'
|
||||||
|
name='wechat_test_account_verification_token'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
type='password'
|
||||||
|
value={inputs.wechat_test_account_verification_token}
|
||||||
|
placeholder='接口配置信息 -> Token'
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Button onClick={() => submit('test')} loading={loading}>
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => test('test')}>测试</Button>
|
||||||
|
<Divider />
|
||||||
|
<Header as='h3'>
|
||||||
|
企业微信设置(corp)
|
||||||
|
<Header.Subheader>
|
||||||
|
通过企业微信进行推送,点击前往配置:
|
||||||
|
<a
|
||||||
|
target='_blank'
|
||||||
|
href='https://work.weixin.qq.com/wework_admin/frame#apps'
|
||||||
|
>
|
||||||
|
企业微信应用管理
|
||||||
|
</a>
|
||||||
|
</Header.Subheader>
|
||||||
|
</Header>
|
||||||
|
<Form.Group widths={3}>
|
||||||
|
<Form.Input
|
||||||
|
label='企业 ID'
|
||||||
|
name='wechat_corp_account_id'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.wechat_corp_account_id}
|
||||||
|
placeholder='我的企业 -> 企业信息 -> 企业 ID'
|
||||||
|
/>
|
||||||
|
<Form.Input
|
||||||
|
label='应用 AgentId'
|
||||||
|
name='wechat_corp_account_agent_id'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.wechat_corp_account_agent_id}
|
||||||
|
placeholder='应用管理 -> 自建 -> 创建应用 -> AgentId'
|
||||||
|
/>
|
||||||
|
<Form.Input
|
||||||
|
label='应用 Secret'
|
||||||
|
name='wechat_corp_account_agent_secret'
|
||||||
|
type='password'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.wechat_corp_account_agent_secret}
|
||||||
|
placeholder='应用管理 -> 自建 -> 创建应用 -> Secret'
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Form.Group widths={3}>
|
||||||
|
<Form.Input
|
||||||
|
label='用户账号'
|
||||||
|
name='wechat_corp_account_user_id'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.wechat_corp_account_user_id}
|
||||||
|
placeholder='通讯录 -> 点击姓名 -> 账号'
|
||||||
|
/>
|
||||||
|
<Form.Select
|
||||||
|
label='微信企业号客户端类型'
|
||||||
|
name='wechat_corp_account_client_type'
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
key: 'plugin',
|
||||||
|
text: '微信中的企业微信插件',
|
||||||
|
value: 'plugin',
|
||||||
|
},
|
||||||
|
{ key: 'app', text: '企业微信 APP', value: 'app' },
|
||||||
|
]}
|
||||||
|
value={inputs.wechat_corp_account_client_type}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Button onClick={() => submit('corp')} loading={loading}>
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => test('corp')}>测试</Button>
|
||||||
|
<Divider />
|
||||||
|
<Header as='h3'>
|
||||||
|
飞书设置(lark)
|
||||||
|
<Header.Subheader>
|
||||||
|
通过飞书群机器人进行推送,选择一个群聊 -> 设置 -> 群机器人 ->
|
||||||
|
添加机器人 -> 自定义机器人 -> 添加(
|
||||||
|
<strong>注意选中「签名校验」</strong>)。具体参见:
|
||||||
|
<a
|
||||||
|
target='_blank'
|
||||||
|
href='https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN'
|
||||||
|
>
|
||||||
|
飞书开放文档
|
||||||
|
</a>
|
||||||
|
</Header.Subheader>
|
||||||
|
</Header>
|
||||||
|
<Form.Group widths={2}>
|
||||||
|
<Form.Input
|
||||||
|
label='Webhook 地址'
|
||||||
|
name='lark_webhook_url'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.lark_webhook_url}
|
||||||
|
placeholder='在此填写飞书提供的 Webhook 地址'
|
||||||
|
/>
|
||||||
|
<Form.Input
|
||||||
|
label='签名校验密钥'
|
||||||
|
name='lark_webhook_secret'
|
||||||
|
type='password'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.lark_webhook_secret}
|
||||||
|
placeholder='在此填写飞书提供的签名校验密钥'
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Button onClick={() => submit('lark')} loading={loading}>
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => test('lark')}>测试</Button>
|
||||||
|
<Divider />
|
||||||
|
<Header as='h3'>
|
||||||
|
钉钉设置(ding)
|
||||||
|
<Header.Subheader>
|
||||||
|
通过钉钉机器人进行推送,选择一个群聊 -> 群设置 -> 智能群助手 ->
|
||||||
|
添加机器人(点击右侧齿轮图标) -> 自定义 -> 添加(
|
||||||
|
<strong>注意选中「加密」</strong>)。具体参见:
|
||||||
|
<a
|
||||||
|
target='_blank'
|
||||||
|
href='https://open.dingtalk.com/document/robots/custom-robot-access'
|
||||||
|
>
|
||||||
|
钉钉开放文档
|
||||||
|
</a>
|
||||||
|
</Header.Subheader>
|
||||||
|
</Header>
|
||||||
|
<Form.Group widths={2}>
|
||||||
|
<Form.Input
|
||||||
|
label='Webhook 地址'
|
||||||
|
name='ding_webhook_url'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.ding_webhook_url}
|
||||||
|
placeholder='在此填写钉钉提供的 Webhook 地址'
|
||||||
|
/>
|
||||||
|
<Form.Input
|
||||||
|
label='签名校验密钥'
|
||||||
|
name='ding_webhook_secret'
|
||||||
|
type='password'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.ding_webhook_secret}
|
||||||
|
placeholder='在此填写钉钉提供的签名校验密钥'
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Button onClick={() => submit('ding')} loading={loading}>
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => test('ding')}>测试</Button>
|
||||||
|
</Form>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PushSetting;
|
||||||
@@ -4,6 +4,7 @@ import SystemSetting from '../../components/SystemSetting';
|
|||||||
import { isRoot } from '../../helpers';
|
import { isRoot } from '../../helpers';
|
||||||
import OtherSetting from '../../components/OtherSetting';
|
import OtherSetting from '../../components/OtherSetting';
|
||||||
import PersonalSetting from '../../components/PersonalSetting';
|
import PersonalSetting from '../../components/PersonalSetting';
|
||||||
|
import PushSetting from '../../components/PushSetting';
|
||||||
|
|
||||||
const Setting = () => {
|
const Setting = () => {
|
||||||
let panes = [
|
let panes = [
|
||||||
@@ -13,8 +14,16 @@ const Setting = () => {
|
|||||||
<Tab.Pane attached={false}>
|
<Tab.Pane attached={false}>
|
||||||
<PersonalSetting />
|
<PersonalSetting />
|
||||||
</Tab.Pane>
|
</Tab.Pane>
|
||||||
)
|
),
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
menuItem: '推送设置',
|
||||||
|
render: () => (
|
||||||
|
<Tab.Pane attached={false}>
|
||||||
|
<PushSetting />
|
||||||
|
</Tab.Pane>
|
||||||
|
),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isRoot()) {
|
if (isRoot()) {
|
||||||
@@ -24,7 +33,7 @@ const Setting = () => {
|
|||||||
<Tab.Pane attached={false}>
|
<Tab.Pane attached={false}>
|
||||||
<SystemSetting />
|
<SystemSetting />
|
||||||
</Tab.Pane>
|
</Tab.Pane>
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
panes.push({
|
panes.push({
|
||||||
menuItem: '其他设置',
|
menuItem: '其他设置',
|
||||||
@@ -32,7 +41,7 @@ const Setting = () => {
|
|||||||
<Tab.Pane attached={false}>
|
<Tab.Pane attached={false}>
|
||||||
<OtherSetting />
|
<OtherSetting />
|
||||||
</Tab.Pane>
|
</Tab.Pane>
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user