示例#1
0
    def decrypt(self, eid):
        """
        Return the SessionStore to which the encrypted identifier is
        pointing. Raises ValueError if the identifier is invalid.
        """

        try:
            session_id = cipher.decrypt(ub64decode(eid),
                                        self.ciphertext_length)
        except (TypeError, ValueError):
            pass
        else:
            session_id = session_id[self.random_prefix_bytes:]
            session_id = ub64encode(session_id)
            session = SessionStore(session_key=session_id)
            if session.get('encrypted_id') == eid:
                # circular import
                from .models import RevokedToken

                # revoke to prevent replay attacks
                if RevokedToken.add(eid):
                    del session['encrypted_id']
                    session.save()
                    return session
        raise ValueError('Invalid session id')
示例#2
0
    def decrypt(self, eid):
        """
        Return the SessionStore to which the encrypted identifier is
        pointing. Raises ValueError if the identifier is invalid.
        """

        try:
            session_id = cipher.decrypt(ub64decode(eid),
                                        self.ciphertext_length)
        except (TypeError, ValueError):
            pass
        else:
            session_id = session_id[self.random_prefix_bytes:]
            session_id = ub64encode(session_id)
            session = SessionStore(session_key=session_id)
            if session.get('encrypted_id') == eid:
                # circular import
                from .models import RevokedToken

                # revoke to prevent replay attacks
                if RevokedToken.add(eid):
                    del session['encrypted_id']
                    session.save()
                    return session
        raise ValueError('Invalid session id')
示例#3
0
 def processSession(skey):
     # get the latest session associated with this object
     session = SessionStore(skey)
     # do not go if the session has already been logged out
     if session.get('account') is None or SESSION_KEY not in session:
         return
         
     processCometReceivedDict(session, postDict)
     
     # need to save session to commit modifications
     session.modified = True
     session.save()
     
     # flag all threads with this session_key about the new stuff
     # same browser - different tabs
     CometSession.objects.update()
     for comet in CometSession.objects.filter(session_key=skey):
         comet.modified = True
         comet.save()
示例#4
0
    def processSession(skey):
        # get the latest session associated with this object
        session = SessionStore(skey)
        # do not go if the session has already been logged out
        if session.get('account') is None or SESSION_KEY not in session:
            return

        processCometReceivedDict(session, postDict)

        # need to save session to commit modifications
        session.modified = True
        session.save()

        # flag all threads with this session_key about the new stuff
        # same browser - different tabs
        CometSession.objects.update()
        for comet in CometSession.objects.filter(session_key=skey):
            comet.modified = True
            comet.save()
class SessionTestCase(TestCase):
    def setUp(self):
        self.session = SessionStore()

    def tearDown(self):
        self.session.delete()

    def test_set_and_get(self):
        self.session['spam'] = 'egg'
        self.assertEqual(self.session.get('spam'), 'egg')

    def test_set_and_pop(self):
        self.session['spam'] = 'egg'
        self.assertEqual(self.session.pop('spam'), 'egg')
        self.assertIsNone(self.session.get('spam'))

    def test_pop_no_default_keyerror_raised(self):
        with self.assertRaises(KeyError):
            self.session.pop('spam')

    def test_update(self):
        self.session.update({'update key': 1})
        self.assertEqual(self.session.get('update key', None), 1)

    def test_has_key(self):
        self.session['spam'] = 'egg'
        self.assertIn('spam', self.session)

    def test_values(self):
        self.assertEqual(list(self.session.values()), [])
        self.session['spam'] = 'egg'
        self.assertEqual(list(self.session.values()), ['egg'])

    def test_keys(self):
        self.assertEqual(list(self.session.values()), [])
        self.session['spam'] = 'egg'
        self.assertEqual(list(self.session.keys()), ['spam'])

    def test_items(self):
        self.session['spam'] = 'egg'
        self.assertEqual(list(self.session.items()), [('spam', 'egg')])

    def test_clear(self):
        self.session['spam'] = 'egg'
        self.session.clear()
        self.assertEqual(list(self.session.items()), [])

    def test_save(self):
        self.session.save()
        self.assertIs(self.session.exists(self.session.session_key), True)

    def test_delete(self):
        self.session.save()
        self.session.delete(self.session.session_key)
        self.assertIs(self.session.exists(self.session.session_key), False)

    def test_flush(self):
        self.session['spam'] = 'egg'
        self.session.save()
        prev_key = self.session.session_key
        self.session.flush()
        self.assertNotEqual(self.session.session_key, prev_key)
        self.assertIsNone(self.session.session_key)
示例#6
0
def update_balance(request, update_type, obj=None):
    # 创建主题
    if update_type == 'create':
        # 获取当前用户的id
        uid = request.session.get('user_info')['uid']
        # 设置改变值
        change_balance = -20
        # 类型
        balance_type = "创建主题"
        # 描述
        marks = '创建了的主题 > <a href="{_uri}">{_title}</a>'.format(_uri=reverse('topic', args=(obj.topic_sn,)),
                                                                _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') + change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(
            user_id=uid,
            balance_type=balance_type,
            balance=change_balance,
            marks=marks,
            last_balance=user_obj.balance
        )

        # 更新session 中数据
        request.session['user_info']['balance'] = user_obj.balance

    # 创建回复
    elif update_type == 'reply':
        uid = request.session.get('user_info')['uid']
        change_balance = -5
        balance_type = "创建回复"
        marks = '在主题 > <a href="{_uri}">{_title}</a> 中创建了回复'.format(_uri=reverse('topic', args=(obj.topic_sn,)),
                                                                    _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') + change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(
            user_id=uid,
            balance_type=balance_type,
            balance=change_balance,
            marks=marks,
            last_balance=user_obj.balance
        )

        # 更新session 中数据
        request.session['user_info']['balance'] = user_obj.balance

    # 感谢主题
    elif update_type == 'thanks':
        uid = request.session.get('user_info')['uid']
        change_balance = -15
        balance_type = "发送谢意"
        marks = '感谢 <a href="{_member_uri}">{_author}</a> 的 > <a href="{_uri}">{_title}</a> 主题'.format(
            _member_uri=reverse('member', args=(obj.author.username,)), _author=obj.author.username,
            _uri=reverse('topic', args=(obj.topic_sn,)), _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') + change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(
            user_id=uid,
            balance_type=balance_type,
            balance=change_balance,
            marks=marks,
            last_balance=user_obj.balance
        )

        # 更新session 中数据
        request.session['user_info']['balance'] = user_obj.balance

    # 收到感谢
    elif update_type == 'recv_thanks':
        # 获取基础信息
        uid = obj.author_id
        change_balance = 10
        balance_type = "收到谢意"
        marks = '主题 > <a href="{_uri}">{_title}</a> 收到感谢'.format(_uri=reverse('topic', args=(obj.topic_sn,)),
                                                                 _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') + change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(
            user_id=uid,
            balance_type=balance_type,
            balance=change_balance,
            marks=marks,
            last_balance=user_obj.balance
        )

        # 收到感谢,要查找是谁收到感谢,然后更新此用户的session数据
        session = SessionStore(session_key=obj.author.session)
        # 如果用户在线,才更新
        if session.get('user_info', None):
            session['user_info']['balance'] = user_obj.balance
            # 在外边使用session 要调用save 保存数据
            session.save()

    # 主题收到回复
    elif update_type == 'reply_recv':
        uid = obj.author_id
        change_balance = 5
        balance_type = "主题回复收益"
        marks = '主题 > <a href="{_uri}">{_title}</a> 收到了回复'.format(_uri=reverse('topic', args=(obj.topic_sn,)),
                                                                  _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') + change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(
            user_id=uid,
            balance_type=balance_type,
            balance=change_balance,
            marks=marks,
            last_balance=user_obj.balance
        )

        # 收到回复,要查找是谁收到回复,然后更新此用户的session数据
        session = SessionStore(session_key=obj.author.session)
        if session.get('user_info', None):
            session['user_info']['balance'] = user_obj.balance
            # 在外边使用session 要调用save 保存数据
            session.save()

    # 编辑主题
    elif update_type == 'edit':
        uid = obj.author_id
        change_balance = -5
        balance_type = "编辑主题"
        marks = '编辑了主题 > <a href="{_uri}">{_title}</a>'.format(_uri=reverse('topic', args=(obj.topic_sn,)),
                                                               _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') + change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(
            user_id=uid,
            balance_type=balance_type,
            balance=change_balance,
            marks=marks,
            last_balance=user_obj.balance
        )
        # 更新session 中数据
        request.session['user_info']['balance'] = user_obj.balance
def update_balance(request, update_type, obj=None):
    # 创建话题
    if update_type == 'create':
        # 获取当前用户的id
        uid = request.session.get('user_info')['uid']
        # 设置改变值
        change_balance = -20
        # 类型
        balance_type = "创建话题"
        # 描述
        marks = '创建了新话题 > <a href="{_uri}">{_title}</a>'.format(
            _uri=reverse('topic', args=(obj.topic_sn, )), _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') +
                                                       change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(user_id=uid,
                                   balance_type=balance_type,
                                   balance=change_balance,
                                   marks=marks,
                                   last_balance=user_obj.balance)

        # 更新session 中数据
        request.session['user_info']['balance'] = user_obj.balance

    # 创建回复
    elif update_type == 'reply':
        uid = request.session.get('user_info')['uid']
        change_balance = -5
        balance_type = "创建回复"
        marks = '在话题 > <a href="{_uri}">{_title}</a> 中创建了回复'.format(
            _uri=reverse('topic', args=(obj.topic_sn, )), _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') +
                                                       change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(user_id=uid,
                                   balance_type=balance_type,
                                   balance=change_balance,
                                   marks=marks,
                                   last_balance=user_obj.balance)

        # 更新session 中数据
        request.session['user_info']['balance'] = user_obj.balance

    # 感谢话题
    elif update_type == 'thanks':
        uid = request.session.get('user_info')['uid']
        change_balance = -15
        balance_type = "发送谢意"
        marks = '感谢 <a href="{_member_uri}">{_author}</a> 的 > <a href="{_uri}">{_title}</a> 主题'.format(
            _member_uri=reverse('member', args=(obj.author.username, )),
            _author=obj.author.username,
            _uri=reverse('topic', args=(obj.topic_sn, )),
            _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') +
                                                       change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(user_id=uid,
                                   balance_type=balance_type,
                                   balance=change_balance,
                                   marks=marks,
                                   last_balance=user_obj.balance)

        # 更新session 中数据
        request.session['user_info']['balance'] = user_obj.balance

    # 收到感谢
    elif update_type == 'recv_thanks':
        # 获取基础信息
        uid = obj.author_id
        change_balance = 10
        balance_type = "收到谢意"
        marks = '话题 > <a href="{_uri}">{_title}</a> 收到感谢'.format(
            _uri=reverse('topic', args=(obj.topic_sn, )), _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') +
                                                       change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(user_id=uid,
                                   balance_type=balance_type,
                                   balance=change_balance,
                                   marks=marks,
                                   last_balance=user_obj.balance)

        # 收到感谢,要查找是谁收到感谢,然后更新此用户的session数据
        session = SessionStore(session_key=obj.author.session)
        # 如果用户在线,才更新
        if session.get('user_info', None):
            session['user_info']['balance'] = user_obj.balance
            # 在外边使用session 要调用save 保存数据
            session.save()

    # 话题收到回复
    elif update_type == 'reply_recv':
        uid = obj.author_id
        change_balance = 5
        balance_type = "话题回复收益"
        marks = '话题 > <a href="{_uri}">{_title}</a> 收到了回复'.format(
            _uri=reverse('topic', args=(obj.topic_sn, )), _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') +
                                                       change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(user_id=uid,
                                   balance_type=balance_type,
                                   balance=change_balance,
                                   marks=marks,
                                   last_balance=user_obj.balance)

        # 收到回复,要查找是谁收到回复,然后更新此用户的session数据
        session = SessionStore(session_key=obj.author.session)
        if session.get('user_info', None):
            session['user_info']['balance'] = user_obj.balance
            # 在外边使用session 要调用save 保存数据
            session.save()

    # 编辑话题
    elif update_type == 'edit':
        uid = obj.author_id
        change_balance = -5
        balance_type = "编辑话题"
        marks = '编辑了话题 > <a href="{_uri}">{_title}</a>'.format(
            _uri=reverse('topic', args=(obj.topic_sn, )), _title=obj.title)

        # 更新数据库中的用户余额
        UserDetails.objects.filter(user_id=uid).update(balance=F('balance') +
                                                       change_balance)

        # 获取此用户更新后的balance
        user_obj = UserDetails.objects.filter(user_id=uid).first()

        # 创建余额变动清单
        BalanceInfo.objects.create(user_id=uid,
                                   balance_type=balance_type,
                                   balance=change_balance,
                                   marks=marks,
                                   last_balance=user_obj.balance)
        # 更新session 中数据
        request.session['user_info']['balance'] = user_obj.balance
示例#8
0
    def comet(session_copy):
        # used by more than 1 (note that it is ok to retrieve all of
        # the lists since they are all pointers - not the actual list!
        employees_pending_list_copy =\
            SESSION.get_employees_pending_list(session_copy)
        employees_approved_list_copy =\
            SESSION.get_employees_approved_list(session_copy)
        messages_received_list_copy =\
            SESSION.get_messages_received_list(session_copy)
        redemptions_pending_copy =\
            SESSION.get_redemptions_pending(session_copy)
        redemptions_past_copy =\
            SESSION.get_redemptions_past(session_copy)

        # this is the latest session data
        session = SessionStore(request.session.session_key)
        employees_pending_list =\
            SESSION.get_employees_pending_list(session)
        employees_approved_list =\
            SESSION.get_employees_approved_list(session)
        messages_received_list =\
            SESSION.get_messages_received_list(session)
        redemptions_pending =\
            SESSION.get_redemptions_pending(session)
        redemptions_past =\
            SESSION.get_redemptions_past(session)

        # put the diffs between session_copy and session here
        data = {}

        #############################################################
        # FEEDBACKS_UNREAD ##################################
        fbs_unread_copy = [ fb.objectId for fb in\
            messages_received_list_copy if not fb.is_read ]
        fbs_unread = [ fb.objectId for fb in\
            messages_received_list if not fb.is_read ]

        # get the difference between the two
        feedbacks_unread =\
            tuple(set(fbs_unread) - set(fbs_unread_copy))
        if feedbacks_unread:
            fb_unread = []
            messages_received_ids =\
                [ fb.objectId for fb in messages_received_list ]
            for feedback_id in feedbacks_unread:
                for fb in messages_received_list:
                    if fb.objectId == feedback_id:
                        fb_unread.append(fb.jsonify())
                        break

            if len(fb_unread) > 0:
                fb_count = 0
                for fb in messages_received_list:
                    if not fb.get("is_read"):
                        fb_count += 1
                data['feedbacks_unread'] = fb_unread
                data['feedback_unread_count'] = fb_count

        #############################################################
        # EMPLOYEES_PENDING ##################################
        # must also check if employee is already approved!
        emps_pending_copy = [
            emp.objectId for emp in employees_pending_list_copy
        ]
        emps_pending = [emp.objectId for emp in employees_pending_list]

        employees_pending =\
            tuple(set(emps_pending) - set(emps_pending_copy))

        if employees_pending:
            pending = []
            for emp_id in employees_pending:
                for emp in employees_pending_list:
                    if emp.objectId == emp_id:
                        pending.append(emp.jsonify())
                        break

            if len(pending) > 0:
                data['employees_pending_count'] =\
                    len(employees_pending_list)
                data['employees_pending'] = pending

        #############################################################
        # EMPLOYEES APPROVED (pending to approved) #################
        emps_approved_copy = [ emp.objectId for emp in\
            employees_approved_list_copy]
        emps_approved = [ emp.objectId for emp in\
            employees_approved_list]

        appr_emps =\
            tuple(set(emps_approved) - set(emps_approved_copy))

        if appr_emps:
            approved = []
            for appr_emp_id in appr_emps:
                for emp in employees_approved_list:
                    if emp.objectId == appr_emp_id:
                        approved.append(emp.jsonify())
                        break

            if len(approved) > 0:
                data['employees_approved'] = approved
                data['employees_pending_count'] =\
                    len(employees_pending_list)

        #############################################################
        # EMPLOYEES DELETED/DENIED/REJECTED (pending/approved to pop)!
        # need to compare approved and pending!
        emps_copy = emps_approved_copy[:]
        emps_copy.extend(emps_pending_copy)
        emps = emps_approved[:]
        emps.extend(emps_pending)

        # emps_copy has the same or more items that emps
        del_emps = tuple(set(emps_copy) - set(emps))

        if del_emps:
            deleted = []
            for demp_id in del_emps:
                if demp_id in emps_approved_copy:
                    emps_list = employees_approved_list_copy
                else:
                    emps_list = employees_pending_list_copy

                for emp in emps_list:
                    if emp.objectId == demp_id:
                        deleted.append(emp.jsonify())
                        break

            if len(deleted) > 0:
                data['employees_pending_count'] =\
                    len(employees_pending_list)
                data['employees_deleted'] = deleted

        #############################################################
        # REDEMPTIONS PENDING
        reds_pending_copy = [ r.objectId for r in\
            redemptions_pending_copy ]
        reds_pending = [r.objectId for r in redemptions_pending]

        reds = tuple(set(reds_pending) - set(reds_pending_copy))

        if reds:
            redemps = []
            for r_id in reds:
                for redemp in redemptions_pending:
                    if redemp.objectId == r_id:
                        redemps.append(redemp.jsonify())
                        break

            if len(redemps) > 0:
                data['redemption_pending_count'] =\
                    len(redemptions_pending)
                data['redemptions_pending'] = redemps

        #############################################################
        # REDEMPTIONS APPROVED (pending to history)
        reds_past_copy = [ r.objectId for r in\
            redemptions_past_copy ]
        reds_past = [r.objectId for r in redemptions_past]

        appr_redemps =\
            tuple(set(reds_past) - set(reds_past_copy))

        if appr_redemps:
            redemp_js = []
            for red_id in appr_redemps:
                for redemp in redemptions_past:
                    if redemp.objectId == red_id:
                        redemp_js.append(redemp.jsonify())
                        break

            if len(redemp_js) > 0:
                data['redemption_pending_count'] =\
                    len(redemptions_pending)
                data['redemptions_approved'] = redemp_js

        #############################################################
        # REDEMPTIONS DELETED ##############################
        # remove from pending (should not be in history!)
        reds_copy = reds_past_copy[:]
        reds_copy.extend(reds_pending_copy)
        reds = reds_past[:]
        reds.extend(reds_pending)

        # reds_copy has the same or more items that reds
        del_redemps = tuple(set(reds_copy) - set(reds))
        if del_redemps:
            redemp_js = []
            for red_id in del_redemps:
                reds_list = []
                if red_id in reds_past_copy:
                    reds_list = redemptions_past_copy
                elif red_id in reds_pending_copy:
                    reds_list = redemptions_pending_copy

                for redemp in reds_list:
                    if redemp.objectId == red_id:
                        redemp_js.append(redemp.jsonify())
                        break
            if len(redemp_js) > 0:
                data['redemption_pending_count'] =\
                    len(redemptions_pending)
                data['redemptions_deleted'] = redemp_js

        #############################################################
        # SETTINGS UPDATED ##############################
        settings_copy = session_copy.get("settings")
        settings = session.get("settings")
        if settings_copy.get("retailer_pin") !=\
            settings.get("retailer_pin"):
            data['retailer_pin'] = settings.get("retailer_pin")

        #############################################################
        # REWARDS UPDATED ##############################
        rewards_copy = session_copy.get("store").get("rewards")
        rewards_copy =\
            { reward['reward_id']:reward for reward in rewards_copy }

        rewards = session.get("store").get("rewards")
        rewards = {reward['reward_id']: reward for reward in rewards}
        updated_rewards = []

        for reward_id, rew_copy in rewards_copy.iteritems():
            # Note that some rewards may have been deleted!
            rew = rewards.get(reward_id)
            if rew and rew_copy['redemption_count'] !=\
                rew['redemption_count']:
                # only the redemtpion_count and reward_id are used
                # in the client side
                updated_rewards.append({
                    "reward_id":
                    reward_id,
                    "redemption_count":
                    rew['redemption_count'],
                })

        if updated_rewards:
            data['rewards'] = updated_rewards

        #############################################################
        # PATRONSTORE_COUNT ##################################
        patronStore_count_copy = int(session_copy["patronStore_count"])
        patronStore_count = int(session["patronStore_count"])
        if patronStore_count_copy != patronStore_count:
            data['patronStore_count'] = patronStore_count

        #############################################################
        # ACTIVE_STORE_LOCATION_ID ############################
        if session['active_store_location_id'] !=\
            session_copy['active_store_location_id']:
            data['active_store_location_id'] =\
                session['active_store_location_id']

        # IMPORTANT! The request.session is the same as the
        # SessionStore(session_key)! so we must use the
        # request.session because it is automatically saved at the end
        # of each request- thereby overriding/undoing any changes made
        # to the SessionStore(session_key) key!
        # need to check if we are still logged in
        session = SessionStore(request.session.session_key)
        if 'account' in session and SESSION_KEY in session:
            request.session.clear()
            request.session.update(session)
        else:
            flush(request.session)

        ############################################################
        # Respond ###########################################
        try:
            return HttpResponse(json.dumps(data),
                                content_type="application/json")
        except (IOError, socket.error) as e:  # broken pipe/socket.
            thread.exit()  # exit silently
示例#9
0
    def comet(session_copy):
        # used by more than 1 (note that it is ok to retrieve all of 
        # the lists since they are all pointers - not the actual list!
        employees_pending_list_copy =\
            SESSION.get_employees_pending_list(session_copy)
        employees_approved_list_copy =\
            SESSION.get_employees_approved_list(session_copy)
        messages_received_list_copy =\
            SESSION.get_messages_received_list(session_copy)
        redemptions_pending_copy =\
            SESSION.get_redemptions_pending(session_copy)
        redemptions_past_copy =\
            SESSION.get_redemptions_past(session_copy)
        
        # this is the latest session data
        session = SessionStore(request.session.session_key)
        employees_pending_list =\
            SESSION.get_employees_pending_list(session)
        employees_approved_list =\
            SESSION.get_employees_approved_list(session)
        messages_received_list =\
            SESSION.get_messages_received_list(session)
        redemptions_pending =\
            SESSION.get_redemptions_pending(session)
        redemptions_past =\
            SESSION.get_redemptions_past(session)
        
        # put the diffs between session_copy and session here
        data = {}
        
        #############################################################
        # FEEDBACKS_UNREAD ##################################
        fbs_unread_copy = [ fb.objectId for fb in\
            messages_received_list_copy if not fb.is_read ]
        fbs_unread = [ fb.objectId for fb in\
            messages_received_list if not fb.is_read ]
            
        # get the difference between the two
        feedbacks_unread =\
            tuple(set(fbs_unread) - set(fbs_unread_copy))
        if feedbacks_unread:
            fb_unread = []
            messages_received_ids =\
                [ fb.objectId for fb in messages_received_list ]
            for feedback_id in feedbacks_unread:
                for fb in messages_received_list:
                    if fb.objectId == feedback_id:
                        fb_unread.append(fb.jsonify())
                        break
                
            if len(fb_unread) > 0:
                fb_count = 0
                for fb in messages_received_list:
                    if not fb.get("is_read"):
                        fb_count += 1
                data['feedbacks_unread'] = fb_unread
                data['feedback_unread_count'] = fb_count
          
        #############################################################
        # EMPLOYEES_PENDING ##################################
        # must also check if employee is already approved!
        emps_pending_copy = [ emp.objectId for emp in
            employees_pending_list_copy ]
        emps_pending = [ emp.objectId for emp in
            employees_pending_list ]
            
        employees_pending =\
            tuple(set(emps_pending) - set(emps_pending_copy))
            
        if employees_pending:
            pending = []
            for emp_id in employees_pending:
                for emp in employees_pending_list:
                    if emp.objectId == emp_id:
                        pending.append(emp.jsonify())
                        break
                    
            if len(pending) > 0:   
                data['employees_pending_count'] =\
                    len(employees_pending_list)
                data['employees_pending'] = pending
        
        #############################################################
        # EMPLOYEES APPROVED (pending to approved) #################
        emps_approved_copy = [ emp.objectId for emp in\
            employees_approved_list_copy]
        emps_approved = [ emp.objectId for emp in\
            employees_approved_list]
            
        appr_emps =\
            tuple(set(emps_approved) - set(emps_approved_copy))
        
        if appr_emps:
            approved = []
            for appr_emp_id in appr_emps:
                for emp in employees_approved_list:
                    if emp.objectId == appr_emp_id:
                        approved.append(emp.jsonify())
                        break
                        
            if len(approved) > 0:
                data['employees_approved'] = approved
                data['employees_pending_count'] =\
                    len(employees_pending_list)
            
        #############################################################
        # EMPLOYEES DELETED/DENIED/REJECTED (pending/approved to pop)!
        # need to compare approved and pending!
        emps_copy = emps_approved_copy[:]
        emps_copy.extend(emps_pending_copy)
        emps = emps_approved[:]
        emps.extend(emps_pending)
        
        # emps_copy has the same or more items that emps
        del_emps = tuple(set(emps_copy) - set(emps))
        
        if del_emps:
            deleted = []
            for demp_id in del_emps:
                if demp_id in emps_approved_copy:
                    emps_list = employees_approved_list_copy
                else:
                    emps_list = employees_pending_list_copy
                    
                for emp in emps_list:
                    if emp.objectId == demp_id:
                        deleted.append(emp.jsonify())
                        break  
                        
            if len(deleted) > 0:   
                data['employees_pending_count'] =\
                    len(employees_pending_list)
                data['employees_deleted'] = deleted
           
        #############################################################
        # REDEMPTIONS PENDING
        reds_pending_copy = [ r.objectId for r in\
            redemptions_pending_copy ]
        reds_pending = [ r.objectId for r in redemptions_pending ]
        
        reds = tuple(set(reds_pending) - set(reds_pending_copy))
        
        if reds:
            redemps = []
            for r_id in reds:
                for redemp in redemptions_pending:
                    if redemp.objectId == r_id:
                        redemps.append(redemp.jsonify())
                        break
                        
            if len(redemps) > 0:
                data['redemption_pending_count'] =\
                    len(redemptions_pending)
                data['redemptions_pending'] = redemps
                
        #############################################################
        # REDEMPTIONS APPROVED (pending to history)
        reds_past_copy = [ r.objectId for r in\
            redemptions_past_copy ]
        reds_past = [ r.objectId for r in redemptions_past ]
        
        appr_redemps =\
            tuple(set(reds_past) - set(reds_past_copy))
            
        if appr_redemps:   
            redemp_js = []
            for red_id in appr_redemps:
                for redemp in redemptions_past:
                    if redemp.objectId == red_id:
                        redemp_js.append(redemp.jsonify())
                        break
            
            if len(redemp_js) > 0:
                data['redemption_pending_count'] =\
                    len(redemptions_pending)
                data['redemptions_approved'] = redemp_js
            
        #############################################################
        # REDEMPTIONS DELETED ##############################
        # remove from pending (should not be in history!)
        reds_copy = reds_past_copy[:]
        reds_copy.extend(reds_pending_copy)
        reds = reds_past[:]
        reds.extend(reds_pending)
        
        # reds_copy has the same or more items that reds
        del_redemps = tuple(set(reds_copy) - set(reds))
        if del_redemps:
            redemp_js = []
            for red_id in del_redemps:
                reds_list = []
                if red_id in reds_past_copy:
                    reds_list = redemptions_past_copy
                elif red_id in reds_pending_copy:
                    reds_list = redemptions_pending_copy
                    
                for redemp in reds_list:
                    if redemp.objectId == red_id:
                        redemp_js.append(redemp.jsonify())
                        break               
            if len(redemp_js) > 0:
                data['redemption_pending_count'] =\
                    len(redemptions_pending)
                data['redemptions_deleted'] = redemp_js
            
        #############################################################
        # SETTINGS UPDATED ##############################
        settings_copy = session_copy.get("settings")
        settings = session.get("settings")
        if settings_copy.get("retailer_pin") !=\
            settings.get("retailer_pin"):
            data['retailer_pin'] = settings.get("retailer_pin")
        
        #############################################################
        # REWARDS UPDATED ##############################
        rewards_copy = session_copy.get("store").get("rewards")
        rewards_copy =\
            { reward['reward_id']:reward for reward in rewards_copy }
            
        rewards = session.get("store").get("rewards")
        rewards = { reward['reward_id']:reward for reward in rewards }
        updated_rewards = []
        
        for reward_id, rew_copy in rewards_copy.iteritems():
            # Note that some rewards may have been deleted!
            rew = rewards.get(reward_id)
            if rew and rew_copy['redemption_count'] !=\
                rew['redemption_count']:
                # only the redemtpion_count and reward_id are used
                # in the client side
                updated_rewards.append({
                    "reward_id": reward_id,
                    "redemption_count": rew['redemption_count'],
                })
        
        if updated_rewards:
            data['rewards'] = updated_rewards
           
        #############################################################
        # PATRONSTORE_COUNT ##################################
        patronStore_count_copy =int(session_copy["patronStore_count"])
        patronStore_count = int(session["patronStore_count"])
        if patronStore_count_copy != patronStore_count:
            data['patronStore_count'] = patronStore_count
            
            
        #############################################################
        # ACTIVE_STORE_LOCATION_ID ############################
        if session['active_store_location_id'] !=\
            session_copy['active_store_location_id']:
            data['active_store_location_id'] =\
                session['active_store_location_id']
            

        # IMPORTANT! The request.session is the same as the 
        # SessionStore(session_key)! so we must use the 
        # request.session because it is automatically saved at the end
        # of each request- thereby overriding/undoing any changes made
        # to the SessionStore(session_key) key!
        # need to check if we are still logged in
        session = SessionStore(request.session.session_key)
        if 'account' in session and SESSION_KEY in session:
            request.session.clear()
            request.session.update(session)
        else:
            flush(request.session)
        
        ############################################################
        # Respond ###########################################
        try: 
            return HttpResponse(json.dumps(data), 
                        content_type="application/json")
        except (IOError, socket.error) as e: # broken pipe/socket. 
            thread.exit() # exit silently