application_user.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. from .user import user
  2. from .user import user_builder
  3. from .user_loader import user_loader
  4. from .application_part import application_part
  5. from .validators import nick_validator
  6. from .validators import password_validator
  7. class application_user(application_part):
  8. """
  9. This class is part of the app, which is responsible for user api
  10. endpoints, like registering users, login to app, change nick and
  11. others. To full responses and parameters documentation, see api
  12. documentation.
  13. """
  14. def get(self, apikey: str) -> dict:
  15. """
  16. This return information about user, like nick or code_key, to use
  17. in end-to-end encryption.
  18. Parameters:
  19. apikey (str): Apikey of the user
  20. Returns:
  21. (dict): Information about user
  22. """
  23. with self.__loader as loader:
  24. user = loader.get_by_apikey(apikey)
  25. if user is None:
  26. return self._fail_no_apikey()
  27. return self._success_response(
  28. nick = user.nick,
  29. password = user.password,
  30. apikey = user.apikey,
  31. code_key = user.code_key
  32. )
  33. def register(self, nick: str, password: str) -> dict:
  34. """
  35. This register new user, by password and nick. It check that nick is
  36. not in use, also validate password and nick. ApiKey and code_key
  37. would be generate by operating system random generator.
  38. Parameters:
  39. nick (str): Nick of the new user
  40. password (str): Password of the new user
  41. Returns:
  42. (dict): Response to generate json
  43. """
  44. validate = self._validation(
  45. "nick",
  46. nick_validator(nick)
  47. )
  48. validate = validate or self._validation(
  49. "password",
  50. password_validator(password)
  51. )
  52. if validate is not None:
  53. return validate
  54. builder = user_builder()
  55. builder.nick = nick
  56. builder.set_password(password)
  57. with self.__loader as loader:
  58. new_user = builder.result
  59. if loader.nick_in_use(new_user.nick):
  60. return self._fail_response(cause = "Nick already in use.")
  61. if loader.register(new_user):
  62. return self._apikey_response(new_user.apikey)
  63. return self._fail_response(cause = "Other database error.")
  64. def login(self, nick: str, password: str) -> dict:
  65. """
  66. This function login user. To operate client apps require apikey. This
  67. endpoint would return apikey, when valid nick and password had been
  68. provided.
  69. Parameters:
  70. nick (str): Nick of the user
  71. password (str): Passworrd of the user
  72. Returns:
  73. (dict): Result with apikey or error on fail
  74. """
  75. with self.__loader as loader:
  76. user = loader.login(nick, password)
  77. if user is None:
  78. return self._fail_response(cause = "Bad login or password.")
  79. return self._apikey_response(user.apikey)
  80. def unregister(self, apikey: str, password: str) -> dict:
  81. """
  82. This function drop user from database. It require password as second
  83. validation, and of course apikey to identify user.
  84. Parameters:
  85. apikey (str): ApiKey of the user to drop
  86. password (str): Password of the user to drop
  87. Returns:
  88. (dict): Result of the operation as to generate json response
  89. """
  90. with self.__loader as loader:
  91. user = loader.get_by_apikey(apikey)
  92. if user is None:
  93. return self._fail_no_apikey()
  94. if not user_builder(user).check_password(password):
  95. return self._fail_bad_password()
  96. loader.unregister(user)
  97. return self._success_response()
  98. def apikey_refresh(self, apikey: str) -> dict:
  99. """
  100. This function refresh apikey. It is useable when want to logout all
  101. devices which store apikey to stay logged in.
  102. Parameters:
  103. apikey (str): ApiKey of the user to refresh apikey
  104. Returns:
  105. (dict): Result of the operation, with new apikey when success
  106. """
  107. with self.__loader as loader:
  108. user = loader.get_by_apikey(apikey)
  109. if user is None:
  110. return self._fail_no_apikey()
  111. builder = user_builder(user)
  112. builder.refresh_apikey()
  113. new_user = builder.result
  114. if not loader.save(new_user):
  115. return self._fail_response(cause = "Database error.")
  116. return self._apikey_response(new_user.apikey)
  117. def change_password(
  118. self,
  119. apikey: str,
  120. old_password: str,
  121. new_password: str
  122. ) -> dict:
  123. """
  124. This function change password of the user. It require also old
  125. password, to decrypt key, which would be re-encrypt by new password.
  126. Of course new password would be validated before set.
  127. Parameters:
  128. apikey (str): ApiKey of the user to work on
  129. old_password (str): Old password of the user
  130. new_password (str): New password which would be set
  131. Returns:
  132. (dict): Result of the operation to create response
  133. """
  134. validate = self._validation(
  135. "password",
  136. password_validator(new_password)
  137. )
  138. if validate is not None:
  139. return validate
  140. with self.__loader as loader:
  141. user = loader.get_by_apikey(apikey)
  142. if user is None:
  143. return self._fail_no_apikey()
  144. builder = user_builder(user)
  145. if not builder.set_password(new_password, old_password):
  146. return self._fail_bad_password()
  147. new_user = builder.result
  148. loader.save(new_user)
  149. return self._apikey_response(new_user.apikey)
  150. def change_nick(self, apikey: str, nick: str) -> dict:
  151. """
  152. This function would change nick of the user. It also check that nick
  153. is not in use, and validate that nick is not bad formated.
  154. Parameters:
  155. apikey (str): ApiKey of the user to work on
  156. nick (str): New nick for the user
  157. Returns:
  158. (dict): Result of the operation to create response
  159. """
  160. validation = self._validation(
  161. "nick",
  162. nick_validator(nick)
  163. )
  164. if validation is not None:
  165. return validation
  166. with self.__loader as loader:
  167. user = loader.get_by_apikey(apikey)
  168. if user is None:
  169. return self._fail_no_apikey()
  170. if loader.nick_in_use(nick):
  171. return self._fail_response(cause = "Nick already in use.")
  172. builder = user_builder(user)
  173. builder.nick = nick
  174. new_user = builder.result
  175. if not loader.save(new_user):
  176. return self._fail_response(cause = "Other database error.")
  177. return self._success_response()
  178. @property
  179. def __loader(self) -> user_loader:
  180. """ This return new user_loader with database connector. """
  181. return user_loader(self._connector)