No Description
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.

main.py 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # -*- coding: utf-8 -*-
  2. import binascii
  3. import copy
  4. import datetime
  5. import os
  6. import pickle
  7. import re
  8. import time
  9. from lodel import logger
  10. from lodel.settings import Settings
  11. from lodel.auth.exceptions import ClientAuthenticationFailure
  12. from .filesystem_session import FileSystemSession
  13. ## @brief lists the active sessions in a dict
  14. # Its keys are the session tokens and its values are the file paths of session
  15. # files.
  16. __sessions = dict()
  17. # ====== UTILS ====== #
  18. ## @brief Generates a session token
  19. # @return str
  20. def __generate_token():
  21. new_token = binascii.hexlify(os.urandom(Settings.sessions.tokensize//2))
  22. if new_token in __sessions.keys():
  23. new_token = __generate_token()
  24. return new_token
  25. ## @brief Checks if a token is valid and matchs with a registered session
  26. # @param token str
  27. # @raise ClientAuthenticationFailure for invalid or not found session token
  28. def _check_token(token):
  29. # Bad length
  30. if len(token) != Settings.sessions.tokensize:
  31. raise ClientAuthenticationFailure("Malformed session token")
  32. # Not found
  33. if token not in __sessions:
  34. raise ClientAuthenticationFailure("No session found with this token")
  35. ## @brief Lists all the session files' paths
  36. # @return list
  37. def _list_all_sessions():
  38. session_files_directory = os.abspath(Settings.sessions.directory)
  39. return [file_path for file_path in os.listdir(session_files_directory) if os.path.isfile(os.path.join(session_files_directory, file_path))]
  40. ## @brief Returns the token from a session file's name
  41. # @param filename str
  42. # @return str
  43. def _get_token_from_session_filename(filename):
  44. token_regex = re.compile(Settings.sessions.file_template % '(?P<token>.*)')
  45. token_searching_result = token_regex.match(filename)
  46. if token_searching_result is not None:
  47. return token_searching_result.groupdict()['token']
  48. return None
  49. ## @brief Returns the session's last modification timestamp
  50. # @param token str
  51. # @return float
  52. def _get_session_last_modified(token):
  53. if token in __sessions.keys():
  54. return os.stat(__sessions[token]).st_mtime
  55. else:
  56. raise ValueError("The given token %s doesn't match with an existing session")
  57. # ====== SESSION MANAGEMENT ====== #
  58. ## @brief Registers the session in the active sessions' list
  59. # @param session LodelSession
  60. def _register_session(token):
  61. __sessions[token] = os.path.join(Settings.sessions.directory, Settings.sessions.file_template % token)
  62. ## @brief Session store's garbage collector
  63. def gc():
  64. # unregistered files in the session directory
  65. sessions_dir_files = _list_all_sessions()
  66. for sessions_dir_file in sessions_dir_files:
  67. token = _get_token_from_session_filename(sessions_dir_file)
  68. if token is None or token not in __sessions.keys():
  69. os.unlink(sessions_dir_file)
  70. # expired registered sessions
  71. for token in __sessions.keys():
  72. if os.path.isfile(__sessions[token]):
  73. now_timestamp = time.mktime(datetime.datetime.now().timetuple())
  74. if now_timestamp - _get_session_last_modified(token) > Settings.sessions.expiration:
  75. destroy_session(token)
  76. ## @brief starts a new session and returns its token
  77. # @return str
  78. def start_session():
  79. new_token = __generate_token()
  80. new_session = FileSystemSession(new_token)
  81. new_session.save()
  82. _register_session(new_token)
  83. _check_token(new_token)
  84. logger.debug("New session created")
  85. return new_token
  86. ## @brief destroys a session defined by its token
  87. # @param token str
  88. def destroy_session(token):
  89. _check_token(token)
  90. if os.path.isfile(__sessions[token]):
  91. os.unlink(__sessions[token])
  92. del(__sessions[token])
  93. logger.debug("Session %s destroyed" % token)
  94. ## @brief restores a session's content
  95. # @param token str
  96. # @return FileSystemSession
  97. def restore_session(token):
  98. _check_token(token)
  99. logger.debug("Restoring session : %s" % token)
  100. if os.path.isfile(__sessions[token]):
  101. with open(__sessions[token], 'rb') as session_file:
  102. session = pickle.load(session_file)
  103. return session
  104. return None
  105. def save_session(token, datas=None):
  106. _check_token(token)
  107. session = restore_session(token)
  108. session.datas = copy.copy(datas)
  109. with open(__sessions[token], 'wb') as session_file:
  110. pickle.dump(session, session_file)
  111. logger.debug("Session %s saved" % token)