feat: 收口视频访问与摄像头密钥输出
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"silk-server-go/internal/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func TestCameraResponseNeverContainsSecrets(t *testing.T) {
|
||||
password := "secret-password"
|
||||
camera := model.Camera{
|
||||
PasswordEnc: &password,
|
||||
GbAuthPassword: &password,
|
||||
}
|
||||
|
||||
raw, err := json.Marshal(camera)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal camera: %v", err)
|
||||
}
|
||||
body := string(raw)
|
||||
if strings.Contains(body, "passwordEnc") || strings.Contains(body, password) {
|
||||
t.Fatalf("camera JSON must not contain password fields: %s", body)
|
||||
}
|
||||
if strings.Contains(body, "gbAuthPassword") {
|
||||
t.Fatalf("camera JSON must not contain gbAuthPassword: %s", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssueAndValidateVideoToken(t *testing.T) {
|
||||
SetVideoTokenSecret("test-secret")
|
||||
token, err := IssueVideoToken("user-1", "camera", "12", time.Minute)
|
||||
if err != nil {
|
||||
t.Fatalf("issue video token: %v", err)
|
||||
}
|
||||
if token == "" {
|
||||
t.Fatal("expected non-empty video token")
|
||||
}
|
||||
|
||||
if err := ValidateVideoToken(token, "camera", "12"); err != nil {
|
||||
t.Fatalf("valid video token rejected: %v", err)
|
||||
}
|
||||
if err := ValidateVideoToken(token, "camera", "13"); err == nil {
|
||||
t.Fatal("expected resource mismatch error")
|
||||
}
|
||||
if err := ValidateVideoToken(token, "clip", "12"); err == nil {
|
||||
t.Fatal("expected resource type mismatch error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateVideoTokenForUserRejectsMismatch(t *testing.T) {
|
||||
SetVideoTokenSecret("test-secret")
|
||||
token, err := IssueVideoToken("user-1", "camera", "12", time.Minute)
|
||||
if err != nil {
|
||||
t.Fatalf("issue video token: %v", err)
|
||||
}
|
||||
|
||||
if err := ValidateVideoTokenForUser(token, "camera", "12", "user-1"); err != nil {
|
||||
t.Fatalf("same-user token rejected: %v", err)
|
||||
}
|
||||
if err := ValidateVideoTokenForUser(token, "camera", "12", "user-2"); err == nil {
|
||||
t.Fatal("expected cross-user token rejection")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVideoTokenExpires(t *testing.T) {
|
||||
SetVideoTokenSecret("test-secret")
|
||||
token, err := IssueVideoToken("user-1", "camera", "12", -time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("issue expired token: %v", err)
|
||||
}
|
||||
if err := ValidateVideoToken(token, "camera", "12"); err == nil {
|
||||
t.Fatal("expected expired token rejection")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVideoStreamRequiresValidToken(t *testing.T) {
|
||||
SetVideoTokenSecret("test-secret")
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = &http.Request{URL: &url.URL{RawQuery: ""}}
|
||||
if requireVideoToken(c, "camera", "12") {
|
||||
t.Fatal("missing token should be rejected")
|
||||
}
|
||||
if rec.Code != http.StatusUnauthorized {
|
||||
t.Fatalf("missing token status = %d, want 401", rec.Code)
|
||||
}
|
||||
|
||||
token, err := IssueVideoToken("user-1", "camera", "13", time.Minute)
|
||||
if err != nil {
|
||||
t.Fatalf("issue token: %v", err)
|
||||
}
|
||||
rec2 := httptest.NewRecorder()
|
||||
c2, _ := gin.CreateTestContext(rec2)
|
||||
c2.Request = &http.Request{URL: &url.URL{RawQuery: "videoToken=" + token}}
|
||||
if requireVideoToken(c2, "camera", "12") {
|
||||
t.Fatal("wrong resource token should be rejected")
|
||||
}
|
||||
if rec2.Code != http.StatusForbidden {
|
||||
t.Fatalf("wrong resource token status = %d, want 403", rec2.Code)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user