diff --git a/pandora/api/views.py b/pandora/api/views.py index 3ceaaf0f..a2c58f65 100644 --- a/pandora/api/views.py +++ b/pandora/api/views.py @@ -13,7 +13,7 @@ from django.db.models import Max, Sum from ox.django.shortcuts import render_to_json_response, json_response from ox.utils import json -from user.models import init_user, get_ui +from user.models import init_user from item.models import ItemSort from actions import actions @@ -69,11 +69,7 @@ def init(request): key['format']['args'][0] = value response['data']['site'] = config - if request.user.is_authenticated(): - response['data']['user'] = init_user(request.user, request) - else: - response['data']['user'] = response['data']['site']['user'] - response['data']['user']['ui'] = get_ui(json.loads(request.session.get('ui', '{}'))) + response['data']['user'] = init_user(request.user, request) return render_to_json_response(response) actions.register(init) diff --git a/pandora/app/config.py b/pandora/app/config.py index a4612a8c..60d28670 100644 --- a/pandora/app/config.py +++ b/pandora/app/config.py @@ -14,6 +14,7 @@ from django.contrib.auth.models import User import ox.jsonc from ox.utils import json + _win = (sys.platform == "win32") RUN_RELOADER = True diff --git a/pandora/user/managers.py b/pandora/user/managers.py index 6a1a0d13..a427f10a 100644 --- a/pandora/user/managers.py +++ b/pandora/user/managers.py @@ -1,16 +1,13 @@ # -*- coding: utf-8 -*- # vi:si:et:sw=4:sts=4:ts=4 -from django.contrib.auth.models import User - -from django.db.models import Q +from django.db.models import Q, Manager +from ox.django.query import QuerySet def parseCondition(condition, user): k = condition.get('key', 'name') k = { - 'firstseen': 'created', - 'lastseen': 'last_login', + 'email': 'user__email', 'user': 'username', - 'name': 'username', }.get(k, k) v = condition['value'] op = condition.get('operator') @@ -61,12 +58,40 @@ def parseConditions(conditions, operator, user): return q return None -def find_user(data, user): - qs = User.objects.all() - query = data.get('query', {}) - conditions = parseConditions(query.get('conditions', []), - query.get('operator', '&'), - user) - if conditions: - qs = qs.filter(conditions) - return qs +class SessionDataManager(Manager): + + def get_query_set(self): + return QuerySet(self.model) + + def find(self, data, user): + ''' + query: { + conditions: [ + { + value: "war" + } + { + key: "year", + value: "1970-1980, + operator: "!=" + }, + { + key: "country", + value: "f", + operator: "^" + } + ], + operator: "&" + } + ''' + + #join query with operator + qs = self.get_query_set() + + query = data.get('query', {}) + conditions = parseConditions(query.get('conditions', []), + query.get('operator', '&'), + user) + if conditions: + qs = qs.filter(conditions) + return qs diff --git a/pandora/user/models.py b/pandora/user/models.py index 2216f118..4c32a39f 100644 --- a/pandora/user/models.py +++ b/pandora/user/models.py @@ -4,6 +4,7 @@ import copy from datetime import datetime from django.contrib.auth.models import User +from django.contrib.sessions.models import Session from django.db import models from django.db.models import Max from django.conf import settings @@ -14,6 +15,86 @@ from ox.utils import json from itemlist.models import List, Position +import managers + +class SessionData(models.Model): + session_key = models.CharField(max_length=40, primary_key=True) + user = models.ForeignKey(User, unique=True, null=True, blank=True, related_name='data') + firstseen = models.DateTimeField(auto_now_add=True, db_index=True) + lastseen = models.DateTimeField(auto_now=True, db_index=True) + username = models.CharField(max_length=255, null=True, db_index=True) + + timesseen = models.IntegerField(default=0) + ip = models.CharField(default='', max_length=255) + useragent = models.CharField(default='', max_length=255) + windowsize = models.CharField(default='', max_length=255) + screensize = models.CharField(default='', max_length=255) + info = DictField(default={}) + + + objects = managers.SessionDataManager() + + def __unicode__(self): + return u"%s" % self.session_key + + def save(self, *args, **kwargs): + if self.user: + self.username = self.user.username + self.firstseen = self.user.date_joined + super(SessionData, self).save(*args, **kwargs) + + @classmethod + def get_or_create(cls, request): + session_key = request.session.session_key + if request.user.is_authenticated(): + cls.objects.filter(user=request.user).update(session_key=session_key) + data, created = cls.objects.get_or_create(session_key=session_key) + if request.user.is_authenticated(): + data.user = request.user + data.info = json.loads(request.POST.get('data', '{}')) + screen = data.info.get('screen', {}) + if 'height' in screen and 'width' in screen: + data.screensize = '%sx%s' % (screen['width'], screen['height']) + window = data.info.get('window', {}) + if 'outerHeight' in window and 'outerWidth' in window: + data.windowsize = '%sx%s' % (window['outerWidth'], window['outerHeight']) + data.ip = request.META['REMOTE_ADDR'] + data.useragent = request.META['HTTP_USER_AGENT'] + if not data.timesseen: + data.timesseen = 0 + data.timesseen += 1 + data.save() + return data + + def json(self, keys=None, user=None): + j = { + 'disabled': False, + 'email': '', + 'firstseen': self.firstseen, + 'ip': self.ip, + 'id': self.user and ox.to26(self.user.id) or self.session_key, + 'lastseen': self.lastseen, + 'level': 'guest', + 'notes': '', + 'numberoflists': 0, + 'screensize': self.screensize, + 'timesseen': self.timesseen, + 'username': self.username or '', + 'useragent': self.useragent, + 'windowsize': self.windowsize, + } + if self.user: + p = self.user.get_profile() + j['disabled'] = not self.user.is_active + j['email'] = self.user.email + j['level'] = p.get_level() + j['notes'] = p.notes + j['numberoflists'] = self.user.lists.count() + if keys: + for key in j.keys(): + if key not in keys: + del j[key] + return j class UserProfile(models.Model): reset_code = models.CharField(max_length=255, blank=True, null=True, unique=True) @@ -25,12 +106,6 @@ class UserProfile(models.Model): ui = DictField(default={}) preferences = DictField(default={}) - timesseen = models.IntegerField(default=0) - ip = models.CharField(default='', max_length=255) - useragent = models.CharField(default='', max_length=255) - windowsize = models.CharField(default='', max_length=255) - screensize = models.CharField(default='', max_length=255) - info = DictField(default={}) notes = models.TextField(default='') def get_ui(self): @@ -105,54 +180,39 @@ def get_ui(user_ui, user=None): del ui['lists'][i] return ui -def user_json(user, keys=None, request_user=None): +def init_user(user, request=None): + data = SessionData.get_or_create(request) + if user.is_anonymous(): + result = settings.CONFIG['user'].copy() + result['ui'] = get_ui(json.loads(request.session.get('ui', '{}'))) + else: + profile = user.get_profile() + result = {} + for key in ('username', ): + result[key] = getattr(user, key) + result['level'] = profile.get_level() + result['groups'] = [g.name for g in user.groups.all()] + result['email'] = user.email + result['ui'] = profile.get_ui() + result['volumes'] = [v.json() for v in user.volumes.all()] + return result + + +def user_json(user, keys=None): p = user.get_profile() j = { 'disabled': not user.is_active, 'email': user.email, 'firstseen': user.date_joined, - 'ip': p.ip, 'id': ox.to26(user.id), 'lastseen': user.last_login, 'level': p.get_level(), 'notes': p.notes, 'numberoflists': user.lists.count(), - 'screensize': p.screensize, - 'timesseen': p.timesseen, 'username': user.username, - 'useragent': p.useragent, - 'windowsize': p.windowsize, } if keys: for key in j.keys(): if key not in keys: del j[key] return j - -def init_user(user, request=None): - profile = user.get_profile() - if request: - data = json.loads(request.POST.get('data', '{}')) - profile.info = data - screen = data.get('screen', {}) - if 'height' in screen and 'width' in screen: - profile.screensize = '%sx%s' % (screen['width'], screen['height']) - window = data.get('window', {}) - if 'outerHeight' in window and 'outerWidth' in window: - profile.windowsize = '%sx%s' % (window['outerWidth'], window['outerHeight']) - profile.ip = request.META['REMOTE_ADDR'] - profile.useragent = request.META['HTTP_USER_AGENT'] - if not profile.timesseen: - profile.timesseen = 0 - profile.timesseen += 1 - profile.save() - result = {} - for key in ('username', ): - result[key] = getattr(user, key) - result['level'] = profile.get_level() - result['groups'] = [g.name for g in user.groups.all()] - result['email'] = user.email - result['ui'] = profile.get_ui() - result['volumes'] = [v.json() for v in user.volumes.all()] - return result - diff --git a/pandora/user/views.py b/pandora/user/views.py index 207d4ac3..667246f7 100644 --- a/pandora/user/views.py +++ b/pandora/user/views.py @@ -340,7 +340,7 @@ def editUser(request): user.username = data['username'] user.save() profile.save() - response['data'] = models.user_json(user) + response['data'] = user.data.get().json() return render_to_json_response(response) actions.register(editUser, cache=False) @@ -403,7 +403,7 @@ def parse_query(data, user): for key in ('keys', 'range', 'sort', 'query'): if key in data: query[key] = data[key] - query['qs'] = managers.find_user(query, user) + query['qs'] = models.SessionData.objects.find(query, user) return query def order_query(qs, sort): @@ -413,21 +413,23 @@ def order_query(qs, sort): if operator != '-': operator = '' key = { - 'email': 'email', - 'firstseen': 'date_joined', - 'lastseen': 'last_login', + 'email': 'user__email', + 'firstseen': 'firstseen', + 'ip': 'ip', + 'lastseen': 'lastseen', + 'screensize': 'screensize', + 'timesseen': 'timesseen', + 'useragent': 'useragent', 'username': 'username', - 'name': 'username', - }.get(e['key'], 'profile__%s'%e['key']) - if key == 'profile__numberoflists': - qs = qs.annotate(numberoflists=Sum('lists')) + 'windowsize': 'windowsize', + }.get(e['key'], 'user__profile__%s'%e['key']) + if key == 'user__profile__numberoflists': + qs = qs.annotate(numberoflists=Sum('user__lists')) key = 'numberoflists' order = '%s%s' % (operator, key) order_by.append(order) if order_by: - #user table does not support this - #qs = qs.order_by(*order_by, nulls_last=True) - qs = qs.order_by(*order_by) + qs = qs.order_by(*order_by, nulls_last=True) return qs @admin_required_json @@ -499,7 +501,7 @@ Positions qs = order_query(query['qs'], query['sort']) if 'keys' in data: qs = qs[query['range'][0]:query['range'][1]] - response['data']['items'] = [models.user_json(p, data['keys'], request.user) for p in qs] + response['data']['items'] = [p.json(data['keys'], request.user) for p in qs] elif 'position' in query: ids = [i.get_id() for i in qs] data['conditions'] = data['conditions'] + { diff --git a/static/js/pandora/usersDialog.js b/static/js/pandora/usersDialog.js index 49feecaf..6319ed0f 100644 --- a/static/js/pandora/usersDialog.js +++ b/static/js/pandora/usersDialog.js @@ -77,9 +77,6 @@ pandora.ui.usersDialog = function() { title: $('').attr({ src: Ox.UI.getImageURL('symbolCheck') }), - tooltip: function(data) { - return data.disabled ? 'Enable User' : 'Disable User'; - }, visible: true, width: 16 }, @@ -221,10 +218,14 @@ pandora.ui.usersDialog = function() { $user.empty(); if (data.ids.length) { values = $list.value(data.ids[0]); - $userLabel.options({ - title: values.username + ' <' + values.email + '>' - }); - $user.append(renderUserForm(values)) + if(values.level != 'guest') { + $userLabel.options({ + title: values.username + ' <' + values.email + '>' + }); + $user.append(renderUserForm(values)); + } else { + $userLabel.options({title: 'Guest'}); + } } else { $userLabel.options({title: 'No user selected'}); } @@ -269,8 +270,10 @@ pandora.ui.usersDialog = function() { .addClass('OxSelectable') .css({margin: '16px'}) .html( - result.data.items.map(function(item) { - return item.username + ' <' + item.email + '>' + result.data.items.filter(function(item) { + return item.email; + }).map(function(item) { + return item.username + ' <' + item.email + '>'; }).join(', ') ), title: 'E-Mail Addresses'