test_models.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. from __future__ import annotations
  2. from sqlalchemy import Computed, UniqueConstraint
  3. import dms.models # noqa: F401
  4. from dms.common.enums import (
  5. AllowedModule,
  6. AuditAction,
  7. AuditResult,
  8. AuditTarget,
  9. ContentExtractStatus,
  10. RoleCode,
  11. SecurityLevel,
  12. SECURITY_LEVEL_VALUES,
  13. )
  14. from dms.extensions import db
  15. EXPECTED_TABLES = {
  16. "sys_organization",
  17. "sys_user",
  18. "doc_category",
  19. "doc_document",
  20. "doc_attachment_binding",
  21. "doc_permission",
  22. "sys_audit_log",
  23. }
  24. BUSINESS_TABLES = EXPECTED_TABLES - {"sys_audit_log"}
  25. COMMON_COLUMNS = {
  26. "id",
  27. "created_by",
  28. "updated_by",
  29. "created_at",
  30. "updated_at",
  31. "deleted_at",
  32. "is_deleted",
  33. "row_version",
  34. }
  35. def test_exactly_seven_models_are_registered():
  36. assert set(db.metadata.tables) == EXPECTED_TABLES
  37. assert len(db.metadata.tables) == 7
  38. def test_business_tables_have_common_columns():
  39. for table_name in BUSINESS_TABLES:
  40. columns = {column.name for column in db.metadata.tables[table_name].columns}
  41. assert COMMON_COLUMNS <= columns
  42. def test_audit_log_has_append_only_exception_fields():
  43. columns = {
  44. column.name for column in db.metadata.tables["sys_audit_log"].columns
  45. }
  46. assert "created_at" in columns
  47. assert {"updated_at", "deleted_at", "is_deleted", "row_version"}.isdisjoint(
  48. columns
  49. )
  50. def test_auth_version_field_exists_with_default_zero():
  51. column = db.metadata.tables["sys_user"].c.auth_version
  52. assert column.nullable is False
  53. assert str(column.server_default.arg) == "0"
  54. def test_attachment_type_field_exists():
  55. column = db.metadata.tables["doc_document"].c.attachment_type
  56. assert column.nullable is True
  57. def test_active_marker_columns_are_virtual_generated_columns():
  58. for table_name in ("doc_attachment_binding", "doc_permission"):
  59. column = db.metadata.tables[table_name].c.active_marker
  60. assert isinstance(column.computed, Computed)
  61. assert "IF(is_deleted = 0, 1, NULL)" in str(column.computed.sqltext)
  62. assert column.computed.persisted is False
  63. def _unique_column_sets(table_name: str) -> set[tuple[str, ...]]:
  64. table = db.metadata.tables[table_name]
  65. return {
  66. tuple(column.name for column in constraint.columns)
  67. for constraint in table.constraints
  68. if isinstance(constraint, UniqueConstraint)
  69. }
  70. def test_active_binding_unique_constraint():
  71. assert (
  72. "main_document_id",
  73. "attachment_document_id",
  74. "active_marker",
  75. ) in _unique_column_sets("doc_attachment_binding")
  76. def test_active_permission_unique_constraint():
  77. assert (
  78. "document_id",
  79. "subject_type",
  80. "subject_id",
  81. "active_marker",
  82. ) in _unique_column_sets("doc_permission")
  83. def test_no_foreign_key_uses_cascade_and_audit_has_no_foreign_keys():
  84. for table in db.metadata.tables.values():
  85. for foreign_key in table.foreign_keys:
  86. assert foreign_key.ondelete in {"RESTRICT", "NO ACTION"}
  87. assert foreign_key.ondelete != "CASCADE"
  88. assert not db.metadata.tables["sys_audit_log"].foreign_keys
  89. def test_created_and_updated_by_have_no_foreign_keys():
  90. for table_name in BUSINESS_TABLES:
  91. table = db.metadata.tables[table_name]
  92. assert not table.c.created_by.foreign_keys
  93. assert not table.c.updated_by.foreign_keys
  94. def test_required_permanent_unique_codes_exist():
  95. assert ("org_code",) in _unique_column_sets("sys_organization")
  96. assert ("username",) in _unique_column_sets("sys_user")
  97. assert ("category_code",) in _unique_column_sets("doc_category")
  98. def test_critical_indexes_exist():
  99. expected = {
  100. "doc_document": {
  101. "ix_doc_document_type_active_updated",
  102. "ix_doc_document_file_hash",
  103. "ix_doc_document_attachment_type_active_updated",
  104. },
  105. "sys_audit_log": {
  106. "ix_sys_audit_log_created_at",
  107. "ix_sys_audit_log_user_created",
  108. "ix_sys_audit_log_organization_created",
  109. "ix_sys_audit_log_action_created",
  110. "ix_sys_audit_log_target_created",
  111. "ix_sys_audit_log_result_created",
  112. "ix_sys_audit_log_request_id",
  113. },
  114. }
  115. for table_name, names in expected.items():
  116. actual = {index.name for index in db.metadata.tables[table_name].indexes}
  117. assert names <= actual
  118. def test_permission_model_has_no_inherited_source_column():
  119. assert "permission_source" not in db.metadata.tables["doc_permission"].c
  120. def test_contract_enums_are_exact():
  121. assert {item.value for item in RoleCode} == {"USER", "ADMIN"}
  122. assert {item.value for item in ContentExtractStatus} == {
  123. "SUCCESS",
  124. "EMPTY",
  125. "UNSUPPORTED",
  126. "FAILED",
  127. }
  128. assert {item.value for item in AllowedModule} == {
  129. "DOCUMENT_BROWSER",
  130. "BACKEND_MANAGEMENT",
  131. "AUDIT_LOG",
  132. }
  133. assert {item.value for item in AuditResult} == {"SUCCESS", "FAILURE"}
  134. assert {item.value for item in AuditAction} == {
  135. "LOGIN",
  136. "LOGOUT",
  137. "VIEW_DOCUMENT",
  138. "DOWNLOAD_DOCUMENT",
  139. "UPLOAD_DOCUMENT",
  140. "BATCH_IMPORT",
  141. "EDIT_DOCUMENT",
  142. "DELETE_DOCUMENT",
  143. "CREATE_CATEGORY",
  144. "EDIT_CATEGORY",
  145. "DELETE_CATEGORY",
  146. "CHANGE_PERMISSION",
  147. "BIND_ATTACHMENT",
  148. "UNBIND_ATTACHMENT",
  149. "RESTORE_DOCUMENT",
  150. }
  151. assert {item.value for item in AuditTarget} == {
  152. "AUTH",
  153. "CATEGORY",
  154. "DOCUMENT",
  155. "ATTACHMENT",
  156. "PERMISSION",
  157. "ATTACHMENT_BINDING",
  158. }
  159. assert SECURITY_LEVEL_VALUES == {
  160. SecurityLevel.PUBLIC: 10,
  161. SecurityLevel.INTERNAL: 20,
  162. SecurityLevel.SECRET: 30,
  163. SecurityLevel.CONFIDENTIAL: 40,
  164. SecurityLevel.TOP_SECRET: 50,
  165. }