A multipurpose python flask API server and administration SPA
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
4.3 KiB

  1. """Service to handle user operations."""
  2. import logging
  3. from datetime import datetime
  4. from typing import Optional, Dict, Callable, Any
  5. from corvus.db import db
  6. from corvus.model import User
  7. from corvus.service.transformation_service import (
  8. BaseTransformer,
  9. register_transformer
  10. )
  11. from corvus.utility import authentication_utility
  12. LOGGER = logging.getLogger(__name__)
  13. class UserTransformer(BaseTransformer):
  14. """Serialize User model."""
  15. type = User
  16. def _deserializers(
  17. self) -> Dict[str, Callable[[User, Any], None]]:
  18. """Define the fields and the accompanying deserializer factory."""
  19. return {
  20. 'name': self.deserialize_name,
  21. 'creationTime': self.deserialize_creation_time,
  22. 'lastLoginTime': self.deserialize_last_login_time,
  23. 'version': self.deserialize_version,
  24. 'role': self.deserialize_role,
  25. }
  26. def _serializers(self) -> Dict[str, Callable[[], Any]]:
  27. """Define the fields and the accompanying serializer factory."""
  28. return {
  29. 'name': self.serialize_name,
  30. 'creationTime': self.serialize_creation_time,
  31. 'lastLoginTime': self.serialize_last_login_time,
  32. 'version': self.serialize_version,
  33. 'role': self.serialize_role,
  34. }
  35. def serialize_name(self) -> str:
  36. """User name."""
  37. return self.model.name
  38. @staticmethod
  39. def deserialize_name(model: User, name: str) -> None:
  40. """User name."""
  41. model.name = name
  42. def serialize_creation_time(self) -> datetime:
  43. """User creation time."""
  44. return self.model.creation_time
  45. @staticmethod
  46. def deserialize_creation_time(
  47. model: User, creation_time: datetime) -> None:
  48. """User creation time."""
  49. model.creation_time = creation_time
  50. def serialize_last_login_time(self) -> datetime:
  51. """User last login time."""
  52. return self.model.last_login_time
  53. @staticmethod
  54. def deserialize_last_login_time(
  55. model: User, last_login_time: datetime) -> None:
  56. """User last login time."""
  57. model.last_login_time = last_login_time
  58. def serialize_version(self) -> int:
  59. """User version."""
  60. return self.model.version
  61. @staticmethod
  62. def deserialize_version(model: User, version: int) -> None:
  63. """User version."""
  64. model.version = version
  65. def serialize_role(self) -> str:
  66. """User role."""
  67. return self.model.role
  68. @staticmethod
  69. def deserialize_role(model: User, role: str) -> None:
  70. """User role."""
  71. model.role = role
  72. register_transformer(User.__name__, UserTransformer)
  73. def register(name: str, password: str, role: str) -> User:
  74. """
  75. Register a new user.
  76. :param name: Desired user name. Must be unique and not already registered
  77. :param password: Password to be hashed and stored for the user
  78. :param role: Role to assign the user [ROLE_USER, ROLE_ADMIN]
  79. :return:
  80. """
  81. pw_hash, pw_revision = authentication_utility.get_password_hash(password)
  82. new_user = User(
  83. name=name,
  84. role=role,
  85. password_hash=pw_hash,
  86. password_revision=pw_revision,
  87. creation_time=datetime.now(),
  88. version=0)
  89. db.session.add(new_user)
  90. db.session.commit()
  91. LOGGER.info('Registered new user: %s with role: %s', name, role)
  92. return new_user
  93. def delete(user: User) -> bool:
  94. """
  95. Delete a user.
  96. :param user:
  97. :return:
  98. """
  99. existing_user = db.session.delete(user)
  100. if existing_user is None:
  101. db.session.commit()
  102. return True
  103. return False
  104. def update_last_login_time(user: User) -> None:
  105. """
  106. Bump the last login time for the user.
  107. :param user:
  108. :return:
  109. """
  110. if user is not None:
  111. user.last_login_time = datetime.now()
  112. db.session.commit()
  113. def update_password(user: User, password: str) -> None:
  114. """
  115. Change the user password.
  116. :param user:
  117. :param password:
  118. :return:
  119. """
  120. pw_hash, pw_revision = authentication_utility.get_password_hash(
  121. password)
  122. user.password_hash = pw_hash
  123. user.password_revision = pw_revision
  124. db.session.commit()
  125. def find_by_name(name: str) -> Optional[User]:
  126. """
  127. Find a user by name.
  128. :param name:
  129. :return:
  130. """
  131. return User.query.filter_by(name=name).first()