feat: send learning business audit events
Some checks failed
CI / hygiene (push) Successful in 2s
Build and Deploy / build-and-deploy (push) Successful in 35s
CI / test (push) Failing after 24s

This commit is contained in:
Grendgi
2026-06-17 12:52:57 +03:00
parent 94dd530823
commit ae2ac23a3a
5 changed files with 406 additions and 3 deletions

View File

@@ -0,0 +1,117 @@
package handler
import (
"net/http"
"testing"
)
func TestMatchLearningAuditAction(t *testing.T) {
tests := []struct {
name string
method string
path string
action string
entityType string
entityID string
}{
{
name: "test create",
method: http.MethodPost,
path: "/api/tests",
action: "learning.test_create",
entityType: "learning_test",
},
{
name: "question reorder",
method: http.MethodPost,
path: "/api/tests/7/questions/reorder",
action: "learning.question_reorder",
entityType: "learning_test",
entityID: "7",
},
{
name: "question update",
method: http.MethodPut,
path: "/api/tests/7/questions/9",
action: "learning.question_update",
entityType: "learning_question",
entityID: "9",
},
{
name: "attempt submit",
method: http.MethodPost,
path: "/api/attempts/11/submit",
action: "learning.attempt_submit",
entityType: "learning_attempt",
entityID: "11",
},
{
name: "course update",
method: http.MethodPatch,
path: "/api/courses/5",
action: "learning.course_update",
entityType: "learning_course",
entityID: "5",
},
{
name: "lesson create",
method: http.MethodPost,
path: "/api/courses/5/lessons",
action: "learning.lesson_create",
entityType: "learning_course",
entityID: "5",
},
{
name: "lesson video upload",
method: http.MethodPost,
path: "/api/lessons/3/video",
action: "learning.lesson_video_upload",
entityType: "learning_lesson",
entityID: "3",
},
{
name: "access grant create",
method: http.MethodPost,
path: "/api/access/course/5",
action: "learning.access_grant_create",
entityType: "learning_access",
entityID: "access/course/5",
},
{
name: "public token revoke",
method: http.MethodDelete,
path: "/api/public-tokens/13",
action: "learning.public_token_revoke",
entityType: "learning_public_token",
entityID: "13",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := matchLearningAuditAction(tt.method, tt.path)
if got.Action != tt.action || got.EntityType != tt.entityType || got.EntityID != tt.entityID {
t.Fatalf("unexpected action: got %#v, want action=%q entityType=%q entityID=%q", got, tt.action, tt.entityType, tt.entityID)
}
})
}
}
func TestMatchLearningAuditActionUnknown(t *testing.T) {
got := matchLearningAuditAction(http.MethodPost, "/public/learning/tokens/token/resolve")
if got.Action != "" {
t.Fatalf("expected no audit action, got %#v", got)
}
}
func TestExtractAuditEntityID(t *testing.T) {
if got := extractAuditEntityID([]byte(`{"id":42}`)); got != "42" {
t.Fatalf("numeric id = %q, want 42", got)
}
if got := extractAuditEntityID([]byte(`{"id":"abc"}`)); got != "abc" {
t.Fatalf("string id = %q, want abc", got)
}
if got := extractAuditEntityID([]byte(`{"title":"missing"}`)); got != "" {
t.Fatalf("missing id = %q, want empty", got)
}
}