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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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. def generate_file_path(token):
  30. return os.path.abspath(os.path.join(Settings.sessions.directory, Settings.sessions.file_template) % token)
  31. def get_token_from_filepath(filepath):
  32. token_regex = re.compile(os.path.abspath(os.path.join(Settings.sessions.directory, Settings.sessions.file_template % '(?P<token>.*)')))
  33. token_search_result = token_regex.match(filepath)
  34. if token_search_result is not None:
  35. return token_search_result.groupdict()['token']
  36. return None
  37. ## @brief returns the session's last modification timestamp
  38. # @param token str
  39. # @return float
  40. # @raise ValueError if the given token doesn't match with an existing session
  41. def get_session_last_modified(token):
  42. if token in __sessions[token]:
  43. return os.stat(__sessions[token]).st_mtime
  44. else:
  45. raise ValueError("The given token %s doesn't match with an existing session")
  46. ## @brief returns the token of a new session
  47. # @return str
  48. def start_session():
  49. session = FileSystemSession(generate_token())
  50. session.path = generate_file_path(session.token)
  51. with open(session.path, 'wb') as session_file:
  52. pickle.dump(session, session_file)
  53. __sessions[session.token] = session.path
  54. logger.debug("New session created")
  55. return session.token
  56. ## @brief destroys a session given its token
  57. # @param token str
  58. def destroy_session(token):
  59. check_token(token)
  60. if os.path.isfile(__sessions[token]):
  61. os.unlink(__sessions[token])
  62. logger.debug("Session file for %s destroyed" % token)
  63. del(__sessions[token])
  64. logger.debug("Session %s unregistered" % token)
  65. def restore_session(token):
  66. gc()
  67. check_token(token)
  68. logger.debug("Restoring session : %s" % token)
  69. if os.path.isfile(__sessions[token]):
  70. with open(__sessions[token], 'rb') as session_file:
  71. session = pickle.load(session_file)
  72. return session
  73. else:
  74. return None # raise FileNotFoundError("Session file not found for the token %s" % token)
  75. def save_session(token, datas):
  76. session = datas
  77. if not isinstance(datas, FileSystemSession):
  78. session = FileSystemSession(token)
  79. session.path = generate_file_path(token)
  80. session.update(datas)
  81. with open(__sessions[token], 'wb') as session_file:
  82. pickle.dump(session, session_file)
  83. if token not in __sessions.keys():
  84. __sessions[token] = session.path
  85. logger.debug("Session %s saved" % token)
  86. def gc():
  87. # Unregistered files in the session directory
  88. session_files_directory = os.path.abspath(Settings.sessions.directory)
  89. 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))]:
  90. session_file_path = os.path.join(session_files_directory, session_file)
  91. token = get_token_from_filepath(session_file_path)
  92. if token is None or token not in __sessions.keys():
  93. os.unlink(session_file_path)
  94. logger.debug("Unregistered session file %s has been deleted" % session_file)
  95. # Expired registered sessions
  96. for token in __sessions.keys():
  97. if os.path.isfile(__sessions[token]):
  98. now_timestamp = time.mktime(datetime.datetime.now().timetuple())
  99. if now_timestamp - get_session_last_modified(token) > Settings.sessions.expiration:
  100. destroy_session(token)
  101. logger.debug("Expired session %s has been destroyed" % token)
  102. def set_session_value(token, key, value):
  103. session = restore_session(token)
  104. session[key] = value
  105. save_session(token, session)
  106. def get_session_value(token, key):
  107. session = restore_session(token)
  108. return session[key]
  109. def del_session_value(token, key):
  110. session = restore_session(token)
  111. if key in session:
  112. del(session[key])