admin_compliance_test.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package service
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "testing"
  7. "github.com/Wei-Shaw/sub2api/internal/config"
  8. "github.com/stretchr/testify/require"
  9. )
  10. type adminComplianceRepoStub struct {
  11. values map[string]string
  12. }
  13. func (r *adminComplianceRepoStub) Get(ctx context.Context, key string) (*Setting, error) {
  14. if value, ok := r.values[key]; ok {
  15. return &Setting{Key: key, Value: value}, nil
  16. }
  17. return nil, ErrSettingNotFound
  18. }
  19. func (r *adminComplianceRepoStub) GetValue(ctx context.Context, key string) (string, error) {
  20. setting, err := r.Get(ctx, key)
  21. if err != nil {
  22. return "", err
  23. }
  24. return setting.Value, nil
  25. }
  26. func (r *adminComplianceRepoStub) Set(ctx context.Context, key, value string) error {
  27. if r.values == nil {
  28. r.values = map[string]string{}
  29. }
  30. r.values[key] = value
  31. return nil
  32. }
  33. func (r *adminComplianceRepoStub) GetMultiple(ctx context.Context, keys []string) (map[string]string, error) {
  34. return map[string]string{}, nil
  35. }
  36. func (r *adminComplianceRepoStub) SetMultiple(ctx context.Context, settings map[string]string) error {
  37. return nil
  38. }
  39. func (r *adminComplianceRepoStub) GetAll(ctx context.Context) (map[string]string, error) {
  40. return map[string]string{}, nil
  41. }
  42. func (r *adminComplianceRepoStub) Delete(ctx context.Context, key string) error {
  43. delete(r.values, key)
  44. return nil
  45. }
  46. func TestAdminComplianceStatusRequiresAckWhenMissing(t *testing.T) {
  47. svc := NewSettingService(&adminComplianceRepoStub{}, &config.Config{})
  48. status, err := svc.GetAdminComplianceStatus(context.Background(), 1)
  49. require.NoError(t, err)
  50. require.True(t, status.Required)
  51. require.Equal(t, AdminComplianceVersion, status.Version)
  52. require.Equal(t, AdminComplianceAckPhraseZH, status.AckPhraseZH)
  53. require.Equal(t, AdminComplianceDocumentPathZH, status.DocumentPathZH)
  54. }
  55. func TestAcceptAdminComplianceRejectsWrongPhrase(t *testing.T) {
  56. svc := NewSettingService(&adminComplianceRepoStub{}, &config.Config{})
  57. _, err := svc.AcceptAdminCompliance(context.Background(), AdminComplianceAcceptInput{
  58. AdminUserID: 1,
  59. Language: "zh",
  60. Phrase: "我同意",
  61. })
  62. require.Error(t, err)
  63. require.True(t, errors.Is(err, ErrAdminComplianceInvalidPhrase))
  64. }
  65. func TestAcceptAdminCompliancePersistsCurrentVersion(t *testing.T) {
  66. repo := &adminComplianceRepoStub{}
  67. svc := NewSettingService(repo, &config.Config{})
  68. status, err := svc.AcceptAdminCompliance(context.Background(), AdminComplianceAcceptInput{
  69. AdminUserID: 42,
  70. Language: "zh-CN",
  71. Phrase: AdminComplianceAckPhraseZH,
  72. IPAddress: "203.0.113.10",
  73. UserAgent: "test-agent",
  74. })
  75. require.NoError(t, err)
  76. require.False(t, status.Required)
  77. require.NotNil(t, status.Acknowledgement)
  78. require.Equal(t, int64(42), status.Acknowledgement.AdminUserID)
  79. require.Equal(t, "203.0.113.10", status.Acknowledgement.IPAddress)
  80. var stored AdminComplianceAcknowledgement
  81. require.NoError(t, json.Unmarshal([]byte(repo.values[adminComplianceAcknowledgementKey(42)]), &stored))
  82. require.Equal(t, AdminComplianceVersion, stored.Version)
  83. require.Equal(t, AdminComplianceDocumentPathZH, stored.DocumentZH)
  84. }
  85. func TestAdminComplianceStatusRequiresAckOnOldVersion(t *testing.T) {
  86. old, err := json.Marshal(AdminComplianceAcknowledgement{Version: "v2026.01.01"})
  87. require.NoError(t, err)
  88. svc := NewSettingService(&adminComplianceRepoStub{
  89. values: map[string]string{adminComplianceAcknowledgementKey(1): string(old)},
  90. }, &config.Config{})
  91. status, err := svc.GetAdminComplianceStatus(context.Background(), 1)
  92. require.NoError(t, err)
  93. require.True(t, status.Required)
  94. require.Nil(t, status.Acknowledgement)
  95. }
  96. func TestAdminComplianceStatusIsPerAdminUser(t *testing.T) {
  97. current, err := json.Marshal(AdminComplianceAcknowledgement{
  98. Version: AdminComplianceVersion,
  99. AdminUserID: 1,
  100. })
  101. require.NoError(t, err)
  102. svc := NewSettingService(&adminComplianceRepoStub{
  103. values: map[string]string{adminComplianceAcknowledgementKey(1): string(current)},
  104. }, &config.Config{})
  105. statusForUserOne, err := svc.GetAdminComplianceStatus(context.Background(), 1)
  106. require.NoError(t, err)
  107. require.False(t, statusForUserOne.Required)
  108. statusForUserTwo, err := svc.GetAdminComplianceStatus(context.Background(), 2)
  109. require.NoError(t, err)
  110. require.True(t, statusForUserTwo.Required)
  111. }