chore: 合入 stash Ops hardening 与 migration 000041
Ask/catalog 权限与审计加固、量表读权限统一,以及未提交的 ops hardening 变更。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/google/uuid"
|
||||
@@ -10,7 +11,7 @@ import (
|
||||
"github.com/yuxingu/digital-psychology/apps/api/internal/repository"
|
||||
)
|
||||
|
||||
// AskSessionDetail is AskSessionView plus messages.
|
||||
// AskSessionDetail is AskSessionView plus messages (transcript).
|
||||
type AskSessionDetail struct {
|
||||
repository.AskSessionView
|
||||
Messages []repository.AskMessageView `json:"messages"`
|
||||
@@ -30,8 +31,20 @@ func (s *Service) ListAskSessions(ctx context.Context, userID *uuid.UUID, limit,
|
||||
return items, nil
|
||||
}
|
||||
|
||||
// GetAskSessionDetail loads meta + messages.
|
||||
func (s *Service) GetAskSessionDetail(ctx context.Context, threadID uuid.UUID) (*AskSessionDetail, error) {
|
||||
// GetAskSessionMeta loads thread meta without message bodies.
|
||||
func (s *Service) GetAskSessionMeta(ctx context.Context, threadID uuid.UUID) (*repository.AskSessionView, error) {
|
||||
view, err := s.Repo.GetAskSession(ctx, threadID)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, ErrAskThreadNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return view, nil
|
||||
}
|
||||
|
||||
// GetAskSessionTranscript loads message bodies and audits access.
|
||||
func (s *Service) GetAskSessionTranscript(ctx context.Context, adminID, threadID uuid.UUID) (*AskSessionDetail, error) {
|
||||
view, err := s.Repo.GetAskSession(ctx, threadID)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, ErrAskThreadNotFound
|
||||
@@ -46,5 +59,10 @@ func (s *Service) GetAskSessionDetail(ctx context.Context, threadID uuid.UUID) (
|
||||
if msgs == nil {
|
||||
msgs = []repository.AskMessageView{}
|
||||
}
|
||||
meta, _ := json.Marshal(map[string]any{
|
||||
"message_count": len(msgs),
|
||||
"user_id": view.UserID.String(),
|
||||
})
|
||||
_ = s.Repo.InsertAudit(ctx, adminID, "ask.transcript.read", "ask_thread", threadID.String(), meta)
|
||||
return &AskSessionDetail{AskSessionView: *view, Messages: msgs}, nil
|
||||
}
|
||||
|
||||
@@ -10,9 +10,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrBadFeedbackRating = errString("rating must be 1-5")
|
||||
ErrBadFeedbackTag = errString("invalid tag")
|
||||
ErrFeedbackNoteLong = errString("note too long")
|
||||
ErrBadFeedbackRating = errString("rating must be 1-5")
|
||||
ErrBadFeedbackTag = errString("invalid tag")
|
||||
ErrFeedbackNoteLong = errString("note too long")
|
||||
ErrMessageNotInThread = errString("message not in thread")
|
||||
)
|
||||
|
||||
// ListQualityFeedback lists recent QualityFeedback.
|
||||
@@ -54,6 +55,8 @@ func (s *Service) CreateQualityFeedback(
|
||||
return nil, ErrFeedbackNoteLong
|
||||
case strings.Contains(msg, "thread not found"):
|
||||
return nil, ErrAskThreadNotFound
|
||||
case strings.Contains(msg, "message not in thread"):
|
||||
return nil, ErrMessageNotInThread
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ const (
|
||||
PermMembershipCodesRead = "admin.membership.codes.read"
|
||||
PermMembershipCodesWrite = "admin.membership.codes.write"
|
||||
PermAskRead = "admin.ask.read"
|
||||
PermAskTranscriptRead = "admin.ask.transcript.read"
|
||||
PermAskFeedbackWrite = "admin.ask.feedback.write"
|
||||
PermContentSafetyRead = "admin.content_safety.read"
|
||||
PermAIConfigRead = "admin.ai_config.read"
|
||||
@@ -41,7 +42,7 @@ var knownPermissions = map[string]struct{}{
|
||||
PermContentWrite: {}, PermRolesRead: {}, PermRolesWrite: {},
|
||||
PermUsersStatusWrite: {}, PermMembershipPlansRead: {}, PermMembershipPlansWrite: {},
|
||||
PermMembershipCodesRead: {}, PermMembershipCodesWrite: {},
|
||||
PermAskRead: {}, PermAskFeedbackWrite: {}, PermContentSafetyRead: {},
|
||||
PermAskRead: {}, PermAskTranscriptRead: {}, PermAskFeedbackWrite: {}, PermContentSafetyRead: {},
|
||||
PermAIConfigRead: {}, PermCrisisRead: {}, PermCMSRead: {}, PermGrowthRead: {}, PermExploreRead: {}, PermPrivacyRead: {},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user