Blame session.py

b838e2
b838e2
import time
b838e2
import uuid
b838e2
import threading
b838e2
b838e2
b838e2
class Session:
b838e2
  def __init__(self, manager, user_id):
b838e2
    self.manager = manager
b838e2
    self.server = manager.server
b838e2
    self.id = uuid.uuid4().hex
b838e2
    self.user_id = user_id
b838e2
    self.maxtime = self.server.config['session']['time']
b838e2
    self.touch()
b838e2
        
b838e2
  def touch(self):
b838e2
    self.time = time.monotonic()
b838e2
b838e2
  def expired(self):
b838e2
    return self.time + self.maxtime < time.monotonic()
b838e2
        
b838e2
b838e2
class SessionManager:
b838e2
  COOKIE='session'
b838e2
  
b838e2
  def __init__(self, server):
b838e2
    self.server = server
b838e2
    self.lock = threading.Lock()
b838e2
    self.sessions = dict()
b838e2
    self.timer = threading.Timer(server.config['session']['time']*0.1, self.remove_expired)
b838e2
    self.timer.start()
b838e2
    
b838e2
  def remove_expired(self):
b838e2
    with self.lock:
b838e2
      remove = list()
b838e2
      for id, session in self.sessions.items():
b838e2
        if session.expired():
b838e2
          remove.append(id)
b838e2
      for id in remove:
b838e2
        del self.sessions[id]
b838e2
        
b838e2
  def delete_by_user_id(self, user_id):
b838e2
    assert(type(user_id) is int)
b838e2
    with self.lock:
b838e2
      remove = list()
b838e2
      for id, session in self.sessions.items():
b838e2
        if session.user_id == user_id:
b838e2
          remove.append(id)
b838e2
      for id in remove:
b838e2
        del self.sessions[id]
b838e2
  
b838e2
  def add_cookie_header(self, request):
b838e2
    remove = list()
b838e2
    j = 0
b838e2
    for i in request.answer.headers:
b838e2
      if i[0] == 'Set-Cookie':
b838e2
        remove.insert(0, j)
b838e2
      j += 1
b838e2
    for i in remove:
b838e2
      del request.answer.headers[i]
b838e2
    
b838e2
    value = None
b838e2
    if request.session:
b838e2
      path = self.server.config['urlprefix'] + '/'
b838e2
      value = '%s=%s; Path=%s; Max-Age=%d; Secure' \
b838e2
            % (self.COOKIE, request.session.id, path, request.session.maxtime)
b838e2
    else:
b838e2
      value = '%s=; Expires=Thu, 01 Jan 1970 00:00:00 GMT' \
b838e2
            % (self.COOKIE)
b838e2
    request.answer.headers.append( ('Set-Cookie', value) )
b838e2
  
b838e2
  def create_session(self, request, user_id):
b838e2
    assert(type(user_id) is int)
b838e2
    assert(user_id)
b838e2
    with self.lock:
b838e2
      session = Session(self, user_id)
b838e2
      self.sessions[session.id] = session
b838e2
      request.session = session
b838e2
    self.add_cookie_header(request)
b838e2
b838e2
  def attach_session(self, request):
b838e2
    request.session = None
b838e2
    
b838e2
    # parse cookie
b838e2
    id = None
b838e2
    for i in request.cookie.split(';'):
b838e2
      j = i.split('=')
b838e2
      if len(j) == 2:
b838e2
        if j[0].strip() == self.COOKIE:
b838e2
          if not id is None: # double cookie equals no cookie
b838e2
            id = None
b838e2
            break
b838e2
          id = j[1].strip()
b838e2
b838e2
    if id:
b838e2
      with self.lock:
b838e2
        session = self.sessions.get(id)
b838e2
        if session:
b838e2
          if session.expired():
b838e2
            del self.sessions[id]
b838e2
          else:
b838e2
            session.touch()
b838e2
            request.session = session
b838e2
b838e2
    if request.session or request.cookie: # need we add new or delete existant cookie
b838e2
      self.add_cookie_header(request)
b838e2
b838e2
  def close_session(self, request):
b838e2
    if request.session:
b838e2
      with self.lock:
b838e2
        if request.session.id in self.sessions:
b838e2
          del self.sessions[request.session.id]
b838e2
      request.session = None
b838e2
    if request.cookie:
b838e2
      self.add_cookie_header(request)