permission.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. """主案ACL借阅授权模型(0026迁移:面向用户的限时借阅)。"""
  2. from __future__ import annotations
  3. from datetime import datetime
  4. from sqlalchemy import (
  5. BigInteger,
  6. Boolean,
  7. Computed,
  8. DateTime,
  9. ForeignKey,
  10. Index,
  11. Integer,
  12. String,
  13. UniqueConstraint,
  14. text,
  15. )
  16. from sqlalchemy.orm import Mapped, mapped_column
  17. from dms.database.base import BusinessTableMixin
  18. from dms.extensions import db
  19. class Permission(BusinessTableMixin, db.Model):
  20. __tablename__ = "doc_permission"
  21. __table_args__ = (
  22. UniqueConstraint(
  23. "document_id",
  24. "subject_id",
  25. "active_marker",
  26. name="uq_doc_permission_active",
  27. ),
  28. Index(
  29. "ix_doc_permission_document_active",
  30. "document_id",
  31. "is_deleted",
  32. ),
  33. Index(
  34. "ix_doc_permission_subject_active",
  35. "subject_id",
  36. "is_deleted",
  37. ),
  38. )
  39. document_id: Mapped[int] = mapped_column(
  40. BigInteger,
  41. ForeignKey("doc_document.id", ondelete="RESTRICT"),
  42. nullable=False,
  43. )
  44. subject_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
  45. subject_name: Mapped[str] = mapped_column(String(255), nullable=False)
  46. can_view: Mapped[bool] = mapped_column(
  47. Boolean,
  48. nullable=False,
  49. server_default=text("1"),
  50. )
  51. can_download: Mapped[bool] = mapped_column(
  52. Boolean,
  53. nullable=False,
  54. server_default=text("0"),
  55. )
  56. # 借阅到期时刻:服务层强制必填且不早于当前、不晚于当前+7天;
  57. # 1970 哨兵默认=fail-safe,漏赋值路径插入的行立即过期拒绝访问
  58. expires_at: Mapped[datetime] = mapped_column(
  59. DateTime,
  60. nullable=False,
  61. server_default=text("'1970-01-01 00:00:00'"),
  62. )
  63. # 审批单凭证(每条授权一份PDF,可空)
  64. voucher_file_name: Mapped[str | None] = mapped_column(
  65. String(255), nullable=True
  66. )
  67. voucher_storage_path: Mapped[str | None] = mapped_column(
  68. String(512), nullable=True
  69. )
  70. voucher_file_size: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
  71. voucher_uploaded_at: Mapped[datetime | None] = mapped_column(
  72. DateTime, nullable=True
  73. )
  74. active_marker: Mapped[int | None] = mapped_column(
  75. Integer,
  76. Computed("IF(is_deleted = 0, 1, NULL)", persisted=False),
  77. nullable=True,
  78. )