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 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. # -*- coding: utf-8 -*-
  2. import binascii
  3. import datetime
  4. import os
  5. import pickle
  6. import re
  7. import time
  8. from lodel import logger
  9. from lodel.auth.exceptions import ClientAuthenticationFailure
  10. from lodel.settings import Settings
  11. from .filesystem_session import FileSystemSession
  12. __sessions = dict()
  13. SESSION_TOKENSIZE = 150
  14. ## @brief generates a new session token
  15. # @return str
  16. def generate_token():
  17. token = binascii.hexlify(os.urandom(SESSION_TOKENSIZE//2))
  18. if token in __sessions.keys():
  19. token = generate_token()
  20. return token.decode('utf-8')
  21. ## @brief checks the validity of a given session token
  22. # @param token str
  23. # @raise ClientAuthenticationFailure for invalid or not found session token
  24. def check_token(token):
  25. if len(token) != SESSION_TOKENSIZE:
  26. raise ClientAuthenticationFailure("Invalid token string")
  27. if token not in __sessions.keys():
  28. raise ClientAuthenticationFailure("No session found for this token")
  29. ## @brief returns a session file path for a specific token
  30. def generate_file_path(token):
  31. return os.path.abspath(os.path.join(Settings.sessions.directory, Settings.sessions.file_template) % token)
  32. def get_token_from_filepath(filepath):
  33. token_regex = re.compile(os.path.abspath(os.path.join(Settings.sessions.directory, Settings.sessions.file_template % '(?P<token>.*)')))
  34. token_search_result = token_regex.match(filepath)
  35. if token_search_result is not None:
  36. return token_search_result.groupdict()['token']
  37. return None
  38. ## @brief returns the session's last modification timestamp
  39. # @param token str
  40. # @return float
  41. # @raise ValueError if the given token doesn't match with an existing session
  42. def get_session_last_modified(token):
  43. if token in __sessions[token]:
  44. return os.stat(__sessions[token]).st_mtime
  45. else:
  46. raise ValueError("The given token %s doesn't match with an existing session")
  47. ## @brief returns the token of a new session
  48. # @return str
  49. def start_session():
  50. session = FileSystemSession(generate_token())
  51. session.path = generate_file_path(session.token)
  52. with open(session.path, 'wb') as session_file:
  53. pickle.dump(session, session_file)
  54. __sessions[session.token] = session.path
  55. logger.debug("New session created")
  56. return session.token
  57. ## @brief destroys a session given its token
  58. # @param token str
  59. def destroy_session(token):
  60. check_token(token)
  61. if os.path.isfile(__sessions[token]):
  62. os.unlink(__sessions[token])
  63. logger.debug("Session file for %s destroyed" % token)
  64. del(__sessions[token])
  65. logger.debug("Session %s unregistered" % token)
  66. ## @brief restores a session's content
  67. # @param token str
  68. # @return FileSystemSession|None
  69. def restore_session(token):
  70. gc()
  71. check_token(token)
  72. logger.debug("Restoring session : %s" % token)
  73. if os.path.isfile(__sessions[token]):
  74. with open(__sessions[token], 'rb') as session_file:
  75. session = pickle.load(session_file)
  76. return session
  77. else:
  78. return None # raise FileNotFoundError("Session file not found for the token %s" % token)
  79. ## @brief saves the session's content to a file
  80. # @param token str
  81. # @param datas dict
  82. def save_session(token, datas):
  83. session = datas
  84. if not isinstance(datas, FileSystemSession):
  85. session = FileSystemSession(token)
  86. session.path = generate_file_path(token)
  87. session.update(datas)
  88. with open(__sessions[token], 'wb') as session_file:
  89. pickle.dump(session, session_file)
  90. if token not in __sessions.keys():
  91. __sessions[token] = session.path
  92. logger.debug("Session %s saved" % token)
  93. ## @brief session store's garbage collector
  94. def gc():
  95. # Unregistered files in the session directory
  96. session_files_directory = os.path.abspath(Settings.sessions.directory)
  97. for session_file in [file_path for file_path in os.listdir(session_files_directory) if os.path.isfile(os.path.join(session_files_directory, file_path))]:
  98. session_file_path = os.path.join(session_files_directory, session_file)
  99. token = get_token_from_filepath(session_file_path)
  100. if token is None or token not in __sessions.keys():
  101. os.unlink(session_file_path)
  102. logger.debug("Unregistered session file %s has been deleted" % session_file)
  103. # Expired registered sessions
  104. for token in __sessions.keys():
  105. if os.path.isfile(__sessions[token]):
  106. now_timestamp = time.mktime(datetime.datetime.now().timetuple())
  107. if now_timestamp - get_session_last_modified(token) > Settings.sessions.expiration:
  108. destroy_session(token)
  109. logger.debug("Expired session %s has been destroyed" % token)
  110. def set_session_value(token, key, value):
  111. session = restore_session(token)
  112. session[key] = value
  113. save_session(token, session)
  114. def get_session_value(token, key):
  115. session = restore_session(token)
  116. return session[key]
  117. def del_session_value(token, key):
  118. session = restore_session(token)
  119. if key in session:
  120. del(session[key])