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

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