test_models.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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_document_relation",
  22. "doc_sub_plan_binding",
  23. "doc_permission",
  24. "sys_audit_log",
  25. "sys_role",
  26. "sys_role_permission",
  27. "sys_ip_entry",
  28. "sys_org_ip_assignment",
  29. }
  30. BUSINESS_TABLES = EXPECTED_TABLES - {"sys_audit_log"}
  31. COMMON_COLUMNS = {
  32. "id",
  33. "created_by",
  34. "updated_by",
  35. "created_at",
  36. "updated_at",
  37. "deleted_at",
  38. "is_deleted",
  39. "row_version",
  40. }
  41. def test_expected_models_are_registered():
  42. assert set(db.metadata.tables) == EXPECTED_TABLES
  43. assert len(db.metadata.tables) == 13
  44. def test_business_tables_have_common_columns():
  45. for table_name in BUSINESS_TABLES:
  46. columns = {column.name for column in db.metadata.tables[table_name].columns}
  47. assert COMMON_COLUMNS <= columns
  48. def test_audit_log_has_append_only_exception_fields():
  49. columns = {
  50. column.name for column in db.metadata.tables["sys_audit_log"].columns
  51. }
  52. assert "created_at" in columns
  53. assert {"updated_at", "deleted_at", "is_deleted", "row_version"}.isdisjoint(
  54. columns
  55. )
  56. def test_auth_version_field_exists_with_default_zero():
  57. column = db.metadata.tables["sys_user"].c.auth_version
  58. assert column.nullable is False
  59. assert str(column.server_default.arg) == "0"
  60. def test_attachment_type_field_exists():
  61. column = db.metadata.tables["doc_document"].c.attachment_type
  62. assert column.nullable is True
  63. def test_active_marker_columns_are_virtual_generated_columns():
  64. for table_name in (
  65. "doc_attachment_binding",
  66. "doc_permission",
  67. "sys_role",
  68. "sys_role_permission",
  69. "sys_ip_entry",
  70. "sys_org_ip_assignment",
  71. "sys_user",
  72. "doc_sub_plan_binding",
  73. ):
  74. column = db.metadata.tables[table_name].c.active_marker
  75. assert isinstance(column.computed, Computed)
  76. assert "IF(is_deleted = 0, 1, NULL)" in str(column.computed.sqltext)
  77. assert column.computed.persisted is False
  78. def test_role_default_marker_is_virtual_generated_column():
  79. column = db.metadata.tables["sys_role"].c.default_marker
  80. assert isinstance(column.computed, Computed)
  81. assert "IF(is_default = 1 AND is_deleted = 0, 1, NULL)" in str(
  82. column.computed.sqltext
  83. )
  84. assert column.computed.persisted is False
  85. def _unique_column_sets(table_name: str) -> set[tuple[str, ...]]:
  86. table = db.metadata.tables[table_name]
  87. return {
  88. tuple(column.name for column in constraint.columns)
  89. for constraint in table.constraints
  90. if isinstance(constraint, UniqueConstraint)
  91. }
  92. def test_active_binding_unique_constraint():
  93. assert (
  94. "main_document_id",
  95. "attachment_document_id",
  96. "active_marker",
  97. ) in _unique_column_sets("doc_attachment_binding")
  98. def test_active_permission_unique_constraint():
  99. assert (
  100. "document_id",
  101. "subject_type",
  102. "subject_id",
  103. "active_marker",
  104. ) in _unique_column_sets("doc_permission")
  105. def test_role_tables_unique_constraints():
  106. assert ("role_name", "active_marker") in _unique_column_sets("sys_role")
  107. assert ("default_marker",) in _unique_column_sets("sys_role")
  108. assert (
  109. "role_id",
  110. "security_level",
  111. "dept_scope",
  112. "active_marker",
  113. ) in _unique_column_sets("sys_role_permission")
  114. def test_ip_tables_unique_constraints():
  115. assert ("ip_value", "active_marker") in _unique_column_sets("sys_ip_entry")
  116. assert (
  117. "organization_id",
  118. "ip_entry_id",
  119. "active_marker",
  120. ) in _unique_column_sets("sys_org_ip_assignment")
  121. def test_sub_plan_binding_unique_constraint_and_indexes():
  122. assert (
  123. "main_document_id",
  124. "sub_document_id",
  125. "active_marker",
  126. ) in _unique_column_sets("doc_sub_plan_binding")
  127. names = {
  128. index.name
  129. for index in db.metadata.tables["doc_sub_plan_binding"].indexes
  130. }
  131. assert {
  132. "ix_doc_sub_plan_binding_main_active_sort",
  133. "ix_doc_sub_plan_binding_sub_active",
  134. } <= names
  135. def test_portal_user_external_id_unique_constraint():
  136. assert ("external_id", "active_marker") in _unique_column_sets("sys_user")
  137. def test_no_foreign_key_uses_cascade_and_audit_has_no_foreign_keys():
  138. for table in db.metadata.tables.values():
  139. for foreign_key in table.foreign_keys:
  140. assert foreign_key.ondelete in {"RESTRICT", "NO ACTION"}
  141. assert foreign_key.ondelete != "CASCADE"
  142. assert not db.metadata.tables["sys_audit_log"].foreign_keys
  143. def test_created_and_updated_by_have_no_foreign_keys():
  144. for table_name in BUSINESS_TABLES:
  145. table = db.metadata.tables[table_name]
  146. assert not table.c.created_by.foreign_keys
  147. assert not table.c.updated_by.foreign_keys
  148. def test_required_permanent_unique_codes_exist():
  149. assert ("org_code", "active_marker") in _unique_column_sets("sys_organization")
  150. assert ("username",) in _unique_column_sets("sys_user")
  151. assert ("category_code", "active_marker") in _unique_column_sets("doc_category")
  152. def test_critical_indexes_exist():
  153. expected = {
  154. "doc_document": {
  155. "ix_doc_document_type_active_updated",
  156. "ix_doc_document_file_hash",
  157. "ix_doc_document_attachment_type_active_updated",
  158. },
  159. "sys_audit_log": {
  160. "ix_sys_audit_log_created_at",
  161. "ix_sys_audit_log_user_created",
  162. "ix_sys_audit_log_organization_created",
  163. "ix_sys_audit_log_action_created",
  164. "ix_sys_audit_log_target_created",
  165. "ix_sys_audit_log_result_created",
  166. "ix_sys_audit_log_request_id",
  167. },
  168. }
  169. for table_name, names in expected.items():
  170. actual = {index.name for index in db.metadata.tables[table_name].indexes}
  171. assert names <= actual
  172. def test_permission_model_has_no_inherited_source_column():
  173. assert "permission_source" not in db.metadata.tables["doc_permission"].c
  174. def test_contract_enums_are_exact():
  175. assert {item.value for item in RoleCode} == {"USER", "ADMIN"}
  176. assert {item.value for item in ContentExtractStatus} == {
  177. "SUCCESS",
  178. "EMPTY",
  179. "UNSUPPORTED",
  180. "FAILED",
  181. }
  182. assert {item.value for item in AllowedModule} == {
  183. "DOCUMENT_BROWSER",
  184. "BACKEND_MANAGEMENT",
  185. "AUDIT_LOG",
  186. "ORGANIZATION_USER_MANAGEMENT",
  187. }
  188. assert {item.value for item in AuditResult} == {"SUCCESS", "FAILURE"}
  189. assert {item.value for item in AuditAction} == {
  190. "LOGIN",
  191. "LOGOUT",
  192. "VIEW_DOCUMENT",
  193. "DOWNLOAD_DOCUMENT",
  194. "UPLOAD_DOCUMENT",
  195. "BATCH_IMPORT",
  196. "EDIT_DOCUMENT",
  197. "DELETE_DOCUMENT",
  198. "CREATE_CATEGORY",
  199. "EDIT_CATEGORY",
  200. "DELETE_CATEGORY",
  201. "CHANGE_PERMISSION",
  202. "BIND_ATTACHMENT",
  203. "UNBIND_ATTACHMENT",
  204. "RESTORE_DOCUMENT",
  205. "CREATE_ORGANIZATION",
  206. "EDIT_ORGANIZATION",
  207. "DELETE_ORGANIZATION",
  208. "CREATE_USER",
  209. "EDIT_USER",
  210. "DELETE_USER",
  211. "RESET_USER_PASSWORD",
  212. "REORDER_DOCUMENT",
  213. "REORDER_ATTACHMENT",
  214. "REORDER_CATEGORY",
  215. "CREATE_ROLE",
  216. "EDIT_ROLE",
  217. "DELETE_ROLE",
  218. "CHANGE_ROLE_PERMISSION",
  219. "CHANGE_ROLE_USER",
  220. "DOCUMENT_PASSWORD_SET",
  221. "DOCUMENT_PASSWORD_REMOVE",
  222. "CREATE_IP_ENTRY",
  223. "EDIT_IP_ENTRY",
  224. "DELETE_IP_ENTRY",
  225. "ASSIGN_ORG_IP",
  226. }
  227. assert {item.value for item in AuditTarget} == {
  228. "AUTH",
  229. "CATEGORY",
  230. "DOCUMENT",
  231. "ATTACHMENT",
  232. "PERMISSION",
  233. "ATTACHMENT_BINDING",
  234. "ORGANIZATION",
  235. "USER",
  236. "ROLE",
  237. "IP_ENTRY",
  238. }
  239. assert SECURITY_LEVEL_VALUES == {
  240. SecurityLevel.PUBLIC: 10,
  241. SecurityLevel.INTERNAL: 20,
  242. SecurityLevel.SECRET: 30,
  243. SecurityLevel.CONFIDENTIAL: 40,
  244. SecurityLevel.TOP_SECRET: 50,
  245. }