# -*- coding: utf-8 -*-
#
# UnivNautes
# Copyright (C) 2014  Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

'''
delete all django sessions:
* if pfsenseid exists in session but is not in captiveportal.db
* if session is expired
'''

import os
import datetime
import subprocess

from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
from django.contrib.sessions.backends.file import SessionStore

storage_path = settings.SESSION_FILE_PATH
file_prefix = settings.SESSION_COOKIE_NAME

class Command(BaseCommand):
    help = 'remove Django sessions without pfSense equivalent'

    def handle(self, *args, **options):
        try:
            p = subprocess.Popen(settings.UNIVNAUTES_CP_GET_SESSIONS_CMD,
                close_fds=True,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE)
        except OSError, e:
            # FIXME : log
            return
        stdout, stderr = p.communicate()

        if p.returncode != 0:
            # FIXME : log
            return

        pfsenseids = stdout.split()

        for session_file in os.listdir(storage_path):
            if not session_file.startswith(file_prefix):
                continue
            session_key = session_file[len(file_prefix):]
            session = SessionStore(session_key)
            # When an expired session is loaded, its file is removed, and a
            # new file is immediately created. Prevent this by disabling
            # the create() method.
            session.create = lambda: None

            session_data = session.load()
            # pfsenseid doesn't exist in captiveportal.db
            if session_data.get('pfsenseid') and session_data['pfsenseid'] not in pfsenseids:
                session.delete()
                continue

            # expired
            modification = os.stat(session._key_to_file()).st_ctime
            age = datetime.datetime.now() - datetime.datetime.fromtimestamp(modification)
            if age.seconds > session.get_expiry_age():
                session.delete()
                continue

