validators.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. import re
  2. import enum
  3. class validator_result(enum.IntEnum):
  4. """
  5. This is class, which provide validator_results. Validator results is
  6. presents as int, and this class define which int represent which error.
  7. """
  8. """ Valid result. """
  9. valid = 0
  10. """ Given string is too long. """
  11. too_long = 1
  12. """ Given string is too short. """
  13. too_short = 2
  14. """ Given string not contain one of required chars. """
  15. add_required_char = 3
  16. """ Given string contain one of blocked chars. """
  17. contain_invalid_char = 4
  18. def name(code: int) -> str | None:
  19. """
  20. This function convert given error code to readable string. When given
  21. code means, that string is valid, return None.
  22. Parameters:
  23. code (int): Error code number
  24. Returns:
  25. (str | None): Error as string, None when code is valid
  26. """
  27. if code == validator_result.valid:
  28. return None
  29. if code == validator_result.too_long:
  30. return "Given string is too long."
  31. if code == validator_result.too_short:
  32. return "Given string is too short."
  33. if code == validator_result.add_required_char:
  34. return "Given string not contain one of required chars."
  35. if code == validator_result.contain_invalid_char:
  36. return "Given string contain char, which is blocker."
  37. return "Not known error number."
  38. class validator:
  39. """
  40. This is validator class. It is responsible for checking, that given string
  41. meets the organisation policy. For example, password is not too short, or
  42. contain required string.
  43. """
  44. def __init__(self, content: str | None = None) -> None:
  45. """
  46. This is class initialiser, it get string to check. It also could get
  47. None, then information validator is builded. Information validator is
  48. validator, which not validate anything, but provide information about
  49. validation, like max_lenght.
  50. Parameters:
  51. content (str | None): Target string to check, or None
  52. """
  53. self.__content = content
  54. @property
  55. def content(self) -> str:
  56. """
  57. String to check, provided in the constructor. When content is None,
  58. it raise TypeError.
  59. Returns:
  60. (str): Content of the validator
  61. """
  62. if self.__content is None:
  63. error = "This is only validator, which provide informations. "
  64. error = error + "It has not any content."
  65. raise TypeError(error)
  66. return self.__content
  67. @property
  68. def is_valid(self) -> bool:
  69. """
  70. This check that provided string is valid.
  71. Returns:
  72. (bool): True when provided string is valid, False if not
  73. """
  74. return self.result == validator_result.valid
  75. @property
  76. def result(self) -> int:
  77. """
  78. This return result of the check, as number from validator_result.
  79. Returns:
  80. (int): Result of the validation.
  81. """
  82. lenght = len(self.content)
  83. invalid_regex = False
  84. contain_regex = False
  85. if len(self.must_contain) > 0:
  86. contain_regex = "[" + "".join(self.must_contain) + "]"
  87. if len(self.invalid_chars) > 0:
  88. invalid_regex = "[" + "".join(self.invalid_chars) + "]"
  89. if lenght > self.max_lenght:
  90. return validator_result.too_long
  91. if lenght < self.min_lenght:
  92. return validator_result.too_short
  93. if invalid_regex and len(re.findall(invalid_regex, self.content)) > 0:
  94. return validator_result.contain_invalid_char
  95. if contain_regex and len(re.findall(contain_regex, self.content)) == 0:
  96. return validator_result.add_required_char
  97. return self._end_final(self.content)
  98. def _end_final(self, content: str) -> int:
  99. """
  100. This function is end check. It could be overwriten to make custom
  101. validation. For example check for additional reguls.
  102. Parameters:
  103. content (str): Content of the string, which must be validate
  104. Returns:
  105. (int): Number from validator_results enum
  106. """
  107. return validator_result.valid
  108. @property
  109. def info(self) -> str | None:
  110. """ This return additional info about validator, for frontend. """
  111. return None
  112. @property
  113. def min_lenght(self) -> int:
  114. """ This return minimum lenght of the string. """
  115. raise TypeError("Property min_lenght must be overwrite.")
  116. @property
  117. def max_lenght(self) -> int:
  118. """ This return maximum lenght of the string. """
  119. raise TypeError("Property max_lenght must be overwrite.")
  120. @property
  121. def must_contain(self) -> list:
  122. """ This return list of chars, one of them must being in content """
  123. raise TypeError("Property must_contain must be overwrite.")
  124. @property
  125. def invalid_chars(self) -> list:
  126. """ This return chars, which can not being in the content. """
  127. raise TypeError("Property invalid_chars must be overwrite.")
  128. class validator_dumper:
  129. """
  130. This class is responsible for validators info dumps, required for example
  131. on application frontend, to presents information.
  132. """
  133. def __init__(self, target: type) -> None:
  134. """
  135. This set target validator.
  136. Parameters:
  137. target (type): This is validator to setup, as class
  138. """
  139. self.__target = target()
  140. @property
  141. def target(self) -> validator:
  142. """ Target validator. """
  143. return self.__target
  144. @property
  145. def route(self) -> dict:
  146. """
  147. This is dump of all informations as dictionary.
  148. * max-lenght (int) -> validator.max_lenght
  149. * min-lenght (int) -> validator.min_lenght
  150. * invalid-chars (list) -> validator.invalid_chars
  151. * required-chars (list) -> validator.must_contain
  152. * readable-info (str) -> validator.info or ""
  153. Returns:
  154. (dict): Info as described up
  155. """
  156. return {
  157. "max-lenght": self.target.max_lenght,
  158. "min-lenght": self.target.min_lenght,
  159. "invalid-chars": self.target.invalid_chars,
  160. "required-chars": self.target.must_contain,
  161. "readable-info": self.target.info or ""
  162. }
  163. class password_validator(validator):
  164. """
  165. This is validator for main app password.
  166. """
  167. @property
  168. def max_lenght(self) -> int:
  169. return 256
  170. @property
  171. def must_contain(self) -> list:
  172. return []
  173. @property
  174. def invalid_chars(self) -> list:
  175. return ["\"", "'", " ", "\t", "\n", "`"]
  176. @property
  177. def info(self) -> str:
  178. return "Password can not have white chars and quotation marks."
  179. @property
  180. def min_lenght(self) -> int:
  181. return 8
  182. class nick_validator(validator):
  183. """
  184. This is validator for nick in app.
  185. """
  186. @property
  187. def max_lenght(self) -> int:
  188. return 256
  189. @property
  190. def must_contain(self) -> list:
  191. return []
  192. @property
  193. def invalid_chars(self) -> list:
  194. return []
  195. @property
  196. def min_lenght(self) -> int:
  197. return 4
  198. @property
  199. def info(self) -> str | None:
  200. return "Nick can contain only letters, digits, and \"-, _\" chars."
  201. def _end_final(self, content: str) -> int:
  202. for letter in content:
  203. if letter.isalpha():
  204. continue
  205. if letter.isdigit():
  206. continue
  207. if letter == "_" or letter == "-":
  208. continue
  209. return validator_result.contain_invalid_char
  210. return validator_result.valid