Skip to content

Commit

Permalink
Merge branch 'master' of github.com:dgrant/django_kids
Browse files Browse the repository at this point in the history
  • Loading branch information
dgrant committed Mar 6, 2014
2 parents 6740e10 + 5197aeb commit a61ac1e
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 5 deletions.
2 changes: 1 addition & 1 deletion TODO.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
-DONE: Bring over bootstrap stuff from kids.davidgrant.ca
-Get caching working
-Expire entries in the thumbnail url cache over time
-Move title to url
6 changes: 5 additions & 1 deletion links/admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.contrib import admin
from models import Link, Category, Url
from .models import *

class UrlAdmin(admin.ModelAdmin):
fields = ('media_type', 'media_id',)
Expand All @@ -11,6 +11,10 @@ class LinkAdmin(admin.ModelAdmin):
class CategoryAdmin(admin.ModelAdmin):
pass

class MagicTokenAdmin(admin.ModelAdmin):
pass

admin.site.register(Url, UrlAdmin)
admin.site.register(Link, LinkAdmin)
admin.site.register(Category, CategoryAdmin)
admin.site.register(MagicToken, MagicTokenAdmin)
95 changes: 95 additions & 0 deletions links/migrations/0026_auto__add_magictoken.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'MagicToken'
db.create_table(u'links_magictoken', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)),
('magictoken', self.gf('django.db.models.fields.CharField')(max_length=128)),
))
db.send_create_signal(u'links', ['MagicToken'])


def backwards(self, orm):
# Deleting model 'MagicToken'
db.delete_table(u'links_magictoken')


models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'links.category': {
'Meta': {'object_name': 'Category'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'})
},
u'links.link': {
'Meta': {'ordering': "['-ctime']", 'object_name': 'Link'},
'category': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['links.Category']", 'null': 'True', 'blank': 'True'}),
'comment': ('django.db.models.fields.TextField', [], {}),
'ctime': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mtime': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'private': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'url': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['links.Url']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
u'links.magictoken': {
'Meta': {'object_name': 'MagicToken'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'magictoken': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'links.url': {
'Meta': {'ordering': "['media_type', 'media_id']", 'object_name': 'Url'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'media_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
'media_type': ('django.db.models.fields.CharField', [], {'default': "'youtube'", 'max_length': '50'}),
'thumbnail_url': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'})
}
}

complete_apps = ['links']
90 changes: 90 additions & 0 deletions links/migrations/0027_auto__add_unique_magictoken_magictoken.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding unique constraint on 'MagicToken', fields ['magictoken']
db.create_unique(u'links_magictoken', ['magictoken'])


def backwards(self, orm):
# Removing unique constraint on 'MagicToken', fields ['magictoken']
db.delete_unique(u'links_magictoken', ['magictoken'])


models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'links.category': {
'Meta': {'object_name': 'Category'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'})
},
u'links.link': {
'Meta': {'ordering': "['-ctime']", 'object_name': 'Link'},
'category': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['links.Category']", 'null': 'True', 'blank': 'True'}),
'comment': ('django.db.models.fields.TextField', [], {}),
'ctime': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mtime': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'private': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'url': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['links.Url']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
u'links.magictoken': {
'Meta': {'object_name': 'MagicToken'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'magictoken': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'links.url': {
'Meta': {'ordering': "['media_type', 'media_id']", 'object_name': 'Url'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'media_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
'media_type': ('django.db.models.fields.CharField', [], {'default': "'youtube'", 'max_length': '50'}),
'thumbnail_url': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'})
}
}

complete_apps = ['links']
7 changes: 7 additions & 0 deletions links/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@

thumbnail_url_cache = {}

class MagicToken(models.Model):
user = models.OneToOneField(User)
magictoken = models.CharField(max_length=128, unique=True)

def __unicode__(self):
return unicode(self.user)

class Category(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(max_length=50)
Expand Down
5 changes: 5 additions & 0 deletions links/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,8 @@ def test_unicode(self):
self.assertEquals(unicode(link), link.title)


class MagicTokenTest(TestCase):
def test_create(self):
token='adkjupup1343'
magictoken_obj = mommy.make('MagicToken', magictoken=token)
self.assertEquals(magictoken_obj.magictoken, token)
16 changes: 16 additions & 0 deletions links/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@

from links.models import Category, Link, Url

class TestMagicTokenLogin(TestCase):
def test_magic_token_auth_success(self):
authuser = User.objects.create_user('test', password='test')
myuser = mommy.make('MagicToken', magictoken='abc', user=authuser)

url = reverse('magic_token_login', args=['abc'])
resp = self.client.get(url)
self.assertTrue(len(resp.cookies.items()) > 0)
self.assertRedirects(resp, 'http://testserver/links/mylinks/')

def test_magic_token_auth_failure(self):
url = reverse('magic_token_login', args=['abc'])
resp = self.client.get(url)
self.assertTrue(len(resp.cookies.items()) == 0)
self.assertEquals(resp.status_code, 404)

class TestBrowse(TestCase):

def test_non_auth(self):
Expand Down
4 changes: 3 additions & 1 deletion links/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.conf.urls import patterns, include, url
from links.views import LinkList, Browse, LinkAdd
from links.views import LinkList, Browse, LinkAdd, MagicTokenLogin

urlpatterns = patterns('',
url(r'^mylinks/$', LinkList.as_view(), name='mylinks'),
Expand All @@ -10,4 +10,6 @@

url(r'^browse/$', Browse.as_view(), name='browse'),
url(r'^browse/category/(?P<category_slug>\S+)/$', Browse.as_view(), name='browse_category'),

url(r'^magictokenlogin/([0-9a-zA-Z]+)/$', MagicTokenLogin.as_view(), name='magic_token_login'),
)
21 changes: 19 additions & 2 deletions links/views.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.http import HttpResponse, HttpResponseRedirect
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.template import RequestContext
from django.shortcuts import render_to_response, render
from django.views.generic import ListView, CreateView, TemplateView
from django.views.generic.base import View
from django.views.generic.edit import ModelFormMixin
from django.db.models import Q
from django.core.urlresolvers import reverse
from django.contrib.auth import login

from .models import Link, Category, Url
from .models import *
from .forms import LinkForm

class MagicTokenLogin(View):
def get(self, request, token):
try:
magic_token_obj = MagicToken.objects.get(magictoken=token)
except MagicToken.DoesNotExist:
raise Http404

user = magic_token_obj.user
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('mylinks'))
else:
return HttpResponseRedirect(reverse('browse'))

class LinkAdd(CreateView):
model = Link
form_class = LinkForm
Expand Down

0 comments on commit a61ac1e

Please sign in to comment.