core.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import typer
  2. import enum
  3. import pathlib
  4. import getpass
  5. import json
  6. import os
  7. import uvicorn
  8. from assets import *
  9. default_config = pathlib.Path("config.json")
  10. default_users_db = pathlib.Path("users.json")
  11. default_db = pathlib.Path("database.db")
  12. config_help = "This is configuration file of the app to use."
  13. users_db_help = "This is location of the users json database."
  14. db_help = "This is location of SQLite3 database file."
  15. description = "This is core reservationer package. It could be used to host "
  16. description = description + "app, or manage configuration or database."
  17. app = typer.Typer(help = description)
  18. class user_command(str, enum.Enum):
  19. """
  20. That commands could be used in the user subcommand.
  21. """
  22. add = "register"
  23. delete = "delete"
  24. password = "password-change"
  25. logout = "full-logout"
  26. def password_prompt() -> str:
  27. while True:
  28. first = getpass.getpass("Password: ")
  29. second = getpass.getpass("Repeat password: ")
  30. if first == second:
  31. return first
  32. print("Passwords do not match.")
  33. @app.command()
  34. def server(
  35. port: int = typer.Option(8080, help = "Port to listen on."),
  36. address: str = typer.Option("0.0.0.0", help = "Address to listen on."),
  37. config: pathlib.Path = typer.Option(default_config, help = config_help)
  38. ) -> None:
  39. """
  40. Start app on selected port and interfaces.
  41. """
  42. os.environ["config_file"] = str(config)
  43. server_config = uvicorn.Config(
  44. "assets.server:instance",
  45. port = port,
  46. host = address,
  47. log_level = "info"
  48. )
  49. app = uvicorn.Server(server_config)
  50. try:
  51. app.run()
  52. except json.JSONDecodeError as error:
  53. print("Can not parse config and user database.")
  54. print(str(error))
  55. @app.command()
  56. def user(
  57. command: user_command = typer.Argument(help = "Command to run on users."),
  58. nick: str = typer.Argument(help = "Nick of the user to work on."),
  59. config: pathlib.Path = typer.Option(default_config, help = config_help)
  60. ) -> None:
  61. """
  62. Modify user database.
  63. """
  64. try:
  65. loader = config_loader(app_config).load(config)
  66. collection = loader.resources.users
  67. # User adding
  68. if command == user_command.add:
  69. # Check that user exists
  70. if collection.exists(nick):
  71. raise Exception("User with that nick already exists.")
  72. # Create new user
  73. creator = user_factory()
  74. creator.nick = nick
  75. creator.password = password_prompt()
  76. # Add it
  77. collection.add(creator.result)
  78. print("Adding \"" + nick + "\" to the database.")
  79. # User remove
  80. elif command == user_command.delete:
  81. # Load from database
  82. target = collection.get_by_nick(nick)
  83. # Check that user exists
  84. if target is None:
  85. raise Exception("User with given nick not exists.")
  86. # When exists remove it
  87. collection.remove(target)
  88. # Change user password
  89. elif command == user_command.password:
  90. # Load user by nick
  91. target = collection.get_by_nick(nick)
  92. # Check that user exists
  93. if target is None:
  94. raise Exception("User not exists, can not change password.")
  95. # Change password
  96. handler = user_factory(target)
  97. handler.password = password_prompt()
  98. modified = handler.result
  99. # Store it in collection
  100. collection.remove(target).add(modified)
  101. # Logout user from all devices
  102. elif command == user_command.logout:
  103. # Load user from database
  104. target = collection.get_by_nick(nick)
  105. # Check that exists
  106. if target is None:
  107. raise Exception("User not exists, can not logout.")
  108. # Refresh apikey
  109. modified = user_factory(target) \
  110. .refresh_apikey() \
  111. .result
  112. # Store result
  113. collection.remove(target).add(modified)
  114. # Save collection to file
  115. users_saver(collection) \
  116. .drop(loader.result.users_path) \
  117. .save()
  118. print("Users database saved success.")
  119. except validator_exception as error:
  120. print("Password is not correct, too easy to break.")
  121. except json.JSONDecodeError as error:
  122. print("User JSON has syntax exception.")
  123. print(str(error))
  124. except Exception as error:
  125. print("Can not done work.")
  126. print(str(error))
  127. @app.command()
  128. def initialize(
  129. config: pathlib.Path = typer.Option(default_config, help = config_help),
  130. users: pathlib.Path = typer.Option(default_users_db, help = users_db_help),
  131. database: pathlib.Path = typer.Option(default_db, help = db_help)
  132. ) -> None:
  133. """
  134. Initialize app configuration.
  135. """
  136. try:
  137. # Generating config file
  138. config_generator(app_config) \
  139. .modify("users_file", str(users)) \
  140. .modify("database_uri", "sqlite:///" + str(database)) \
  141. .save(config)
  142. # Generating new blank users database
  143. users_saver(users_collection()).save(users)
  144. print("Config file is being created.")
  145. except Exception as error:
  146. print("Config initialization failed.")
  147. print(str(error))
  148. if __name__ == "__main__":
  149. app()