add simple audit hook base logic

pull/385/head
Michael Li 10 months ago
parent 8ee4ff7e8d
commit c922361ccf
No known key found for this signature in database

@ -383,6 +383,8 @@ release/paopao serve --no-default-features --features sqlite3,localoss,loggerfil
|[`Pyroscope`](docs/proposal/23021510-关于使用pyroscope用于性能调试的设计.md)| 性能优化 | 内测 | 开启Pyroscope功能用于性能调试 |
|[`Pprof`](docs/proposal/23062905-添加Pprof功能特性用于获取Profile.md)| 性能优化 | 内测 | 开启Pprof功能收集Profile信息 |
|`PhoneBind` | 其他 | 稳定 | 手机绑定功能 |
|`UseAuditHook` | 其他 | 内测 | 使用审核hook功能 |
|`UseJobManager` | 其他 | 内测 | 使用JobManager功能 |
|`Web:DisallowUserRegister` | 功能特性 | 稳定 | 不允许用户注册 |
> 功能项状态详情参考 [features-status](features-status.md).

@ -44,8 +44,20 @@ type Priv interface {
mustEmbedUnimplementedPrivServant()
}
type PrivChain interface {
ChainCreateTweet() gin.HandlersChain
mustEmbedUnimplementedPrivChain()
}
// RegisterPrivServant register Priv servant to gin
func RegisterPrivServant(e *gin.Engine, s Priv) {
func RegisterPrivServant(e *gin.Engine, s Priv, m ...PrivChain) {
var cc PrivChain
if len(m) > 0 {
cc = m[0]
} else {
cc = &UnimplementedPrivChain{}
}
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
@ -297,7 +309,7 @@ func RegisterPrivServant(e *gin.Engine, s Priv) {
}
s.Render(c, nil, s.DeleteTweet(req))
})
router.Handle("POST", "/post", func(c *gin.Context) {
router.Handle("POST", "/post", append(cc.ChainCreateTweet(), func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
@ -310,8 +322,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv) {
return
}
resp, err := s.CreateTweet(req)
s.Render(c, resp, err)
})
if err != nil {
s.Render(c, nil, err)
return
}
var rv _render_ = resp
rv.Render(c)
})...)
router.Handle("GET", "/attachment", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
@ -455,3 +472,12 @@ func (UnimplementedPrivServant) UploadAttachment(req *web.UploadAttachmentReq) (
}
func (UnimplementedPrivServant) mustEmbedUnimplementedPrivServant() {}
// UnimplementedPrivChain can be embedded to have forward compatible implementations.
type UnimplementedPrivChain struct{}
func (b *UnimplementedPrivChain) ChainCreateTweet() gin.HandlersChain {
return nil
}
func (b *UnimplementedPrivChain) mustEmbedUnimplementedPrivChain() {}

@ -196,7 +196,17 @@
* `PhoneBind` 手机绑定功能;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* [x] 业务逻辑实现
* `UseAuditHook` 使用审核hook功能 (目前状态: 内测 待完善后将转为Builtin)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `UseJobManager` 使用JobManager功能 (目前状态: 内测 待完善后将转为Builtin)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
### 功能特性:
* `Web:DisallowUserRegister` 不允许用户注册;

@ -18,7 +18,7 @@ var (
func Initial() {
_onceInitial.Do(func() {
initEventManager()
if cfg.If("JobManager") {
if cfg.If("UseJobManager") {
initJobManager()
logrus.Debugln("initial JobManager")
}

@ -0,0 +1,39 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package web
const (
AuditStyleUnknown AuditStyle = iota
AuditStyleUserTweet
AuditStyleUserTweetComment
AuditStyleUserTweetReply
)
const (
AuditHookCtxKey = "audit_ctx_key"
)
type AuditStyle uint8
type AuditMetaInfo struct {
Style AuditStyle
Id int64
}
func (s AuditStyle) String() (res string) {
switch s {
case AuditStyleUserTweet:
res = "UserTweet"
case AuditStyleUserTweetComment:
res = "UserTweetComment"
case AuditStyleUserTweetReply:
res = "UserTweetReply"
case AuditStyleUnknown:
fallthrough
default:
res = "Unknown"
}
return
}

@ -7,12 +7,14 @@ package web
import (
"fmt"
"mime/multipart"
"net/http"
"strings"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/ms"
"github.com/rocboss/paopao-ce/internal/model/joint"
"github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/pkg/convert"
"github.com/rocboss/paopao-ce/pkg/xerror"
@ -281,3 +283,16 @@ func (r *CreateCommentReq) Bind(c *gin.Context) mir.Error {
r.ClientIP = c.ClientIP()
return bindAny(c, r)
}
func (r *CreateTweetResp) Render(c *gin.Context) {
c.JSON(http.StatusOK, &joint.JsonResp{
Code: 0,
Msg: "success",
Data: r,
})
// 设置审核元信息,用于接下来的审核逻辑
c.Set(AuditHookCtxKey, &AuditMetaInfo{
Style: AuditStyleUserTweet,
Id: r.ID,
})
}

@ -0,0 +1,25 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package chain
import (
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
func AuditHook() gin.HandlerFunc {
return func(c *gin.Context) {
// 此midleware后面是真正的http handlder让handler先执行
c.Next()
// 审核hook 后处理逻辑
var ami *web.AuditMetaInfo
if val, ok := c.Get(web.AuditHookCtxKey); ok {
if ami, ok = val.(*web.AuditMetaInfo); !ok {
return
}
}
OnAudiotHookEvent(ami)
}
}

@ -0,0 +1,35 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package chain
import (
"github.com/alimy/tryst/event"
"github.com/rocboss/paopao-ce/internal/events"
"github.com/rocboss/paopao-ce/internal/model/web"
"github.com/sirupsen/logrus"
)
type AuditHookEvent struct {
event.UnimplementedEvent
ami *web.AuditMetaInfo
}
func (e *AuditHookEvent) Name() string {
return "AuditHookEvent"
}
func (e *AuditHookEvent) Action() error {
// TODO: just log event now will add real logic in future.
logrus.Debugf("auditHook event action style[%s] id[%d]", e.ami.Style, e.ami.Id)
return nil
}
func OnAudiotHookEvent(ami *web.AuditMetaInfo) {
if ami != nil {
events.OnEvent(&AuditHookEvent{
ami: ami,
})
}
}

@ -10,6 +10,7 @@ import (
"time"
"github.com/alimy/mir/v4"
"github.com/alimy/tryst/cfg"
"github.com/disintegration/imaging"
"github.com/gin-gonic/gin"
"github.com/gofrs/uuid/v5"
@ -27,7 +28,8 @@ import (
)
var (
_ api.Priv = (*privSrv)(nil)
_ api.Priv = (*privSrv)(nil)
_ api.PrivChain = (*privChain)(nil)
_uploadAttachmentTypeMap = map[string]ms.AttachmentType{
"public/image": ms.AttachmentTypeImage,
@ -35,12 +37,6 @@ var (
"public/video": ms.AttachmentTypeVideo,
"attachment": ms.AttachmentTypeOther,
}
_uploadAttachmentTypes = map[string]cs.AttachmentType{
"public/image": cs.AttachmentTypeImage,
"public/avatar": cs.AttachmentTypeImage,
"public/video": cs.AttachmentTypeVideo,
"attachment": cs.AttachmentTypeOther,
}
)
type privSrv struct {
@ -50,6 +46,17 @@ type privSrv struct {
oss core.ObjectStorageService
}
type privChain struct {
api.UnimplementedPrivChain
}
func (s *privChain) ChainCreateTweet() (res gin.HandlersChain) {
if cfg.If("UseAuditHook") {
res = gin.HandlersChain{chain.AuditHook()}
}
return
}
func (s *privSrv) Chain() gin.HandlersChain {
return gin.HandlersChain{chain.JWT(), chain.Priv()}
}
@ -846,3 +853,7 @@ func newPrivSrv(s *base.DaoServant, oss core.ObjectStorageService) api.Priv {
oss: oss,
}
}
func newPrivChain() api.PrivChain {
return &privChain{}
}

@ -36,7 +36,7 @@ func RouteWeb(e *gin.Engine) {
api.RegisterCoreServant(e, newCoreSrv(ds, _oss, _wc))
api.RegisterRelaxServant(e, newRelaxSrv(ds, _wc))
api.RegisterLooseServant(e, newLooseSrv(ds, _ac))
api.RegisterPrivServant(e, newPrivSrv(ds, _oss))
api.RegisterPrivServant(e, newPrivSrv(ds, _oss), newPrivChain())
api.RegisterPubServant(e, newPubSrv(ds))
api.RegisterFollowshipServant(e, newFollowshipSrv(ds))
api.RegisterFriendshipServant(e, newFriendshipSrv(ds))

@ -25,7 +25,7 @@ type Priv struct {
DownloadAttachment func(Get, web.DownloadAttachmentReq) web.DownloadAttachmentResp `mir:"/attachment"`
// CreateTweet 发布动态
CreateTweet func(Post, web.CreateTweetReq) web.CreateTweetResp `mir:"/post"`
CreateTweet func(Post, Chain, web.CreateTweetReq) web.CreateTweetResp `mir:"/post"`
// DeleteTweet 删除动态
DeleteTweet func(Delete, web.DeleteTweetReq) `mir:"/post"`

Loading…
Cancel
Save