Blame session.py

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