secret.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import sqlmodel
  2. import hashlib
  3. import Crypto
  4. from .user import user
  5. from .builder import builder
  6. from .secret_crypto import secret_crypto
  7. class secret(sqlmodel.SQLModel, table = True):
  8. """
  9. This class represents secret in the database.
  10. """
  11. id: int | None = sqlmodel.Field(default = None, primary_key = True)
  12. name: str | None = sqlmodel.Field(default = None, index = True)
  13. domain: str | None = sqlmodel.Field(default = None, index = True)
  14. crypted: bytes | None = sqlmodel.Field(default = None)
  15. nonce: bytes | None = sqlmodel.Field(default = None)
  16. owner: int | None = sqlmodel.Field(default = None, foreign_key = "user.id")
  17. @property
  18. def in_database(self) -> bool:
  19. """ True when secret exists in database. """
  20. return self.id is not None
  21. @property
  22. def ready(self) -> bool:
  23. """ True when all fields are filled. """
  24. if self.name is None or self.domain is None:
  25. return False
  26. if self.crypted is None or self.nonce is None:
  27. return False
  28. if self.owner is None:
  29. return False
  30. return True
  31. def __str__(self) -> str:
  32. """
  33. This cast user to string, very usefull for debug.
  34. Returns:
  35. (str): User dump as string
  36. """
  37. result = ""
  38. result = result + "Secret "
  39. if self.id is not None:
  40. result = result + "(" + str(self.id) + ")"
  41. result = result + "\n"
  42. result = result + "Name: " + self.name + "\n"
  43. result = result + "Domain: " + self.domain + "\n"
  44. result = result + "Owner ID: " + str(self.owner) + "\n"
  45. result = result + "Crypted: " + self.crypted.hex() + "\n"
  46. result = result + "Nonce: " + self.nonce.hex() + "\n"
  47. return result
  48. class secret_builder(builder, target_type = secret):
  49. """
  50. This class is responsible for creating new secrets for the user.
  51. """
  52. @property
  53. def owner(self) -> int | None:
  54. """ This return ID of the secret owner, or None if not set. """
  55. return self._target.owner
  56. @owner.setter
  57. def owner(self, target: user):
  58. """ This set new owner of the secret. """
  59. if not target.in_database:
  60. raise TypeError("Target user for secret is not registered.")
  61. self._target.owner = target.id
  62. @property
  63. def name(self) -> str | None:
  64. """ This return name of the secret or None if not set. """
  65. return self._target.name
  66. @property
  67. def domain(self) -> str | None:
  68. """ This return domain of the secret or None if not set. """
  69. return self._target.domain
  70. @name.setter
  71. def name(self, target: str) -> None:
  72. """ This set name of the secret. """
  73. self._target.name = target.upper()
  74. @domain.setter
  75. def domain(self, target: str) -> None:
  76. """ This set domain of the secret. """
  77. self._target.domain = target
  78. def crypt(self, key: str, target: str) -> None:
  79. """
  80. This function crypt secret. It require password which could decrypt
  81. it laser, and target secret. It automatic set crypted and nonce secret
  82. fields. If secret already has nonce, then it use it. When secret nonce
  83. is empty, then it would provide new random nonce for secret.
  84. Parameters:
  85. key (str): Password to protect secret
  86. targer (str): Secret to encrypt
  87. """
  88. crypter = secret_crypto(key)
  89. if self._target.nonce is not None:
  90. crypter = crypter.set_iv(self._target.nonce)
  91. crypted, nonce = crypter.crypted(target)
  92. self._target.crypted = crypted
  93. self._target.nonce = nonce