auth_identity_schema_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package schema
  2. import (
  3. "testing"
  4. "entgo.io/ent"
  5. "entgo.io/ent/entc/load"
  6. "entgo.io/ent/schema/field"
  7. "github.com/stretchr/testify/require"
  8. )
  9. func TestAuthIdentityFoundationSchemas(t *testing.T) {
  10. spec, err := (&load.Config{Path: "."}).Load()
  11. require.NoError(t, err)
  12. schemas := map[string]*load.Schema{}
  13. for _, schema := range spec.Schemas {
  14. schemas[schema.Name] = schema
  15. }
  16. authIdentity := requireSchema(t, schemas, "AuthIdentity")
  17. requireSchemaFields(t, authIdentity,
  18. "user_id",
  19. "provider_type",
  20. "provider_key",
  21. "provider_subject",
  22. "verified_at",
  23. "issuer",
  24. "metadata",
  25. )
  26. requireHasUniqueIndex(t, authIdentity, "provider_type", "provider_key", "provider_subject")
  27. authIdentityChannel := requireSchema(t, schemas, "AuthIdentityChannel")
  28. requireSchemaFields(t, authIdentityChannel,
  29. "identity_id",
  30. "provider_type",
  31. "provider_key",
  32. "channel",
  33. "channel_app_id",
  34. "channel_subject",
  35. "metadata",
  36. )
  37. requireHasUniqueIndex(t, authIdentityChannel, "provider_type", "provider_key", "channel", "channel_app_id", "channel_subject")
  38. pendingAuthSession := requireSchema(t, schemas, "PendingAuthSession")
  39. requireSchemaFields(t, pendingAuthSession,
  40. "intent",
  41. "provider_type",
  42. "provider_key",
  43. "provider_subject",
  44. "target_user_id",
  45. "redirect_to",
  46. "resolved_email",
  47. "registration_password_hash",
  48. "upstream_identity_claims",
  49. "local_flow_state",
  50. "browser_session_key",
  51. "completion_code_hash",
  52. "completion_code_expires_at",
  53. "email_verified_at",
  54. "password_verified_at",
  55. "totp_verified_at",
  56. "expires_at",
  57. "consumed_at",
  58. )
  59. adoptionDecision := requireSchema(t, schemas, "IdentityAdoptionDecision")
  60. requireSchemaFields(t, adoptionDecision,
  61. "pending_auth_session_id",
  62. "identity_id",
  63. "adopt_display_name",
  64. "adopt_avatar",
  65. "decided_at",
  66. )
  67. requireHasUniqueIndex(t, adoptionDecision, "pending_auth_session_id")
  68. userSchema := requireSchema(t, schemas, "User")
  69. requireSchemaFields(t, userSchema, "signup_source", "last_login_at", "last_active_at")
  70. signupSource := requireSchemaField(t, userSchema, "signup_source")
  71. require.Equal(t, field.TypeString, signupSource.Info.Type)
  72. require.True(t, signupSource.Default)
  73. require.Equal(t, "email", signupSource.DefaultValue)
  74. require.Equal(t, 1, signupSource.Validators)
  75. validator := requireStringFieldValidator(t, User{}.Fields(), "signup_source")
  76. for _, value := range []string{"email", "linuxdo", "wechat", "oidc", "github", "google", "dingtalk"} {
  77. require.NoError(t, validator(value))
  78. }
  79. require.Error(t, validator("unknown"))
  80. }
  81. func requireSchema(t *testing.T, schemas map[string]*load.Schema, name string) *load.Schema {
  82. t.Helper()
  83. schema, ok := schemas[name]
  84. require.True(t, ok, "schema %s should exist", name)
  85. return schema
  86. }
  87. func requireSchemaFields(t *testing.T, schema *load.Schema, names ...string) {
  88. t.Helper()
  89. fields := map[string]struct{}{}
  90. for _, field := range schema.Fields {
  91. fields[field.Name] = struct{}{}
  92. }
  93. for _, name := range names {
  94. _, ok := fields[name]
  95. require.True(t, ok, "schema %s should include field %s", schema.Name, name)
  96. }
  97. }
  98. func requireSchemaField(t *testing.T, schema *load.Schema, name string) *load.Field {
  99. t.Helper()
  100. for _, schemaField := range schema.Fields {
  101. if schemaField.Name == name {
  102. return schemaField
  103. }
  104. }
  105. require.Failf(t, "missing schema field", "schema %s should include field %s", schema.Name, name)
  106. return nil
  107. }
  108. func requireStringFieldValidator(t *testing.T, fields []ent.Field, name string) func(string) error {
  109. t.Helper()
  110. for _, entField := range fields {
  111. descriptor := entField.Descriptor()
  112. if descriptor.Name != name {
  113. continue
  114. }
  115. require.NotEmpty(t, descriptor.Validators, "field %s should include a validator", name)
  116. validator, ok := descriptor.Validators[0].(func(string) error)
  117. require.True(t, ok, "field %s validator should be func(string) error", name)
  118. return validator
  119. }
  120. require.Failf(t, "missing field validator", "schema should include field %s", name)
  121. return nil
  122. }
  123. func requireHasUniqueIndex(t *testing.T, schema *load.Schema, fields ...string) {
  124. t.Helper()
  125. for _, index := range schema.Indexes {
  126. if !index.Unique {
  127. continue
  128. }
  129. if len(index.Fields) != len(fields) {
  130. continue
  131. }
  132. match := true
  133. for i := range fields {
  134. if index.Fields[i] != fields[i] {
  135. match = false
  136. break
  137. }
  138. }
  139. if match {
  140. return
  141. }
  142. }
  143. require.Failf(t, "missing unique index", "schema %s should include unique index on %v", schema.Name, fields)
  144. }