validators.py 8.4 KB

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