* H-300: wire Captain Skills into Web runtime * H-300: enforce effective model and conservative skill budget * H-300: fix CI gosec step * ci: extend golangci-lint timeout * fix lint findings across backend * fix(push): resolve delivery protocol blockers * test(repository): close SQLite test databases * test(repository): reuse SQLite schema per package * H-307: restore backend Go cache in CI * H-307: prefetch modules before cold lint * H-307: resolve govulncheck security gate * H-307: build lint with patched Go toolchain * H-307: clear remaining security scan findings --------- Co-authored-by: Rogee <rogee@ipao.vip>
135 lines
4.5 KiB
Go
135 lines
4.5 KiB
Go
package security
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/alicebob/miniredis/v2"
|
|
"github.com/gochat/gochat/internal/config"
|
|
"github.com/redis/go-redis/v9"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestTestWrite_Cov3(t *testing.T) {
|
|
TestWrite()
|
|
}
|
|
|
|
func TestTokenBlacklistService_IsBlacklisted_NotBlacklisted_Cov3(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 60}
|
|
svc := NewTokenBlacklistService(rdb, cfg)
|
|
|
|
bl, err := svc.IsBlacklisted(context.Background(), "some-token")
|
|
require.NoError(t, err)
|
|
assert.False(t, bl)
|
|
}
|
|
|
|
func TestTokenBlacklistService_IsBlacklisted_Blacklisted_Cov3(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 60}
|
|
svc := NewTokenBlacklistService(rdb, cfg)
|
|
|
|
// Manually set blacklist entry
|
|
require.NoError(t, mr.Set("gochat:token_blacklist:"+hashToken("some-token"), "1"))
|
|
|
|
bl, err := svc.IsBlacklisted(context.Background(), "some-token")
|
|
require.NoError(t, err)
|
|
assert.True(t, bl)
|
|
}
|
|
|
|
func TestTokenBlacklistService_IsBlacklisted_NotOne_Cov3(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 60}
|
|
svc := NewTokenBlacklistService(rdb, cfg)
|
|
|
|
// Set blacklist entry to something other than "1"
|
|
require.NoError(t, mr.Set("gochat:token_blacklist:"+hashToken("some-token"), "0"))
|
|
|
|
bl, err := svc.IsBlacklisted(context.Background(), "some-token")
|
|
require.NoError(t, err)
|
|
assert.False(t, bl)
|
|
}
|
|
|
|
func TestTokenBlacklistService_BlacklistAllUserTokens_Cov3(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 60}
|
|
svc := NewTokenBlacklistService(rdb, cfg)
|
|
|
|
err := svc.BlacklistAllUserTokens(context.Background(), 42)
|
|
require.NoError(t, err)
|
|
|
|
// Verify the key was set
|
|
assert.True(t, mr.Exists("gochat:user_revoke:42"))
|
|
}
|
|
|
|
func TestTokenBlacklistService_IsUserFullyRevoked_NotRevoked_Cov3(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 60}
|
|
svc := NewTokenBlacklistService(rdb, cfg)
|
|
|
|
revoked, err := svc.IsUserFullyRevoked(context.Background(), 42, time.Now())
|
|
require.NoError(t, err)
|
|
assert.False(t, revoked)
|
|
}
|
|
|
|
func TestTokenBlacklistService_IsUserFullyRevoked_Revoked_Cov3(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 60}
|
|
svc := NewTokenBlacklistService(rdb, cfg)
|
|
|
|
// Set revoke marker to a future timestamp
|
|
require.NoError(t, mr.Set("gochat:user_revoke:42", "9999999999"))
|
|
|
|
// Token issued before the revoke timestamp → should be revoked
|
|
revoked, err := svc.IsUserFullyRevoked(context.Background(), 42, time.Now().Add(-time.Hour))
|
|
require.NoError(t, err)
|
|
assert.True(t, revoked)
|
|
}
|
|
|
|
func TestTokenBlacklistService_IsUserFullyRevoked_TokenAfterRevoke_Cov3(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 60}
|
|
svc := NewTokenBlacklistService(rdb, cfg)
|
|
|
|
// Set revoke marker to 0 (epoch)
|
|
require.NoError(t, mr.Set("gochat:user_revoke:42", "0"))
|
|
|
|
// Token issued after the revoke → should NOT be revoked
|
|
revoked, err := svc.IsUserFullyRevoked(context.Background(), 42, time.Now())
|
|
require.NoError(t, err)
|
|
assert.False(t, revoked)
|
|
}
|
|
|
|
func TestValidateTokenWithChecks_InvalidToken_Cov3(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 60}
|
|
svc := NewTokenBlacklistService(rdb, cfg)
|
|
|
|
_, err := ValidateTokenWithChecks("invalid-token", cfg, svc, context.Background())
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestValidateTokenWithChecks_NilBlacklist_Cov3(t *testing.T) {
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 60}
|
|
|
|
_, err := ValidateTokenWithChecks("invalid-token", cfg, nil, context.Background())
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestValidateTokenWithChecks_EmptyToken_Cov3(t *testing.T) {
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 60}
|
|
|
|
_, err := ValidateTokenWithChecks("", cfg, nil, context.Background())
|
|
require.Error(t, err)
|
|
}
|