added user

This commit is contained in:
Sanj 2011-03-06 18:21:28 +05:30
parent ad4c400bc1
commit 76b66bf959
7 changed files with 635 additions and 0 deletions

0
itf/user/__init__.py Normal file
View File

110
itf/user/models.py Normal file
View File

@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from datetime import datetime
from django.contrib.auth.models import User
from django.db import models
from django.db.models import Max
from ox.django.fields import DictField
#from app.models import site_config
site_config = {
'user': {
'ui': {}
}
}
# from itemlist.models import List, Position
class UserProfile(models.Model):
reset_token = models.TextField(blank=True, null=True)
user = models.ForeignKey(User, unique=True)
# validate_token = models.TextField(blank=True, null=True)
# is_validated = models.BooleanField(default=False)
files_updated = models.DateTimeField(default=datetime.now)
newsletter = models.BooleanField(default=True)
ui = DictField(default={})
preferences = DictField(default={})
def get_preferences(self):
prefs = self.preferences
prefs['email'] = self.user.email
return prefs
def get_ui(self):
ui = {}
config = site_config()
ui.update(config['user']['ui'])
def updateUI(ui, new):
'''
only update set keys in dicts
'''
for key in new:
if isinstance(new[key], dict) and key in ui:
ui[key] = updateUI(ui[key], new[key])
else:
ui[key] = new[key]
return ui
ui = updateUI(ui, self.ui)
if not 'lists' in ui:
ui['lists'] = {}
ui['lists'][''] = config['uiDefaults']['list']
def add(lists, section):
ids = []
for l in lists:
qs = Position.objects.filter(section=section)
if section == 'featured':
try:
pos = Position.objects.get(list=l, section=section)
created = False
except Position.DoesNotExist:
pos = Position(list=l, section=section, user=self.user)
pos.save()
created = True
else:
pos, created = Position.objects.get_or_create(list=l, user=self.user, section=section)
qs = qs.filter(user=self.user)
if created:
pos.position = qs.aggregate(Max('position'))['position__max'] + 1
pos.save()
id = l.get_id()
'''
if id not in ui['lists']:
ui['lists'][id] = {}
ui['lists'][id].update(ui['lists'][''])
'''
ids.append(id)
return ids
ids = ['']
ids += add(self.user.lists.exclude(status="featured"), 'personal')
ids += add(self.user.subscribed_lists.filter(status='public'), 'public')
ids += add(List.objects.filter(status='featured'), 'featured')
for i in ui['lists'].keys():
if i not in ids:
del ui['lists'][i]
return ui
def user_post_save(sender, instance, **kwargs):
profile, new = UserProfile.objects.get_or_create(user=instance)
models.signals.post_save.connect(user_post_save, sender=User)
def get_user_json(user):
# profile = user.get_profile()
result = {}
for key in ('username', ):
result[key] = getattr(user, key)
if user.is_superuser:
result['level'] = 'admin'
elif user.is_staff:
result['level'] = 'staff'
else:
result['level'] = 'member'
result['groups'] = [g.name for g in user.groups.all()]
# result['preferences'] = profile.get_preferences()
# result['ui'] = profile.get_ui()
return result

View File

@ -0,0 +1,4 @@
Hi {{sitename}} admin,
someone sent you a message:
{{message}}

View File

@ -0,0 +1,7 @@
To reset your password, please use the following token:
{{token}}
If you do not want to reset your password, no further action is required.
{{sitename}} - {{url}}

23
itf/user/tests.py Normal file
View File

@ -0,0 +1,23 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

13
itf/user/urls.py Normal file
View File

@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from django.conf.urls.defaults import *
urlpatterns = patterns("user.views",
(r'^preferences', 'preferences'),
(r'^login', 'login'),
(r'^logout', 'logout'),
(r'^register', 'register'),
)

478
itf/user/views.py Normal file
View File

@ -0,0 +1,478 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
import random
random.seed()
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from django.template import RequestContext, loader
from django.utils import simplejson as json
from django.conf import settings
from django.core.mail import send_mail, BadHeaderError
from ox.django.shortcuts import render_to_json_response, json_response
from ox.django.decorators import login_required_json
import ox
import models
from api.actions import actions
from app.models import site_config
from django.db.models import Q
# from item.models import Access, Item
class LoginForm(forms.Form):
usernameOrEmail = forms.TextInput()
password = forms.TextInput()
def signin(request):
'''
param data {
username: 'username',
password: 'password'
}
return {
status: {'code': 200, 'text': 'ok'}
data: {
errors: {
username: 'Unknown Username',
password: 'Incorrect Password'
}
user: {
...
}
}
}
'''
data = json.loads(request.POST['data'])
form = LoginForm(data, request.FILES)
if form.is_valid():
typ = data['usernameOrEmail'][0]['id']
val = data['usernameOrEmail'][1]
qstring = typ + "__iexact"
q = Q(**{qstring:val})
if models.User.objects.filter(q).count == 0:
response = json_response({
'errors': {
'username': 'Unknown Username or E-Mail address'
}
})
else:
if typ == 'email':
uname = models.User.objects.get(email=val).username
else:
uname = val
user = authenticate(username=uname, password=data['password'])
if user is not None:
if user.is_active:
login(request, user)
user_json = models.get_user_json(user)
response = json_response({
'user': user_json
})
else:
response = json_response({
'errors': {
'username': 'User Disabled'
}
})
else:
response = json_response({
'errors': {
'password': 'Incorrect Password'
}
})
else:
response = json_response(status=400, text='invalid data')
return render_to_json_response(response)
actions.register(signin, "login", cache=False)
def signout(request):
'''
param data {
}
return {
status: {'code': int, 'text': string}
data: {
user: {
default user
}
}
}
'''
response = json_response(text='ok')
if request.user.is_authenticated():
response = json_response(text='logged out')
logout(request)
# response['data']['user'] = site_config()['user']
response['data']['user'] = {}
return render_to_json_response(response)
actions.register(signout, "logout", cache=False)
class RegisterForm(forms.Form):
username = forms.TextInput()
password = forms.TextInput()
email = forms.TextInput()
def register(request):
'''
param data {
username: 'username',
password: 'password',
email: 'emailaddress'
}
return {
status: {'code': int, 'text': string}
data: {
errors: {
username: 'Unknown Username',
password: 'Incorrect Password'
}
user: {
...
}
}
}
'''
data = json.loads(request.POST['data'])
form = RegisterForm(data, request.FILES)
if form.is_valid():
if models.User.objects.filter(username=form.data['username']).count() > 0:
response = json_response({
'errors': {
'username': 'Username already exists'
}
})
elif models.User.objects.filter(email=form.data['email']).count() > 0:
response = json_response({
'errors': {
'email': 'Email address already exits'
}
})
elif not form.data['password']:
response = json_response({
'errors': {
'password': 'Password can not be empty'
}
})
else:
first_user = models.User.objects.count() == 0
user = models.User(username=form.data['username'], email=form.data['email'])
user.set_password(form.data['password'])
#make first user admin
user.is_superuser = first_user
user.is_staff = first_user
user.save()
#create default user lists:
'''
for l in settings.DEFAULT_BOXES:
list = models.List(name=l['name'], user=user)
for key in ('query', 'public', 'featured'):
if key in l:
setattr(list, key, l[key])
list.save()
'''
user = authenticate(username=form.data['username'],
password=form.data['password'])
login(request, user)
user_json = models.get_user_json(user)
response = json_response({
'user': user_json
}, text='account created')
else:
response = json_response(status=400, text='invalid data')
return render_to_json_response(response)
actions.register(register, cache=False)
def resetPassword(request):
'''
param data {
token: reset token
password: new password
}
return {
status: {'code': int, 'text': string}
data: {
errors: {
token: 'Invalid token'
}
user {
}
}
}
'''
data = json.loads(request.POST['data'])
if 'token' in data and 'password' in data:
if not data['password']:
response = json_response({
'errors': {
'password': 'Password can not be empty'
}
})
else:
qs = models.UserProfile.objects.filter(reset_token=data['token'])
if qs.count() == 1:
user = qs[0].user
user.set_password(data['password'])
user.save()
user_profile = user.get_profile()
user_profile.reset_token = None
user_profile.save()
user = authenticate(username=user.username, password=data['password'])
login(request, user)
user_json = models.get_user_json(user)
response = json_response({
'user': user_json
}, text='password reset')
else:
response = json_response({
'errors': {
'token': 'Invalid token'
}
})
else:
response = json_response(status=400, text='invalid data')
return render_to_json_response(response)
actions.register(resetPassword, cache=False)
def requestToken(request):
'''
param data {
username: username,
email: email
}
return {
status: {'code': int, 'text': string}
data: {
errors: {
username: 'Unknown Username'
email: 'Unknown Email'
}
username: user
}
}
'''
data = json.loads(request.POST['data'])
user = None
if 'username' in data:
try:
user = models.User.objects.get(username=data['username'])
except models.User.DoesNotExist:
user = None
elif 'email' in data:
try:
user = models.User.objects.get(email=data['email'])
except models.User.DoesNotExist:
user = None
if user:
while True:
token = ox.to32(random.randint(32768, 1048575))
if models.UserProfile.objects.filter(reset_token=token).count() == 0:
break
user_profile = user.get_profile()
user_profile.reset_token = token
user_profile.save()
template = loader.get_template('password_reset_email.txt')
context = RequestContext(request, {
'url': request.build_absolute_uri("/"),
'token': token,
'sitename': settings.SITENAME,
})
message = template.render(context)
subject = '%s - Reset Password' % settings.SITENAME
user.email_user(subject, message)
response = json_response({
'username': user.username
}, text='password reset email sent')
else:
response = json_response({
'errors': {
}
})
if 'username' in data:
response['data']['errors']['username'] = 'Unknown Username'
elif 'email' in data:
response['data']['errors']['email'] = 'Unknown Email'
else:
response = json_response(status=400, text='invalid data')
return render_to_json_response(response)
actions.register(requestToken, cache=False)
def findUser(request):
'''
param data {
key: "username",
value: "foo", operator: "="
}
return {
'status': {'code': int, 'text': string}
'data': {
users = ['user1', 'user2']
}
}
'''
#FIXME: support other operators and keys
data = json.loads(request.POST['data'])
response = json_response(status=200, text='ok')
if data['key'] == 'email':
response['data']['users'] = [u.username for u in User.objects.filter(email__iexact=data['value'])]
else:
response['data']['users'] = [u.username for u in User.objects.filter(username__iexact=data['value'])]
return render_to_json_response(response)
actions.register(findUser)
class ContactForm(forms.Form):
email = forms.EmailField()
subject = forms.TextInput()
message = forms.TextInput()
def contact(request):
'''
param data {
'email': string,
'message': string
}
return {
'status': {'code': int, 'text': string}
}
'''
data = json.loads(request.POST['data'])
form = ContactForm(data, request.FILES)
if form.is_valid():
email = data['email']
template = loader.get_template('contact_email.txt')
context = RequestContext(request, {
'sitename': settings.SITENAME,
'email': email,
'message': data['message'],
})
message = template.render(context)
subject = '%s contact: %s' % (settings.SITENAME, data['subject'])
response = json_response(text='message sent')
try:
send_mail(subject, message, email, [settings.DEFAULT_FROM_EMAIL, ])
except BadHeaderError:
response = json_response(status=400, text='invalid data')
else:
response = json_response(status=400, text='invalid data')
return render_to_json_response(response)
actions.register(contact, cache=False)
def getPositionById(list, key):
for i in range(0, len(list)):
if list[i]['id'] == key:
return i
return -1
@login_required_json
def setPreferences(request):
'''
param data {
key.subkey: value
}
return
'''
data = json.loads(request.POST['data'])
keys = data.keys()[0].split('.')
value = data.values()[0]
profile = request.user.get_profile()
p = profile.preferences
while len(keys)>1:
key = keys.pop(0)
if isinstance(p, list):
p = p[getPositionById(p, key)]
else:
p = p[key]
p[keys[0]] = value
profile.save()
response = json_response()
return render_to_json_response(response)
actions.register(setPreferences, cache=False)
@login_required_json
def resetUI(request):
'''
reset user ui settings to defaults
param data {
}
return {
'status': {'code': int, 'text': string}
}
'''
profile = request.user.get_profile()
profile.ui = {}
profile.save()
response = json_response()
return render_to_json_response(response)
actions.register(resetUI, cache=False)
def setUI(request):
'''
param data {
key.subkey: value
}
you can set nested keys
api.setUI({"lists|my|ListView": "icons"})
return {
'status': {'code': int, 'text': string}
}
'''
data = json.loads(request.POST['data'])
if request.user.is_authenticated():
for key in data:
keys = key.split('|')
value = data[key]
profile = request.user.get_profile()
p = profile.ui
while len(keys)>1:
key = keys.pop(0)
if isinstance(p, list):
p = p[getPositionById(p, key)]
else:
if key not in p:
p[key] = {}
p = p[key]
p[keys[0]] = value
profile.save()
if data.get('item', False):
item = Item.objects.get(itemId=data['item'])
if request.user.is_authenticated():
access, created = Access.objects.get_or_create(item=item, user=request.user)
else:
access, created = Access.objects.get_or_create(item=item, user=None)
access.save()
response = json_response()
return render_to_json_response(response)
actions.register(setUI, cache=False)