fix: block interactions on unpublished content

This commit is contained in:
2026-01-12 09:55:11 +08:00
parent 810c5a52a5
commit 5031df86f4

View File

@@ -157,21 +157,8 @@ func (s *content) Get(ctx context.Context, tenantID, userID, id int64) (*content
return nil, errorx.ErrDatabaseError.WithCause(err)
}
// 未发布内容仅允许作者或租户管理员查看。
if item.Status != consts.ContentStatusPublished {
if userID == 0 {
return nil, errorx.ErrForbidden.WithMsg("内容未发布")
}
if item.UserID != userID {
exists, _ := models.TenantUserQuery.WithContext(ctx).
Where(models.TenantUserQuery.TenantID.Eq(item.TenantID),
models.TenantUserQuery.UserID.Eq(userID),
models.TenantUserQuery.Role.Contains(types.Array[consts.TenantUserRole]{consts.TenantUserRoleTenantAdmin})).
Exists()
if !exists {
return nil, errorx.ErrForbidden.WithMsg("内容未发布")
}
}
if err := s.ensureContentReadable(ctx, userID, &item); err != nil {
return nil, err
}
// Increment Views
@@ -263,16 +250,19 @@ func (s *content) Get(ctx context.Context, tenantID, userID, id int64) (*content
}
func (s *content) ListComments(ctx context.Context, tenantID, userID, id int64, page int) (*requests.Pager, error) {
contentQuery := models.ContentQuery.WithContext(ctx).Where(models.ContentQuery.ID.Eq(id))
if tenantID > 0 {
_, err := models.ContentQuery.WithContext(ctx).
Where(models.ContentQuery.ID.Eq(id), models.ContentQuery.TenantID.Eq(tenantID)).
First()
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errorx.ErrRecordNotFound
}
return nil, errorx.ErrDatabaseError.WithCause(err)
contentQuery = contentQuery.Where(models.ContentQuery.TenantID.Eq(tenantID))
}
content, err := contentQuery.First()
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errorx.ErrRecordNotFound
}
return nil, errorx.ErrDatabaseError.WithCause(err)
}
if err := s.ensureContentReadable(ctx, userID, content); err != nil {
return nil, err
}
tbl, q := models.CommentQuery.QueryContext(ctx)
@@ -354,6 +344,9 @@ func (s *content) CreateComment(
if err != nil {
return errorx.ErrRecordNotFound
}
if err := s.ensureContentReadable(ctx, userID, c); err != nil {
return err
}
comment := &models.Comment{
TenantID: c.TenantID,
@@ -384,6 +377,20 @@ func (s *content) LikeComment(ctx context.Context, tenantID, userID, id int64) e
if err != nil {
return errorx.ErrRecordNotFound
}
contentQuery := models.ContentQuery.WithContext(ctx).Where(models.ContentQuery.ID.Eq(cm.ContentID))
if tenantID > 0 {
contentQuery = contentQuery.Where(models.ContentQuery.TenantID.Eq(tenantID))
}
c, err := contentQuery.First()
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errorx.ErrRecordNotFound
}
return errorx.ErrDatabaseError.WithCause(err)
}
if err := s.ensureContentReadable(ctx, userID, c); err != nil {
return err
}
err = models.Q.Transaction(func(tx *models.Query) error {
exists, _ := tx.UserCommentAction.WithContext(ctx).
@@ -610,6 +617,31 @@ func (s *content) toContentItemDTO(item *models.Content, price float64, authorIs
return dto
}
func (s *content) ensureContentReadable(ctx context.Context, userID int64, item *models.Content) error {
if item.Status == consts.ContentStatusPublished {
return nil
}
// 未发布内容仅允许作者或租户管理员查看。
if userID == 0 {
return errorx.ErrForbidden.WithMsg("内容未发布")
}
if item.UserID == userID {
return nil
}
exists, err := models.TenantUserQuery.WithContext(ctx).
Where(models.TenantUserQuery.TenantID.Eq(item.TenantID),
models.TenantUserQuery.UserID.Eq(userID),
models.TenantUserQuery.Role.Contains(types.Array[consts.TenantUserRole]{consts.TenantUserRoleTenantAdmin})).
Exists()
if err != nil {
return errorx.ErrDatabaseError.WithCause(err)
}
if !exists {
return errorx.ErrForbidden.WithMsg("内容未发布")
}
return nil
}
func (s *content) toMediaURLs(assets []*models.ContentAsset) []content_dto.MediaURL {
var urls []content_dto.MediaURL
for _, ca := range assets {
@@ -637,11 +669,14 @@ func (s *content) addInteract(ctx context.Context, tenantID, userID, contentId i
query = query.Where(models.ContentQuery.TenantID.Eq(tenantID))
}
c, err := query.
Select(models.ContentQuery.UserID, models.ContentQuery.Title).
Select(models.ContentQuery.UserID, models.ContentQuery.Title, models.ContentQuery.Status, models.ContentQuery.TenantID).
First()
if err != nil {
return errorx.ErrRecordNotFound
}
if err := s.ensureContentReadable(ctx, userID, c); err != nil {
return err
}
err = models.Q.Transaction(func(tx *models.Query) error {
exists, _ := tx.UserContentAction.WithContext(ctx).