commit
923a79df18
|
@ -3,7 +3,7 @@ from itertools import islice
|
|||
from lxml import etree
|
||||
import datetime
|
||||
import urlparse
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.utils.http import urlquote
|
||||
|
||||
import pytz
|
||||
|
|
|
@ -2,7 +2,7 @@ from itertools import islice
|
|||
|
||||
import datetime
|
||||
import urlparse
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.utils.http import urlquote
|
||||
import json
|
||||
import pytz
|
||||
|
|
|
@ -10,7 +10,7 @@ from tastypie.exceptions import BadRequest
|
|||
from django.conf.urls import url
|
||||
from django.contrib import auth
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
|
||||
from regluit.core import models
|
||||
import regluit.core.isbn
|
||||
|
@ -170,6 +170,7 @@ class FreeResource(ModelResource):
|
|||
return models.Ebook.objects.none()
|
||||
|
||||
class Meta:
|
||||
queryset = models.Ebook.objects.all()
|
||||
authentication = ApiKeyAuthentication()
|
||||
fields = [ 'provider', 'rights' ]
|
||||
limit = 0
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from tastypie.api import Api
|
||||
|
||||
from django.conf.urls import patterns, url, include
|
||||
from django.conf.urls import url, include
|
||||
from django.views.generic.base import TemplateView
|
||||
|
||||
from regluit.api import resources
|
||||
|
|
|
@ -6,7 +6,7 @@ import logging
|
|||
from django.contrib import auth
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.shortcuts import render, render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
@ -152,7 +152,7 @@ class ApiHelpView(TemplateView):
|
|||
|
||||
# if user is logged in, pass in the user's API key
|
||||
u = auth.get_user(self.request)
|
||||
if u.is_authenticated():
|
||||
if u.is_authenticated:
|
||||
api_key = ApiKey.objects.filter(user=u)[0].key
|
||||
context['api_key'] = api_key
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class Migration(migrations.Migration):
|
|||
('rght', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('tree_id', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('level', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('parent', mptt.fields.TreeForeignKey(related_name='children', blank=True, to='bisac.BisacHeading', null=True)),
|
||||
('parent', mptt.fields.TreeForeignKey(on_delete=models.CASCADE, related_name='children', blank=True, to='bisac.BisacHeading', null=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
|
|
|
@ -6,7 +6,7 @@ class BisacHeading(MPTTModel):
|
|||
full_label = models.CharField(max_length=100, unique=True)
|
||||
label = models.CharField(max_length=60, unique=False)
|
||||
notation = models.CharField(max_length=9, unique=False)
|
||||
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
|
||||
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children', db_index=True)
|
||||
|
||||
class MPTTMeta:
|
||||
order_insertion_by = ['notation']
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.conf.urls import patterns, url, include
|
||||
from django.conf.urls import url, include
|
||||
from .views import tree
|
||||
|
||||
urlpatterns = [
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
def is_preview(request):
|
||||
from django.conf import settings
|
||||
return {'jquery_home': settings.JQUERY_HOME, 'jquery_ui_home': settings.JQUERY_UI_HOME, 'is_preview': settings.IS_PREVIEW, 'show_google_analytics': settings.SHOW_GOOGLE_ANALYTICS}
|
||||
|
||||
from django.conf import settings
|
||||
return {
|
||||
'jquery_home': settings.JQUERY_HOME,
|
||||
'jquery_ui_home': settings.JQUERY_UI_HOME,
|
||||
'jquery_ui_theme': settings.JQUERY_UI_THEME,
|
||||
'is_preview': settings.IS_PREVIEW,
|
||||
'show_google_analytics': settings.SHOW_GOOGLE_ANALYTICS
|
||||
}
|
||||
|
||||
def count_unseen(request):
|
||||
|
||||
if request.user.is_anonymous():
|
||||
count = 0
|
||||
else:
|
||||
from notification.models import Notice
|
||||
count = Notice.objects.unseen_count_for(request.user)
|
||||
return {'unseen_count': count}
|
||||
try:
|
||||
if request.user.is_anonymous:
|
||||
count = 0
|
||||
else:
|
||||
from notification.models import Notice
|
||||
count = Notice.objects.unseen_count_for(request.user)
|
||||
except AttributeError:
|
||||
count = 0
|
||||
return {'unseen_count': count}
|
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
from django import forms
|
||||
from django.contrib.admin import ModelAdmin, register
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
|
||||
from selectable.forms import (
|
||||
AutoCompleteSelectWidget,
|
||||
|
|
|
@ -375,6 +375,9 @@ def dl_online(ebook):
|
|||
if ebook.format != 'online':
|
||||
pass
|
||||
elif ebook.url.find(u'dropbox.com/s/') >= 0:
|
||||
if ebook.url.find(u'dl=0') >= 0:
|
||||
dl_url = ebook.url.replace(u'dl=0', u'dl=1')
|
||||
return make_dl_ebook(dl_url, ebook)
|
||||
response = requests.get(ebook.url, headers={"User-Agent": settings.USER_AGENT})
|
||||
if response.status_code == 200:
|
||||
match_dl = DROPBOX_DL.search(response.content)
|
||||
|
|
|
@ -152,7 +152,7 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('type', models.CharField(max_length=4)),
|
||||
('value', models.CharField(max_length=250)),
|
||||
('edition', models.ForeignKey(related_name='identifiers', to='core.Edition', null=True)),
|
||||
('edition', models.ForeignKey(on_delete=models.CASCADE, related_name='identifiers', to='core.Edition', null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -168,7 +168,7 @@ class Migration(migrations.Migration):
|
|||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('marc_link_target', models.CharField(default=b'UNGLUE', max_length=6, verbose_name=b'MARC record link targets', choices=[(b'DIRECT', b'Raw link'), (b'UNGLUE', b'Unglue.it link')])),
|
||||
('user', models.OneToOneField(related_name='libpref', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.OneToOneField(on_delete=models.CASCADE, related_name='libpref', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -189,7 +189,7 @@ class Migration(migrations.Migration):
|
|||
('amount', models.DecimalField(max_digits=10, decimal_places=0)),
|
||||
('description', models.TextField(null=True)),
|
||||
('limit', models.IntegerField(default=0)),
|
||||
('campaign', models.ForeignKey(related_name='premiums', to='core.Campaign', null=True)),
|
||||
('campaign', models.ForeignKey(on_delete=models.CASCADE, related_name='premiums', to='core.Campaign', null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -220,7 +220,7 @@ class Migration(migrations.Migration):
|
|||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('name', models.CharField(unique=True, max_length=255)),
|
||||
('publisher', models.ForeignKey(related_name='alternate_names', to='core.Publisher', null=True)),
|
||||
('publisher', models.ForeignKey(on_delete=models.CASCADE, related_name='alternate_names', to='core.Publisher', null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -235,9 +235,9 @@ class Migration(migrations.Migration):
|
|||
name='Relator',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('author', models.ForeignKey(to='core.Author')),
|
||||
('edition', models.ForeignKey(related_name='relators', to='core.Edition')),
|
||||
('relation', models.ForeignKey(default=1, to='core.Relation')),
|
||||
('author', models.ForeignKey(on_delete=models.CASCADE, to='core.Author')),
|
||||
('edition', models.ForeignKey(on_delete=models.CASCADE, related_name='relators', to='core.Edition')),
|
||||
('relation', models.ForeignKey(on_delete=models.CASCADE, default=1, to='core.Relation')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'core_author_editions',
|
||||
|
@ -251,7 +251,7 @@ class Migration(migrations.Migration):
|
|||
('email', models.CharField(max_length=100, blank=True)),
|
||||
('rights_holder_name', models.CharField(max_length=100)),
|
||||
('can_sell', models.BooleanField(default=False)),
|
||||
('owner', models.ForeignKey(related_name='rights_holder', to=settings.AUTH_USER_MODEL)),
|
||||
('owner', models.ForeignKey(on_delete=models.CASCADE, related_name='rights_holder', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -286,7 +286,7 @@ class Migration(migrations.Migration):
|
|||
('goodreads_user_link', models.CharField(max_length=200, null=True, blank=True)),
|
||||
('avatar_source', models.PositiveSmallIntegerField(default=4, null=True, choices=[(0, b'No Avatar, Please'), (1, b'Gravatar'), (2, b'Twitter'), (3, b'Facebook'), (4, b'Unglueitar')])),
|
||||
('badges', models.ManyToManyField(related_name='holders', to='core.Badge')),
|
||||
('user', models.OneToOneField(related_name='profile', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.OneToOneField(on_delete=models.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -295,7 +295,7 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('was', models.IntegerField(unique=True)),
|
||||
('moved', models.DateTimeField(auto_now_add=True)),
|
||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('user', models.ForeignKey(on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -314,7 +314,7 @@ class Migration(migrations.Migration):
|
|||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('user', models.OneToOneField(related_name='wishlist', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.OneToOneField(on_delete=models.CASCADE, related_name='wishlist', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -330,7 +330,7 @@ class Migration(migrations.Migration):
|
|||
('publication_range', models.CharField(max_length=50, null=True)),
|
||||
('featured', models.DateTimeField(db_index=True, null=True, blank=True)),
|
||||
('is_free', models.BooleanField(default=False)),
|
||||
('selected_edition', models.ForeignKey(related_name='selected_works', to='core.Edition', null=True)),
|
||||
('selected_edition', models.ForeignKey(on_delete=models.CASCADE, related_name='selected_works', to='core.Edition', null=True)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['title'],
|
||||
|
@ -344,17 +344,17 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='wishes',
|
||||
name='wishlist',
|
||||
field=models.ForeignKey(to='core.Wishlist'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, to='core.Wishlist'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='wishes',
|
||||
name='work',
|
||||
field=models.ForeignKey(related_name='wishes', to='core.Work'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='wishes', to='core.Work'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='waswork',
|
||||
name='work',
|
||||
field=models.ForeignKey(to='core.Work'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, to='core.Work'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subject',
|
||||
|
@ -364,16 +364,16 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='publisher',
|
||||
name='name',
|
||||
field=models.ForeignKey(related_name='key_publisher', to='core.PublisherName'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='key_publisher', to='core.PublisherName'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='offer',
|
||||
name='work',
|
||||
field=models.ForeignKey(related_name='offers', to='core.Work'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='offers', to='core.Work'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='identifier',
|
||||
name='work',
|
||||
field=models.ForeignKey(related_name='identifiers', to='core.Work'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='identifiers', to='core.Work'),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -18,82 +18,82 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='hold',
|
||||
name='library',
|
||||
field=models.ForeignKey(related_name='holds', to='libraryauth.Library'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='holds', to='libraryauth.Library'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='hold',
|
||||
name='user',
|
||||
field=models.ForeignKey(related_name='holds', to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='holds', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='hold',
|
||||
name='work',
|
||||
field=models.ForeignKey(related_name='holds', to='core.Work'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='holds', to='core.Work'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='gift',
|
||||
name='acq',
|
||||
field=models.ForeignKey(related_name='gifts', to='core.Acq'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='gifts', to='core.Acq'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='gift',
|
||||
name='giver',
|
||||
field=models.ForeignKey(related_name='gifts', to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='gifts', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='edition',
|
||||
name='publisher_name',
|
||||
field=models.ForeignKey(related_name='editions', to='core.PublisherName', null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='editions', to='core.PublisherName', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='edition',
|
||||
name='work',
|
||||
field=models.ForeignKey(related_name='editions', to='core.Work', null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='editions', to='core.Work', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ebookfile',
|
||||
name='edition',
|
||||
field=models.ForeignKey(related_name='ebook_files', to='core.Edition'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='ebook_files', to='core.Edition'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ebook',
|
||||
name='edition',
|
||||
field=models.ForeignKey(related_name='ebooks', to='core.Edition'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='ebooks', to='core.Edition'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ebook',
|
||||
name='user',
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='claim',
|
||||
name='rights_holder',
|
||||
field=models.ForeignKey(related_name='claim', to='core.RightsHolder'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='claim', to='core.RightsHolder'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='claim',
|
||||
name='user',
|
||||
field=models.ForeignKey(related_name='claim', to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='claim', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='claim',
|
||||
name='work',
|
||||
field=models.ForeignKey(related_name='claim', to='core.Work'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='claim', to='core.Work'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='celerytask',
|
||||
name='user',
|
||||
field=models.ForeignKey(related_name='tasks', to=settings.AUTH_USER_MODEL, null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='tasks', to=settings.AUTH_USER_MODEL, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='campaignaction',
|
||||
name='campaign',
|
||||
field=models.ForeignKey(related_name='actions', to='core.Campaign'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='actions', to='core.Campaign'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='campaign',
|
||||
name='edition',
|
||||
field=models.ForeignKey(related_name='campaigns', to='core.Edition', null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='campaigns', to='core.Edition', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='campaign',
|
||||
|
@ -103,12 +103,12 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='campaign',
|
||||
name='publisher',
|
||||
field=models.ForeignKey(related_name='campaigns', to='core.Publisher', null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='campaigns', to='core.Publisher', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='campaign',
|
||||
name='work',
|
||||
field=models.ForeignKey(related_name='campaigns', to='core.Work'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='campaigns', to='core.Work'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='author',
|
||||
|
@ -118,22 +118,22 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='acq',
|
||||
name='lib_acq',
|
||||
field=models.ForeignKey(related_name='loans', to='core.Acq', null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='loans', to='core.Acq', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='acq',
|
||||
name='user',
|
||||
field=models.ForeignKey(related_name='acqs', to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='acqs', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='acq',
|
||||
name='watermarked',
|
||||
field=models.ForeignKey(to='booxtream.Boox', null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, to='booxtream.Boox', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='acq',
|
||||
name='work',
|
||||
field=models.ForeignKey(related_name='acqs', to='core.Work'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='acqs', to='core.Work'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='identifier',
|
||||
|
|
|
@ -38,17 +38,17 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='workrelation',
|
||||
name='from_work',
|
||||
field=models.ForeignKey(related_name='works_related_from', to='core.Work'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='works_related_from', to='core.Work'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workrelation',
|
||||
name='to_work',
|
||||
field=models.ForeignKey(related_name='works_related_to', to='core.Work'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='works_related_to', to='core.Work'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='edition',
|
||||
name='note',
|
||||
field=models.ForeignKey(to='core.EditionNote', null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, to='core.EditionNote', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='work',
|
||||
|
|
|
@ -14,6 +14,6 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='ebookfile',
|
||||
name='ebook',
|
||||
field=models.ForeignKey(related_name='ebook_files', to='core.Ebook', null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='ebook_files', to='core.Ebook', null=True),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -28,12 +28,12 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='edition',
|
||||
name='note',
|
||||
field=models.ForeignKey(blank=True, to='core.EditionNote', null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, blank=True, to='core.EditionNote', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='edition',
|
||||
name='publisher_name',
|
||||
field=models.ForeignKey(related_name='editions', blank=True, to='core.PublisherName', null=True),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='editions', blank=True, to='core.PublisherName', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userprofile',
|
||||
|
|
|
@ -22,7 +22,7 @@ from django.conf import settings
|
|||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.models import Site
|
||||
from django.contrib.contenttypes.fields import GenericRelation
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.core.files.base import ContentFile
|
||||
from django.db import models
|
||||
from django.db.models import F, Q
|
||||
|
@ -122,7 +122,7 @@ class Key(models.Model):
|
|||
class CeleryTask(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
task_id = models.CharField(max_length=255)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="tasks", null=True)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="tasks", null=True)
|
||||
description = models.CharField(max_length=2048, null=True) # a description of what the task is
|
||||
function_name = models.CharField(max_length=1024) # used to reconstitute the AsyncTask with which to get status
|
||||
function_args = models.IntegerField(null=True) # not full generalized here -- takes only a single arg for now.
|
||||
|
@ -157,7 +157,7 @@ class Premium(models.Model):
|
|||
TIERS = {"supporter":25, "patron":50, "bibliophile":100} #should load this from fixture
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
type = models.CharField(max_length=2, choices=PREMIUM_TYPES)
|
||||
campaign = models.ForeignKey("Campaign", related_name="premiums", null=True)
|
||||
campaign = models.ForeignKey("Campaign", on_delete=models.CASCADE, related_name="premiums", null=True)
|
||||
amount = models.DecimalField(max_digits=10, decimal_places=0, blank=False)
|
||||
description = models.TextField(null=True, blank=False)
|
||||
limit = models.IntegerField(default=0)
|
||||
|
@ -189,10 +189,10 @@ class CampaignAction(models.Model):
|
|||
# anticipated types: activated, withdrawn, suspended, restarted, succeeded, failed, unglued
|
||||
type = models.CharField(max_length=15)
|
||||
comment = models.TextField(null=True, blank=True)
|
||||
campaign = models.ForeignKey("Campaign", related_name="actions", null=False)
|
||||
campaign = models.ForeignKey("Campaign", on_delete=models.CASCADE, related_name="actions", null=False)
|
||||
|
||||
class Offer(models.Model):
|
||||
work = models.ForeignKey("Work", related_name="offers", null=False)
|
||||
work = models.ForeignKey("Work", on_delete=models.CASCADE, related_name="offers", null=False)
|
||||
price = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=False)
|
||||
license = models.PositiveSmallIntegerField(null=False, default=INDIVIDUAL,
|
||||
choices=OFFER_CHOICES)
|
||||
|
@ -218,15 +218,15 @@ class Acq(models.Model):
|
|||
expires = models.DateTimeField(null=True)
|
||||
refreshes = models.DateTimeField(auto_now_add=True)
|
||||
refreshed = models.BooleanField(default=True)
|
||||
work = models.ForeignKey("Work", related_name='acqs', null=False)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='acqs')
|
||||
work = models.ForeignKey("Work", on_delete=models.CASCADE, related_name='acqs', null=False)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='acqs')
|
||||
license = models.PositiveSmallIntegerField(null=False, default=INDIVIDUAL,
|
||||
choices=ACQ_CHOICES)
|
||||
watermarked = models.ForeignKey("booxtream.Boox", null=True)
|
||||
watermarked = models.ForeignKey("booxtream.Boox", on_delete=models.CASCADE, null=True)
|
||||
nonce = models.CharField(max_length=32, null=True)
|
||||
|
||||
# when the acq is a loan, this points at the library's acq it's derived from
|
||||
lib_acq = models.ForeignKey("self", related_name="loans", null=True)
|
||||
lib_acq = models.ForeignKey("self", on_delete=models.CASCADE, related_name="loans", null=True)
|
||||
|
||||
class mock_ebook(object):
|
||||
def __init__(self, acq):
|
||||
|
@ -358,9 +358,9 @@ post_save.connect(config_acq, sender=Acq)
|
|||
|
||||
class Hold(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
work = models.ForeignKey("Work", related_name='holds', null=False)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='holds', null=False)
|
||||
library = models.ForeignKey(Library, related_name='holds', null=False)
|
||||
work = models.ForeignKey("Work", on_delete=models.CASCADE, related_name='holds', null=False)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='holds', null=False)
|
||||
library = models.ForeignKey(Library, on_delete=models.CASCADE, related_name='holds', null=False)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s for %s at %s' % (self.work, self.user.username, self.library)
|
||||
|
@ -390,8 +390,8 @@ class Campaign(models.Model):
|
|||
activated = models.DateTimeField(null=True, db_index=True,)
|
||||
paypal_receiver = models.CharField(max_length=100, blank=True)
|
||||
amazon_receiver = models.CharField(max_length=100, blank=True)
|
||||
work = models.ForeignKey("Work", related_name="campaigns", null=False)
|
||||
managers = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="campaigns", null=False)
|
||||
work = models.ForeignKey("Work", on_delete=models.CASCADE, related_name="campaigns", null=False)
|
||||
managers = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="campaigns")
|
||||
# status: INITIALIZED, ACTIVE, SUSPENDED, WITHDRAWN, SUCCESSFUL, UNSUCCESSFUL
|
||||
status = models.CharField( max_length=15, null=True, blank=False, default="INITIALIZED",
|
||||
db_index=True, choices=STATUS_CHOICES)
|
||||
|
@ -400,9 +400,9 @@ class Campaign(models.Model):
|
|||
(BUY2UNGLUE, 'Buy-to-unglue campaign'),
|
||||
(THANKS, 'Thanks-for-ungluing campaign'),
|
||||
))
|
||||
edition = models.ForeignKey("Edition", related_name="campaigns", null=True)
|
||||
edition = models.ForeignKey("Edition", on_delete=models.CASCADE, related_name="campaigns", null=True)
|
||||
email = models.CharField(max_length=100, blank=True)
|
||||
publisher = models.ForeignKey("Publisher", related_name="campaigns", null=True)
|
||||
publisher = models.ForeignKey("Publisher", on_delete=models.CASCADE, related_name="campaigns", null=True)
|
||||
do_watermark = models.BooleanField(default=True)
|
||||
use_add_ask = models.BooleanField(default=True)
|
||||
charitable = models.BooleanField(default=False)
|
||||
|
@ -442,7 +442,7 @@ class Campaign(models.Model):
|
|||
self.activated = None
|
||||
self.update_left()
|
||||
self.save()
|
||||
self.managers = old_managers
|
||||
self.managers.set(old_managers)
|
||||
|
||||
# clone associated premiums
|
||||
for premium in new_premiums:
|
||||
|
@ -1034,7 +1034,7 @@ class Campaign(models.Model):
|
|||
rights=self.license,
|
||||
provider="Unglue.it",
|
||||
url=settings.BASE_URL_SECURE + reverse('download_campaign', args=[self.work_id, format]),
|
||||
version='unglued',
|
||||
version_label='unglued',
|
||||
)
|
||||
old_ebooks = Ebook.objects.exclude(pk=ebook.pk).filter(
|
||||
edition=self.work.preferred_edition,
|
||||
|
@ -1084,7 +1084,7 @@ class Campaign(models.Model):
|
|||
|
||||
class Wishlist(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='wishlist')
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='wishlist')
|
||||
works = models.ManyToManyField('Work', related_name='wishlists', through='Wishes')
|
||||
|
||||
def __unicode__(self):
|
||||
|
@ -1117,8 +1117,8 @@ class Wishlist(models.Model):
|
|||
class Wishes(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True, db_index=True,)
|
||||
source = models.CharField(max_length=15, blank=True, db_index=True,)
|
||||
wishlist = models.ForeignKey('Wishlist')
|
||||
work = models.ForeignKey('Work', related_name='wishes')
|
||||
wishlist = models.ForeignKey('Wishlist', on_delete=models.CASCADE)
|
||||
work = models.ForeignKey('Work', on_delete=models.CASCADE, related_name='wishes')
|
||||
class Meta:
|
||||
db_table = 'core_wishlist_works'
|
||||
|
||||
|
@ -1148,7 +1148,7 @@ ANONYMOUS_AVATAR = '/static/images/header/avatar.png'
|
|||
(NO_AVATAR, GRAVATAR, TWITTER, FACEBOOK, UNGLUEITAR) = AVATARS
|
||||
|
||||
class Libpref(models.Model):
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='libpref')
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='libpref')
|
||||
marc_link_target = models.CharField(
|
||||
max_length=6,
|
||||
default='UNGLUE',
|
||||
|
@ -1158,7 +1158,7 @@ class Libpref(models.Model):
|
|||
|
||||
class UserProfile(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='profile')
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='profile')
|
||||
tagline = models.CharField(max_length=140, blank=True)
|
||||
pic_url = models.URLField(blank=True)
|
||||
home_url = models.URLField(blank=True)
|
||||
|
@ -1354,9 +1354,9 @@ class Press(models.Model):
|
|||
|
||||
class Gift(models.Model):
|
||||
# the acq will contain the recipient, and the work
|
||||
acq = models.ForeignKey('Acq', related_name='gifts')
|
||||
acq = models.ForeignKey('Acq', on_delete=models.CASCADE, related_name='gifts')
|
||||
to = models.CharField(max_length=75, blank=True) # store the email address originally sent to, not necessarily the email of the recipient
|
||||
giver = models.ForeignKey(User, related_name='gifts')
|
||||
giver = models.ForeignKey(User, on_delete=models.CASCADE, related_name='gifts')
|
||||
message = models.TextField(max_length=512, default='')
|
||||
used = models.DateTimeField(null=True)
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ from django.conf import settings
|
|||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.fields import GenericRelation
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.db import models
|
||||
from django.db.models import F
|
||||
from django.db.models.signals import post_save, pre_delete
|
||||
|
@ -67,8 +67,8 @@ class Identifier(models.Model):
|
|||
# olib, ltwk, goog, gdrd, thng, isbn, oclc, olwk, doab, gtbg, glue, doi
|
||||
type = models.CharField(max_length=4, null=False)
|
||||
value = models.CharField(max_length=250, null=False)
|
||||
work = models.ForeignKey("Work", related_name="identifiers", null=False)
|
||||
edition = models.ForeignKey("Edition", related_name="identifiers", null=True)
|
||||
work = models.ForeignKey("Work", on_delete=models.CASCADE, related_name="identifiers", null=False)
|
||||
edition = models.ForeignKey("Edition", on_delete=models.CASCADE, related_name="identifiers", null=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ("type", "value")
|
||||
|
@ -122,7 +122,7 @@ class Work(models.Model):
|
|||
openlibrary_lookup = models.DateTimeField(null=True, blank=True)
|
||||
num_wishes = models.IntegerField(default=0, db_index=True)
|
||||
description = models.TextField(default='', null=True, blank=True)
|
||||
selected_edition = models.ForeignKey("Edition", related_name='selected_works', null=True)
|
||||
selected_edition = models.ForeignKey("Edition", on_delete=models.CASCADE, related_name='selected_works', null=True)
|
||||
# repurposed earliest_publication to actually be publication range
|
||||
publication_range = models.CharField(max_length=50, null=True, blank=True)
|
||||
featured = models.DateTimeField(null=True, blank=True, db_index=True,)
|
||||
|
@ -612,7 +612,7 @@ class Work(models.Model):
|
|||
return self.get_user_license(lib_user)
|
||||
|
||||
def borrowable(self, user):
|
||||
if user.is_anonymous():
|
||||
if user.is_anonymous:
|
||||
return False
|
||||
lib_license = self.get_lib_license(user)
|
||||
if lib_license and lib_license.borrowable:
|
||||
|
@ -620,7 +620,7 @@ class Work(models.Model):
|
|||
return False
|
||||
|
||||
def lib_thanked(self, user):
|
||||
if user.is_anonymous():
|
||||
if user.is_anonymous:
|
||||
return False
|
||||
lib_license = self.get_lib_license(user)
|
||||
if lib_license and lib_license.thanked:
|
||||
|
@ -628,7 +628,7 @@ class Work(models.Model):
|
|||
return False
|
||||
|
||||
def in_library(self, user):
|
||||
if user.is_anonymous():
|
||||
if user.is_anonymous:
|
||||
return False
|
||||
lib_license = self.get_lib_license(user)
|
||||
if lib_license and lib_license.acqs.count():
|
||||
|
@ -706,7 +706,7 @@ class Work(models.Model):
|
|||
if user is None:
|
||||
return None
|
||||
if hasattr(user, 'is_anonymous'):
|
||||
if user.is_anonymous():
|
||||
if user.is_anonymous:
|
||||
return None
|
||||
return self.user_license(self.acqs.filter(user=user))
|
||||
else:
|
||||
|
@ -732,8 +732,8 @@ class Work(models.Model):
|
|||
return record_list
|
||||
|
||||
class WorkRelation(models.Model):
|
||||
to_work = models.ForeignKey('Work', related_name='works_related_to')
|
||||
from_work= models.ForeignKey('Work', related_name='works_related_from')
|
||||
to_work = models.ForeignKey('Work', on_delete=models.CASCADE, related_name='works_related_to')
|
||||
from_work= models.ForeignKey('Work', on_delete=models.CASCADE, related_name='works_related_from')
|
||||
relation = models.CharField(max_length=15, choices=TEXT_RELATION_CHOICES)
|
||||
|
||||
|
||||
|
@ -766,9 +766,9 @@ class Relation(models.Model):
|
|||
name = models.CharField(max_length=30, blank=True,)
|
||||
|
||||
class Relator(models.Model):
|
||||
relation = models.ForeignKey('Relation', default=1) #first relation should have code='aut'
|
||||
author = models.ForeignKey('Author')
|
||||
edition = models.ForeignKey('Edition', related_name='relators')
|
||||
relation = models.ForeignKey('Relation', on_delete=models.CASCADE, default=1) #first relation should have code='aut'
|
||||
author = models.ForeignKey('Author', on_delete=models.CASCADE)
|
||||
edition = models.ForeignKey('Edition', on_delete=models.CASCADE, related_name='relators')
|
||||
class Meta:
|
||||
db_table = 'core_author_editions'
|
||||
|
||||
|
@ -846,12 +846,12 @@ class Subject(models.Model):
|
|||
class Edition(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
title = models.CharField(max_length=1000)
|
||||
publisher_name = models.ForeignKey("PublisherName", related_name="editions", null=True, blank=True)
|
||||
publisher_name = models.ForeignKey("PublisherName", on_delete=models.CASCADE, related_name="editions", null=True, blank=True)
|
||||
publication_date = models.CharField(max_length=50, null=True, blank=True, db_index=True)
|
||||
work = models.ForeignKey("Work", related_name="editions", null=True)
|
||||
work = models.ForeignKey("Work", on_delete=models.CASCADE, related_name="editions", null=True)
|
||||
cover_image = models.URLField(null=True, blank=True)
|
||||
unglued = models.BooleanField(default=False)
|
||||
note = models.ForeignKey("EditionNote", null=True, blank=True)
|
||||
note = models.ForeignKey("EditionNote", on_delete=models.CASCADE, null=True, blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
if self.isbn_13:
|
||||
|
@ -1034,7 +1034,7 @@ class EditionNote(models.Model):
|
|||
|
||||
class Publisher(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
name = models.ForeignKey('PublisherName', related_name='key_publisher')
|
||||
name = models.ForeignKey('PublisherName', on_delete=models.CASCADE, related_name='key_publisher')
|
||||
url = models.URLField(max_length=1024, null=True, blank=True)
|
||||
logo_url = models.URLField(max_length=1024, null=True, blank=True)
|
||||
description = models.TextField(default='', null=True, blank=True)
|
||||
|
@ -1045,7 +1045,7 @@ class Publisher(models.Model):
|
|||
class PublisherName(models.Model):
|
||||
name = models.CharField(max_length=255, blank=False, unique=True)
|
||||
|
||||
publisher = models.ForeignKey('Publisher', related_name='alternate_names', null=True)
|
||||
publisher = models.ForeignKey('Publisher', on_delete=models.CASCADE, related_name='alternate_names', null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
@ -1060,10 +1060,10 @@ class PublisherName(models.Model):
|
|||
|
||||
|
||||
class WasWork(models.Model):
|
||||
work = models.ForeignKey('Work')
|
||||
work = models.ForeignKey('Work', on_delete=models.CASCADE)
|
||||
was = models.IntegerField(unique=True)
|
||||
moved = models.DateTimeField(auto_now_add=True)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
|
||||
|
||||
def safe_get_work(work_id):
|
||||
"""
|
||||
|
@ -1087,10 +1087,10 @@ def path_for_file(instance, filename):
|
|||
class EbookFile(models.Model):
|
||||
file = models.FileField(upload_to=path_for_file)
|
||||
format = models.CharField(max_length=25, choices=settings.FORMATS)
|
||||
edition = models.ForeignKey('Edition', related_name='ebook_files')
|
||||
edition = models.ForeignKey('Edition', on_delete=models.CASCADE, related_name='ebook_files')
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
asking = models.BooleanField(default=False)
|
||||
ebook = models.ForeignKey('Ebook', related_name='ebook_files', null=True)
|
||||
ebook = models.ForeignKey('Ebook', on_delete=models.CASCADE, related_name='ebook_files', null=True)
|
||||
source = models.URLField(null=True, blank=True)
|
||||
mobied = models.IntegerField(default=0) #-1 indicates a failed conversion attempt
|
||||
version = None
|
||||
|
@ -1157,8 +1157,8 @@ class Ebook(models.Model):
|
|||
|
||||
# use 'PD-US', 'CC BY', 'CC BY-NC-SA', 'CC BY-NC-ND', 'CC BY-NC', 'CC BY-ND', 'CC BY-SA', 'CC0'
|
||||
rights = models.CharField(max_length=255, null=True, choices=cc.CHOICES, db_index=True)
|
||||
edition = models.ForeignKey('Edition', related_name='ebooks')
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
|
||||
edition = models.ForeignKey('Edition', on_delete=models.CASCADE, related_name='ebooks')
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
|
||||
|
||||
def kindle_sendable(self):
|
||||
if not self.filesize or self.filesize < send_to_kindle_limit:
|
||||
|
|
|
@ -13,9 +13,9 @@ class Claim(models.Model):
|
|||
(u'release', u'Claim has not been accepted.'),
|
||||
)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
rights_holder = models.ForeignKey("RightsHolder", related_name="claim", null=False)
|
||||
work = models.ForeignKey("Work", related_name="claim", null=False)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="claim", null=False)
|
||||
rights_holder = models.ForeignKey("RightsHolder", on_delete=models.CASCADE, related_name="claim", null=False)
|
||||
work = models.ForeignKey("Work", on_delete=models.CASCADE, related_name="claim", null=False)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="claim", null=False)
|
||||
status = models.CharField(max_length=7, choices=STATUSES, default='active')
|
||||
|
||||
@property
|
||||
|
@ -66,7 +66,7 @@ class RightsHolder(models.Model):
|
|||
created = models.DateTimeField(auto_now_add=True)
|
||||
email = models.CharField(max_length=100, blank=False, default='')
|
||||
rights_holder_name = models.CharField(max_length=100, blank=False)
|
||||
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="rights_holder", null=False)
|
||||
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="rights_holder", null=False)
|
||||
approved = models.BooleanField(default=False)
|
||||
address = models.CharField(max_length=400, blank=False, default='')
|
||||
mailing = models.CharField(max_length=400, blank=False, default='')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.contrib.sitemaps import Sitemap
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from regluit.core.models import Work, Edition
|
||||
|
||||
class WorkSitemap(Sitemap):
|
||||
|
|
|
@ -41,6 +41,6 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='deposit',
|
||||
name='target',
|
||||
field=models.ForeignKey(related_name='deposits', to='distro.Target'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='deposits', to='distro.Target'),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -57,7 +57,7 @@ class Target(models.Model):
|
|||
|
||||
|
||||
class Deposit(models.Model):
|
||||
target = models.ForeignKey(Target, related_name="deposits")
|
||||
target = models.ForeignKey(Target, on_delete=models.CASCADE, related_name="deposits")
|
||||
isbn = models.CharField(max_length=13)
|
||||
format = models.CharField(max_length=30)
|
||||
updated = models.DateTimeField(auto_now_add=True)
|
||||
|
|
|
@ -12,8 +12,7 @@ from decimal import Decimal as D
|
|||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.forms.widgets import RadioSelect
|
||||
from django.forms.extras.widgets import SelectDateWidget
|
||||
from django.forms.widgets import RadioSelect, SelectDateWidget
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from selectable.forms import (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from datetime import date, timedelta
|
||||
from decimal import Decimal as D
|
||||
|
||||
from ckeditor.widgets import CKEditorWidget
|
||||
from ckeditor_uploader.widgets import CKEditorUploadingWidget
|
||||
|
||||
from selectable.forms import (
|
||||
AutoCompleteSelectMultipleWidget,
|
||||
|
@ -10,8 +10,7 @@ from selectable.forms import (
|
|||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.forms.extras.widgets import SelectDateWidget
|
||||
from django.forms.widgets import RadioSelect
|
||||
from django.forms.widgets import RadioSelect, SelectDateWidget
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.timezone import now
|
||||
|
||||
|
@ -215,7 +214,7 @@ class ManageCampaignForm(CCDateForm, forms.ModelForm):
|
|||
'required': 'You must enter the email we should contact you at for this campaign.'
|
||||
},
|
||||
)
|
||||
work_description = forms.CharField(required=False , widget=CKEditorWidget())
|
||||
work_description = forms.CharField(required=False , widget=CKEditorUploadingWidget())
|
||||
|
||||
class Meta:
|
||||
model = Campaign
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% block title %} Agreement Submitted {% endblock %}
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
<script type="text/javascript" src="{{ jquery_ui_home }}"></script>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
{% load truncatechars %}{% load sass_tags %}
|
||||
{% load sass_tags %}
|
||||
|
||||
<html>
|
||||
<head>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
{{ form.media.css }}
|
||||
<script type="text/javascript" src="{{ jquery_ui_home }}"></script>
|
||||
{{ form.media.js }}
|
||||
|
|
|
@ -6,6 +6,8 @@ var $j = jQuery.noConflict();
|
|||
$j(document).ready(function() {
|
||||
// don't let users modify their pledge amount on this page; it's just here for reference
|
||||
// if they modified it here we'd have to faff about with validating premiums
|
||||
if($j('#id_work_id').prop('value')!=""){
|
||||
$j('#id_preapproval_amount').prop('disabled', true);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
<link href="/static/css/ui.fancytree.min.css" rel="stylesheet" type="text/css">
|
||||
<style type="text/css">
|
||||
ul.fancytree-container {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
{% load truncatechars %}
|
||||
{% load lang_utils %}
|
||||
{% load explore %}{% explore %}
|
||||
<div class="jsmodule">
|
||||
|
|
|
@ -64,9 +64,9 @@
|
|||
</ul>
|
||||
<ul class="book-list-view">
|
||||
<li>Sort by:</li>
|
||||
<li class="view-list"><a {% if order_by = 'popular' %}class="chosen" {% endif %}href="{% url 'faceted_list' path %}?{% if setkw %}setkw={{setkw}}&{% endif %}order_by=popular">popular</a></li>
|
||||
<li class="view-list"><a {% if order_by = 'newest' %}class="chosen" {% endif %}href="{% url 'faceted_list' path %}?{% if setkw %}setkw={{setkw}}&{% endif %}order_by=newest">newest</a></li>
|
||||
<li class="view-list"><a {% if order_by = 'title' %}class="chosen" {% endif %}href="{% url 'faceted_list' path %}?{% if setkw %}setkw={{setkw}}&{% endif %}order_by=title">title</a></li>
|
||||
<li class="view-list"><a {% if order_by == 'popular' %}class="chosen" {% endif %}href="{% url 'faceted_list' path %}?{% if setkw %}setkw={{setkw}}&{% endif %}order_by=popular">popular</a></li>
|
||||
<li class="view-list"><a {% if order_by == 'newest' %}class="chosen" {% endif %}href="{% url 'faceted_list' path %}?{% if setkw %}setkw={{setkw}}&{% endif %}order_by=newest">newest</a></li>
|
||||
<li class="view-list"><a {% if order_by == 'title' %}class="chosen" {% endif %}href="{% url 'faceted_list' path %}?{% if setkw %}setkw={{setkw}}&{% endif %}order_by=title">title</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="content-block-content">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
{{ transfer_form.media.css }}
|
||||
<script type="text/javascript" src="{{ jquery_ui_home }}" ></script>
|
||||
{{ transfer_form.media.js }}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% load truncatechars %}
|
||||
{% load sass_tags %}
|
||||
{% block title %}— Support Free eBooks{% endblock %}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% block title %} Library Admin {% endblock %}
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
<style type="text/css">
|
||||
.group-border {
|
||||
border: solid #edf3f4;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
{% load el_pagination_tags %}
|
||||
{% load sass_tags %}
|
||||
{% load truncatechars %}
|
||||
|
||||
{% block title %} — {{ library }}{% endblock %}
|
||||
{% block extra_css %}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
|
||||
<script type="text/javascript" src="{{ jquery_ui_home }}" ></script>
|
||||
<script type="text/javascript">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
{{ form.media.css }}
|
||||
<style type="text/css">
|
||||
div.half {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
<link href="/static/selectable/css/dj.selectable.css" type="text/css" media="all" rel="stylesheet" />
|
||||
<script type="text/javascript" src="{{ jquery_ui_home }}"></script>
|
||||
<script type="text/javascript" src="/static/selectable/js/jquery.dj.selectable.js"></script>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
{{ form.media.css }}
|
||||
<script type="text/javascript" src="{{ jquery_ui_home }}" ></script>
|
||||
{{ form.media.js }}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
{{ form.media.css }}
|
||||
<script type="text/javascript" src="{{ jquery_ui_home }}" ></script>
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
{% load i18n %}
|
||||
{% load sass_tags %}
|
||||
{% load truncatechars %}
|
||||
|
||||
{% block title %}{% trans "Notification Settings" %}{% endblock %}
|
||||
|
||||
|
@ -87,7 +86,7 @@ $j(document).ready(function() {
|
|||
<td colspan="2" id="last"><input type="submit" value="{% trans 'Change' %}"></input></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Pledge Notifications</h3>
|
||||
<h3>Pledge/Donation Notifications</h3>
|
||||
<table class="notice_settings table table-striped" width="90%">
|
||||
<tr>
|
||||
<th>{% trans "Notify me when..." %}</th>
|
||||
|
@ -96,7 +95,7 @@ $j(document).ready(function() {
|
|||
{% endfor %}
|
||||
</tr>
|
||||
{% for row in notice_settings.rows %}
|
||||
{% if row.notice_type.label|truncatechars:10 == 'pledge_...' %}
|
||||
{% if row.notice_type.label|truncatechars:10 == 'pledge_...' or row.notice_type.label == 'donation' %}
|
||||
<tr class="{% cycle 'row1' 'row2' %}">
|
||||
<td>
|
||||
<span class="notice_type_description">{% trans row.notice_type.description %}</span>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
{% extends 'notification/notice_template.html' %}
|
||||
|
||||
{% load truncatechars %}
|
||||
|
||||
{% block comments_book %}
|
||||
<a href="{% url 'work' work.id %}"><img src="{{ work.cover_image_small }}" alt="cover image for {{ work.title }}" /></a>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% block title %} Rights Holder Agreement {% endblock %}
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
<script type="text/javascript" src="{{ jquery_ui_home }}"></script>
|
||||
<script type="text/javascript">
|
||||
onload = function(){
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
{% endwith %}
|
||||
{% endifequal %}
|
||||
</div>
|
||||
{% if campaign.status = 'ACTIVE' or campaign.status = 'INITIALIZED' %}
|
||||
{% if campaign.status == 'ACTIVE' or campaign.status == 'INITIALIZED' %}
|
||||
<div>
|
||||
<a href="{% url 'manage_campaign' campaign.id %}" class="manage">Manage This Campaign</a>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% block title %} for Rightsholders {% endblock %}
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
<link href="/static/selectable/css/dj.selectable.css" type="text/css" media="all" rel="stylesheet" />
|
||||
<script type="text/javascript" src="{{ jquery_ui_home }}"></script>
|
||||
<script type="text/javascript" src="/static/selectable/js/jquery.dj.selectable.js"></script>
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
{% with claim.campaign as campaign %}
|
||||
<div class="work_campaigns clearfix">
|
||||
{% if campaign.status = 'ACTIVE' or campaign.status = 'INITIALIZED' %}
|
||||
{% if campaign.status == 'ACTIVE' or campaign.status == 'INITIALIZED' %}
|
||||
<div class="campaign_info">
|
||||
Your {{ campaign.get_type_display }}, "{{ campaign.name }}", is {{ campaign.status }}<br />
|
||||
Created: {{ campaign.created }}<br />
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block extra_extra_head %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
{{ form.media.css }}
|
||||
<script type="text/javascript" src="{{ jquery_ui_home }}" ></script>
|
||||
{{ form.media.js }}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load el_pagination_tags %}
|
||||
{% load truncatechars %}
|
||||
{% load sass_tags %}
|
||||
|
||||
{% block title %} — {{ supporter.username }}{% endblock %}
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
{% block extra_css %}
|
||||
<link type="text/css" rel="stylesheet" href="{% sass_src 'scss/campaign2.scss' %}" />
|
||||
{% if user.is_staff or user in work.last_campaign.managers.all %}
|
||||
<link rel="stylesheet" href="/static/css/ui-lightness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen">
|
||||
<link rel="stylesheet" href="{{ jquery_ui_theme }}" type="text/css" media="screen">
|
||||
{{ kwform.media.css }}
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -19,14 +19,14 @@ def bookpanel(context):
|
|||
supported = False
|
||||
if campaign and campaign.type == REWARDS:
|
||||
if campaign.status == 'ACTIVE':
|
||||
if not user.is_anonymous() and user.transaction_set.filter(campaign__work=work):
|
||||
if not user.is_anonymous and user.transaction_set.filter(campaign__work=work):
|
||||
supported = True
|
||||
context['supported'] = supported
|
||||
|
||||
show_pledge = False
|
||||
if campaign and campaign.type == REWARDS:
|
||||
if campaign.status == 'ACTIVE':
|
||||
if user.is_anonymous() or not supported:
|
||||
if user.is_anonymous or not supported:
|
||||
show_pledge = True
|
||||
context['show_pledge'] = show_pledge
|
||||
|
||||
|
@ -39,7 +39,7 @@ def bookpanel(context):
|
|||
|
||||
show_purchase = False
|
||||
if campaign and campaign.type == BUY2UNGLUE:
|
||||
if user.is_anonymous() or not context.get('license_is_active', False):
|
||||
if user.is_anonymous or not context.get('license_is_active', False):
|
||||
if campaign.status == 'ACTIVE':
|
||||
if not context.get('borrowable', False):
|
||||
if not library:
|
||||
|
|
|
@ -10,7 +10,7 @@ def lib_acqs(context):
|
|||
lib_user = library.user
|
||||
else:
|
||||
user = context['request'].user
|
||||
if user.is_anonymous():
|
||||
if user.is_anonymous:
|
||||
return ''
|
||||
else:
|
||||
lib_user = (lib.user for lib in user.profile.libraries)
|
||||
|
|
|
@ -10,7 +10,7 @@ def purchased(context):
|
|||
try:
|
||||
work.id # sometimes work is a dict
|
||||
user = context['request'].user
|
||||
if user.is_anonymous():
|
||||
if user.is_anonymous:
|
||||
return ''
|
||||
try:
|
||||
user_license = work.get_user_license(user)
|
||||
|
|
|
@ -1,186 +0,0 @@
|
|||
"""
|
||||
The truncatechars filter is part of Django dev, but we're on 1.3.1
|
||||
The following is the filter and its dependencies
|
||||
To use this filter, put "{% load truncatechars %}" at the beginning of your template,
|
||||
then {{ myvariable|truncatechars:num }}
|
||||
"""
|
||||
import unicodedata
|
||||
|
||||
from django import template
|
||||
from django.template import Library
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.encoding import force_unicode
|
||||
from django.utils.functional import allow_lazy, SimpleLazyObject
|
||||
from django.utils.translation import pgettext
|
||||
|
||||
register = Library()
|
||||
|
||||
class Truncator(SimpleLazyObject):
|
||||
"""
|
||||
An object used to truncate text, either by characters or words.
|
||||
"""
|
||||
def __init__(self, text):
|
||||
super(Truncator, self).__init__(lambda: force_unicode(text))
|
||||
|
||||
def add_truncation_text(self, text, truncate=None):
|
||||
if truncate is None:
|
||||
truncate = pgettext(
|
||||
'String to return when truncating text',
|
||||
u'%(truncated_text)s...')
|
||||
truncate = force_unicode(truncate)
|
||||
if '%(truncated_text)s' in truncate:
|
||||
return truncate % {'truncated_text': text}
|
||||
# The truncation text didn't contain the %(truncated_text)s string
|
||||
# replacement argument so just append it to the text.
|
||||
if text.endswith(truncate):
|
||||
# But don't append the truncation text if the current text already
|
||||
# ends in this.
|
||||
return text
|
||||
return '%s%s' % (text, truncate)
|
||||
|
||||
def chars(self, num, truncate=None):
|
||||
"""
|
||||
Returns the text truncated to be no longer than the specified number
|
||||
of characters.
|
||||
|
||||
Takes an optional argument of what should be used to notify that the
|
||||
string has been truncated, defaulting to a translatable string of an
|
||||
ellipsis (...).
|
||||
"""
|
||||
length = int(num)
|
||||
uniself = unicode(self._wrapped)
|
||||
text = unicodedata.normalize('NFC', uniself)
|
||||
|
||||
# Calculate the length to truncate to (max length - end_text length)
|
||||
truncate_len = length
|
||||
for char in self.add_truncation_text('', truncate):
|
||||
if not unicodedata.combining(char):
|
||||
truncate_len -= 1
|
||||
if truncate_len == 0:
|
||||
break
|
||||
|
||||
s_len = 0
|
||||
end_index = None
|
||||
for i, char in enumerate(text):
|
||||
if unicodedata.combining(char):
|
||||
# Don't consider combining characters
|
||||
# as adding to the string length
|
||||
continue
|
||||
s_len += 1
|
||||
if end_index is None and s_len > truncate_len:
|
||||
end_index = i
|
||||
if s_len > length:
|
||||
# Return the truncated string
|
||||
return self.add_truncation_text(text[:end_index or 0],
|
||||
truncate)
|
||||
|
||||
# Return the original string since no truncation was necessary
|
||||
return text
|
||||
chars = allow_lazy(chars)
|
||||
|
||||
def words(self, num, truncate=None, html=False):
|
||||
"""
|
||||
Truncates a string after a certain number of words. Takes an optional
|
||||
argument of what should be used to notify that the string has been
|
||||
truncated, defaulting to ellipsis (...).
|
||||
"""
|
||||
length = int(num)
|
||||
if html:
|
||||
return self._html_words(length, truncate)
|
||||
return self._text_words(length, truncate)
|
||||
words = allow_lazy(words)
|
||||
|
||||
def _text_words(self, length, truncate):
|
||||
"""
|
||||
Truncates a string after a certain number of words.
|
||||
|
||||
Newlines in the string will be stripped.
|
||||
"""
|
||||
words = self._wrapped.split()
|
||||
if len(words) > length:
|
||||
words = words[:length]
|
||||
return self.add_truncation_text(u' '.join(words), truncate)
|
||||
return u' '.join(words)
|
||||
|
||||
def _html_words(self, length, truncate):
|
||||
"""
|
||||
Truncates HTML to a certain number of words (not counting tags and
|
||||
comments). Closes opened tags if they were correctly closed in the
|
||||
given HTML.
|
||||
|
||||
Newlines in the HTML are preserved.
|
||||
"""
|
||||
if length <= 0:
|
||||
return u''
|
||||
html4_singlets = (
|
||||
'br', 'col', 'link', 'base', 'img',
|
||||
'param', 'area', 'hr', 'input'
|
||||
)
|
||||
# Count non-HTML words and keep note of open tags
|
||||
pos = 0
|
||||
end_text_pos = 0
|
||||
words = 0
|
||||
open_tags = []
|
||||
while words <= length:
|
||||
m = re_words.search(self._wrapped, pos)
|
||||
if not m:
|
||||
# Checked through whole string
|
||||
break
|
||||
pos = m.end(0)
|
||||
if m.group(1):
|
||||
# It's an actual non-HTML word
|
||||
words += 1
|
||||
if words == length:
|
||||
end_text_pos = pos
|
||||
continue
|
||||
# Check for tag
|
||||
tag = re_tag.match(m.group(0))
|
||||
if not tag or end_text_pos:
|
||||
# Don't worry about non tags or tags after our truncate point
|
||||
continue
|
||||
closing_tag, tagname, self_closing = tag.groups()
|
||||
# Element names are always case-insensitive
|
||||
tagname = tagname.lower()
|
||||
if self_closing or tagname in html4_singlets:
|
||||
pass
|
||||
elif closing_tag:
|
||||
# Check for match in open tags list
|
||||
try:
|
||||
i = open_tags.index(tagname)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
# SGML: An end tag closes, back to the matching start tag,
|
||||
# all unclosed intervening start tags with omitted end tags
|
||||
open_tags = open_tags[i + 1:]
|
||||
else:
|
||||
# Add it to the start of the open tags list
|
||||
open_tags.insert(0, tagname)
|
||||
if words <= length:
|
||||
# Don't try to close tags if we don't need to truncate
|
||||
return self._wrapped
|
||||
out = self._wrapped[:end_text_pos]
|
||||
truncate_text = self.add_truncation_text('', truncate)
|
||||
if truncate_text:
|
||||
out += truncate_text
|
||||
# Close any tags still open
|
||||
for tag in open_tags:
|
||||
out += '</%s>' % tag
|
||||
# Return string
|
||||
return out
|
||||
|
||||
# django dev uses filter(is_safe=True) syntax here, but that's not yet available in 1.3.1
|
||||
@register.filter()
|
||||
@stringfilter
|
||||
def truncatechars(value, arg):
|
||||
"""
|
||||
Truncates a string after a certain number of characters.
|
||||
|
||||
Argument: Number of characters to truncate after.
|
||||
"""
|
||||
try:
|
||||
length = int(arg)
|
||||
except ValueError: # Invalid literal for int().
|
||||
return value # Fail silently.
|
||||
return Truncator(value).chars(length)
|
||||
truncatechars.is_safe = True
|
|
@ -10,7 +10,7 @@ from decimal import Decimal as D
|
|||
from django.contrib import auth
|
||||
from django.contrib.auth.models import User
|
||||
from django.core import mail
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.test import TestCase
|
||||
from django.test.client import Client
|
||||
from django.utils.timezone import now
|
||||
|
@ -220,7 +220,7 @@ class PledgingUiTests(TestCase):
|
|||
#self.assertEqual(self.client.session['_auth_user_id'], self.user.pk)
|
||||
|
||||
user = auth.get_user(self.client)
|
||||
assert user.is_authenticated()
|
||||
assert user.is_authenticated
|
||||
|
||||
|
||||
# load a Work by putting it on the User's wishlist
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.conf import settings
|
||||
from django.conf.urls import patterns, url, include
|
||||
from django.conf.urls import url, include
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.sites.models import Site
|
||||
|
|
|
@ -29,7 +29,7 @@ from django.core import signing
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.core.files.storage import default_storage
|
||||
from django.core.mail import EmailMessage
|
||||
from django.core.urlresolvers import reverse, reverse_lazy
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.core.validators import validate_email
|
||||
from django.db.models import Q, Count, Sum
|
||||
from django.forms import Select
|
||||
|
@ -171,7 +171,7 @@ def process_kindle_email(request):
|
|||
download + login/account creation; add kindle email to profile
|
||||
"""
|
||||
user = request.user
|
||||
if user.is_authenticated() and request.session.has_key('kindle_email'):
|
||||
if user.is_authenticated and request.session.has_key('kindle_email'):
|
||||
user.profile.kindle_email = request.session['kindle_email']
|
||||
user.profile.save()
|
||||
request.session.pop('kindle_email')
|
||||
|
@ -194,7 +194,7 @@ def cover_width(work):
|
|||
|
||||
def home(request, landing=False):
|
||||
faves = None
|
||||
if request.user.is_authenticated() :
|
||||
if request.user.is_authenticated :
|
||||
next = request.GET.get('next', False)
|
||||
if next:
|
||||
# should happen only for new users
|
||||
|
@ -270,7 +270,7 @@ def home(request, landing=False):
|
|||
reverse=True
|
||||
)
|
||||
|
||||
if request.user.is_authenticated():
|
||||
if request.user.is_authenticated:
|
||||
events = latest_actions[:12]
|
||||
else:
|
||||
events = latest_actions[:6]
|
||||
|
@ -326,7 +326,7 @@ def work(request, work_id, action='display'):
|
|||
formset = EditionFormSet(instance=work)
|
||||
|
||||
# process waiting add request
|
||||
if not request.user.is_anonymous() and request.session.has_key("add_wishlist"):
|
||||
if not request.user.is_anonymous and request.session.has_key("add_wishlist"):
|
||||
add_url = request.session["add_wishlist"]
|
||||
if add_url == request.path:
|
||||
request.user.wishlist.add_work(work, "login", notify=True)
|
||||
|
@ -334,7 +334,7 @@ def work(request, work_id, action='display'):
|
|||
|
||||
process_kindle_email(request)
|
||||
|
||||
if request.method == 'POST' and not request.user.is_anonymous():
|
||||
if request.method == 'POST' and not request.user.is_anonymous:
|
||||
activetab = '4'
|
||||
elif action == 'editions':
|
||||
activetab = '4'
|
||||
|
@ -363,7 +363,7 @@ def work(request, work_id, action='display'):
|
|||
if action == 'preview':
|
||||
work.last_campaign_status = 'ACTIVE'
|
||||
|
||||
if not request.user.is_anonymous():
|
||||
if not request.user.is_anonymous:
|
||||
claimform = UserClaimForm(request.user, initial={'work':work.pk, 'user': request.user.id}, prefix = 'claim')
|
||||
else:
|
||||
claimform = None
|
||||
|
@ -416,7 +416,7 @@ def work(request, work_id, action='display'):
|
|||
|
||||
def edition_uploads(request, edition_id):
|
||||
context = {}
|
||||
if not request.user.is_authenticated() :
|
||||
if not request.user.is_authenticated:
|
||||
return render(request, "admins_only.html")
|
||||
edition = get_edition(edition_id)
|
||||
campaign_type = edition.work.last_campaign().type
|
||||
|
@ -548,7 +548,7 @@ def googlebooks(request, googlebooks_id):
|
|||
if edition.new:
|
||||
# add related editions asynchronously
|
||||
tasks.populate_edition.delay(edition.isbn_13)
|
||||
if request.user.is_authenticated():
|
||||
if request.user.is_authenticated:
|
||||
request.user.profile.works.add(edition.work)
|
||||
except bookloader.LookupFailure:
|
||||
logger.warning("failed to load googlebooks_id %s" % googlebooks_id)
|
||||
|
@ -558,7 +558,7 @@ def googlebooks(request, googlebooks_id):
|
|||
work_url = reverse('work', kwargs={'work_id': edition.work_id})
|
||||
|
||||
# process waiting add request
|
||||
if not request.user.is_anonymous() and request.session.has_key("add_wishlist"):
|
||||
if not request.user.is_anonymous and request.session.has_key("add_wishlist"):
|
||||
add_url = request.session["add_wishlist"]
|
||||
if add_url == request.path:
|
||||
request.user.wishlist.add_work(edition.work, "login", notify=True)
|
||||
|
@ -944,7 +944,7 @@ class PledgeView(FormView):
|
|||
|
||||
def get_form_kwargs(self):
|
||||
|
||||
assert self.request.user.is_authenticated()
|
||||
assert self.request.user.is_authenticated
|
||||
self.work = safe_get_work(self.kwargs["work_id"])
|
||||
|
||||
# if there is no campaign or if campaign is not active, we should raise an error
|
||||
|
@ -1087,7 +1087,7 @@ class PurchaseView(PledgeView):
|
|||
return context
|
||||
|
||||
def get_form_kwargs(self):
|
||||
assert self.request.user.is_authenticated()
|
||||
assert self.request.user.is_authenticated
|
||||
self.work = safe_get_work(self.kwargs["work_id"])
|
||||
|
||||
# if there is no campaign or if campaign is not active, we should raise an error
|
||||
|
@ -1166,7 +1166,7 @@ class FundView(FormView):
|
|||
action = None
|
||||
|
||||
def get_form_class(self):
|
||||
if self.request.user.is_anonymous():
|
||||
if self.request.user.is_anonymous:
|
||||
return AnonCCForm
|
||||
elif self.request.user.profile.account:
|
||||
return AccountCCForm
|
||||
|
@ -1202,7 +1202,7 @@ class FundView(FormView):
|
|||
|
||||
data.update(
|
||||
{'preapproval_amount':self.transaction.needed_amount,
|
||||
'username':self.request.user.username if self.request.user.is_authenticated() else None,
|
||||
'username':self.request.user.username if self.request.user.is_authenticated else None,
|
||||
'work_id':self.transaction.campaign.work_id if self.transaction.campaign else None,
|
||||
'title':self.transaction.campaign.work.title if self.transaction.campaign else COMPANY_TITLE}
|
||||
)
|
||||
|
@ -1225,7 +1225,7 @@ class FundView(FormView):
|
|||
return_url = "%s?tid=%s" % (reverse('pledge_complete'), self.transaction.id)
|
||||
|
||||
if not self.transaction.campaign:
|
||||
if self.request.user.is_authenticated():
|
||||
if self.request.user.is_authenticated:
|
||||
self.transaction.user = self.request.user
|
||||
# if there's an email address, put it in the receipt column, so far unused.
|
||||
self.transaction.receipt = form.cleaned_data.get("email", None)
|
||||
|
@ -1233,12 +1233,12 @@ class FundView(FormView):
|
|||
|
||||
elif self.transaction.campaign.type == THANKS and self.transaction.user == None:
|
||||
#anonymous user, just charge the card!
|
||||
if self.request.user.is_authenticated():
|
||||
if self.request.user.is_authenticated:
|
||||
self.transaction.user = self.request.user
|
||||
# if there's an email address, put it in the receipt column, so far unused.
|
||||
self.transaction.receipt = form.cleaned_data.get("email", None)
|
||||
t, url = p.charge(self.transaction, return_url = return_url, token=stripe_token)
|
||||
elif self.request.user.is_anonymous():
|
||||
elif self.request.user.is_anonymous:
|
||||
#somehow the user lost their login
|
||||
return HttpResponseRedirect(reverse('superlogin'))
|
||||
elif self.transaction.user.id != self.request.user.id:
|
||||
|
@ -1333,7 +1333,7 @@ class PledgeRechargeView(TemplateView):
|
|||
context = super(PledgeRechargeView, self).get_context_data(**kwargs)
|
||||
|
||||
# the following should be true since PledgeView.as_view is wrapped in login_required
|
||||
assert self.request.user.is_authenticated()
|
||||
assert self.request.user.is_authenticated
|
||||
user = self.request.user
|
||||
|
||||
work = safe_get_work(self.kwargs["work_id"])
|
||||
|
@ -1392,7 +1392,7 @@ class FundCompleteView(TemplateView):
|
|||
return DownloadView.as_view()(request, work=self.transaction.campaign.work)
|
||||
|
||||
else:
|
||||
if request.user.is_authenticated():
|
||||
if request.user.is_authenticated:
|
||||
if self.user_is_ok():
|
||||
return self.render_to_response(context)
|
||||
else:
|
||||
|
@ -1482,7 +1482,7 @@ class PledgeCancelView(FormView):
|
|||
|
||||
# the following should be true since PledgeCancelView.as_view is wrapped in login_required
|
||||
|
||||
if self.request.user.is_authenticated():
|
||||
if self.request.user.is_authenticated:
|
||||
user = self.request.user
|
||||
else:
|
||||
context["error"] = "You are not logged in."
|
||||
|
@ -1531,7 +1531,7 @@ class PledgeCancelView(FormView):
|
|||
campaign_id = self.request.POST.get('campaign_id', self.request.GET.get('campaign_id'))
|
||||
|
||||
# this following logic should be extraneous.
|
||||
if self.request.user.is_authenticated():
|
||||
if self.request.user.is_authenticated:
|
||||
user = self.request.user
|
||||
else:
|
||||
return HttpResponse("You need to be logged in.")
|
||||
|
@ -1607,7 +1607,7 @@ def export_surveys(request, qid, work_id):
|
|||
label = landing.label
|
||||
wid = landing.object_id
|
||||
return [wid, subject.ip_address, run.id, completed, label]
|
||||
if not request.user.is_authenticated() :
|
||||
if not request.user.is_authenticated:
|
||||
return HttpResponseRedirect(reverse('surveys'))
|
||||
extra_headings = [u'work id', u'subject ip address', u'run id', u'date completed', u'landing label']
|
||||
return export_answers(request, qid,
|
||||
|
@ -1617,7 +1617,7 @@ def export_surveys(request, qid, work_id):
|
|||
filecode=work_id)
|
||||
|
||||
def surveys_summary(request, qid, work_id):
|
||||
if not request.user.is_authenticated() :
|
||||
if not request.user.is_authenticated:
|
||||
return HttpResponseRedirect(reverse('surveys'))
|
||||
return answer_summary(
|
||||
request,
|
||||
|
@ -1627,7 +1627,7 @@ def surveys_summary(request, qid, work_id):
|
|||
|
||||
|
||||
def new_survey(request, work_id):
|
||||
if not request.user.is_authenticated() :
|
||||
if not request.user.is_authenticated:
|
||||
return HttpResponseRedirect(reverse('surveys'))
|
||||
my_works = works_user_can_admin( request.user)
|
||||
if work_id:
|
||||
|
@ -1659,7 +1659,7 @@ def new_survey(request, work_id):
|
|||
return render(request, "manage_survey.html", {"work":work, "form":form})
|
||||
|
||||
def surveys(request):
|
||||
if not request.user.is_authenticated() :
|
||||
if not request.user.is_authenticated:
|
||||
return render(request, "surveys.html")
|
||||
works = works_user_can_admin(request.user)
|
||||
work_ids = [work.id for work in works]
|
||||
|
@ -1667,7 +1667,7 @@ def surveys(request):
|
|||
return render(request, "surveys.html", {"works":works, "surveys":surveys})
|
||||
|
||||
def campaign_admin(request):
|
||||
if not request.user.is_authenticated() :
|
||||
if not request.user.is_authenticated:
|
||||
return render(request, "admins_only.html")
|
||||
if not request.user.is_staff :
|
||||
return render(request, "admins_only.html")
|
||||
|
@ -1809,7 +1809,7 @@ def supporter(request, supporter_username, template_name, extra_context={}):
|
|||
activetab = "#3"
|
||||
|
||||
# following block to support profile admin form in supporter page
|
||||
if request.user.is_authenticated() and request.user.username == supporter_username:
|
||||
if request.user.is_authenticated and request.user.username == supporter_username:
|
||||
|
||||
profile_obj = request.user.profile
|
||||
|
||||
|
@ -2166,7 +2166,7 @@ class GoodreadsDisplayView(TemplateView):
|
|||
gr_client = GoodreadsClient(key=settings.GOODREADS_API_KEY, secret=settings.GOODREADS_API_SECRET)
|
||||
|
||||
user = self.request.user
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated:
|
||||
api_key = ApiKey.objects.filter(user=user)[0].key
|
||||
context['api_key'] = api_key
|
||||
|
||||
|
@ -2243,7 +2243,7 @@ def goodreads_cb(request):
|
|||
@csrf_exempt
|
||||
def goodreads_flush_assoc(request):
|
||||
user = request.user
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated:
|
||||
profile = user.profile
|
||||
profile.goodreads_user_id = None
|
||||
profile.goodreads_user_name = None
|
||||
|
@ -2544,7 +2544,7 @@ def feedback(request, recipient='unglueit@ebookfoundation.org', template='feedba
|
|||
context['num2'] = request.POST['num2']
|
||||
|
||||
else:
|
||||
if request.user.is_authenticated():
|
||||
if request.user.is_authenticated:
|
||||
context['sender'] = request.user.email
|
||||
try:
|
||||
context['page'] = request.GET['page']
|
||||
|
@ -2639,7 +2639,7 @@ class DownloadView(PurchaseView):
|
|||
self.lib_thanked = self.work.lib_thanked(self.request.user)
|
||||
self.data = {
|
||||
'preapproval_amount':self.get_preapproval_amount(),
|
||||
'anonymous':True if self.request.user.is_anonymous() else self.request.user.profile.anon_pref,
|
||||
'anonymous':True if self.request.user.is_anonymous else self.request.user.profile.anon_pref,
|
||||
}
|
||||
if self.request.method == 'POST':
|
||||
self.data.update(self.request.POST.dict())
|
||||
|
@ -2664,7 +2664,7 @@ class DownloadView(PurchaseView):
|
|||
for ebook in work.ebooks().all():
|
||||
formats[ebook.format] = reverse('download_ebook', args=[ebook.id])
|
||||
|
||||
if request.user.is_authenticated():
|
||||
if request.user.is_authenticated:
|
||||
#add a fave
|
||||
request.user.wishlist.add_work(work,'download')
|
||||
|
||||
|
@ -2805,7 +2805,7 @@ def download_ebook(request, ebook_id):
|
|||
return HttpResponseRedirect(ebook.url)
|
||||
|
||||
def download_purchased(request, work_id):
|
||||
if request.user.is_anonymous():
|
||||
if request.user.is_anonymous:
|
||||
HttpResponseRedirect('/accounts/login/download/')
|
||||
return DownloadView.as_view()(request, work_id=work_id)
|
||||
|
||||
|
@ -2855,12 +2855,12 @@ def receive_gift(request, nonce):
|
|||
# put nonce in session so we know that a user has redeemed a Gift
|
||||
request.session['gift_nonce'] = nonce
|
||||
if gift.used:
|
||||
if request.user.is_authenticated():
|
||||
if request.user.is_authenticated:
|
||||
#check that user hasn't redeemed the gift themselves
|
||||
if (gift.acq.user_id == request.user.id) and not gift.acq.expired:
|
||||
return HttpResponseRedirect(reverse('display_gift', args=[gift.id,'existing']))
|
||||
return render(request, 'gift_error.html', context)
|
||||
if request.user.is_authenticated():
|
||||
if request.user.is_authenticated:
|
||||
user_license = work.get_user_license(request.user)
|
||||
if user_license and user_license.purchased:
|
||||
# check if previously purchased- there would be two user licenses if so.
|
||||
|
@ -3017,7 +3017,7 @@ def send_to_kindle(request, work_id, javascript='0'):
|
|||
work = safe_get_work(work_id)
|
||||
context = {'work':work}
|
||||
acq = None
|
||||
if request.user.is_authenticated():
|
||||
if request.user.is_authenticated:
|
||||
all_acqs = request.user.acqs.filter(work=work).order_by('-created')
|
||||
for an_acq in all_acqs:
|
||||
if not an_acq.expired:
|
||||
|
@ -3058,7 +3058,7 @@ def send_to_kindle(request, work_id, javascript='0'):
|
|||
except ValidationError:
|
||||
return local_response(request, javascript, context, 3)
|
||||
request.session['kindle_email'] = kindle_email
|
||||
elif request.user.is_authenticated():
|
||||
elif request.user.is_authenticated:
|
||||
kindle_email = request.user.profile.kindle_email
|
||||
context['kindle_email'] = kindle_email
|
||||
|
||||
|
@ -3096,7 +3096,7 @@ def send_to_kindle(request, work_id, javascript='0'):
|
|||
logger.error('Unexpected error: %s', sys.exc_info())
|
||||
return local_response(request, javascript, context, 1)
|
||||
|
||||
if request.POST.has_key('kindle_email') and not request.user.is_authenticated():
|
||||
if request.POST.has_key('kindle_email') and not request.user.is_authenticated:
|
||||
return HttpResponseRedirect(reverse('superlogin'))
|
||||
return local_response(request, javascript, context, 2)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ views to edit bibmodels
|
|||
'''
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.files.storage import default_storage
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.db.models import Q
|
||||
from django.http import (
|
||||
HttpResponseRedirect,
|
||||
|
@ -32,7 +32,7 @@ def user_can_edit_work(user, work):
|
|||
'''
|
||||
Check if a user is allowed to edit the work
|
||||
'''
|
||||
if user.is_anonymous():
|
||||
if user.is_anonymous:
|
||||
return False
|
||||
elif user.is_staff :
|
||||
return True
|
||||
|
@ -76,7 +76,7 @@ def get_edition(edition_id):
|
|||
raise Http404 (duplicate-code)
|
||||
|
||||
def user_edition(edition, user):
|
||||
if user and user.is_authenticated() and edition:
|
||||
if user and user.is_authenticated and edition:
|
||||
user.profile.works.add(edition.work)
|
||||
return edition
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ from decimal import Decimal as D
|
|||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse, reverse_lazy
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.forms.models import modelformset_factory
|
||||
from django.http import HttpResponseRedirect, Http404
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
|
@ -39,7 +39,7 @@ class RHAgree(CreateView):
|
|||
return super(RHAgree, self).form_valid(form)
|
||||
|
||||
def rh_admin(request, facet='top'):
|
||||
if not request.user.is_authenticated() or not request.user.is_staff:
|
||||
if not request.user.is_authenticated or not request.user.is_staff:
|
||||
return render(request, "admins_only.html")
|
||||
|
||||
PendingFormSet = modelformset_factory(models.RightsHolder, fields=['approved'], extra=0)
|
||||
|
@ -65,7 +65,7 @@ def rh_admin(request, facet='top'):
|
|||
return render(request, "rights_holders.html", context)
|
||||
|
||||
def user_is_rh(user):
|
||||
if user.is_anonymous():
|
||||
if user.is_anonymous:
|
||||
return False
|
||||
for rh in user.rights_holder.filter(approved=True):
|
||||
return True
|
||||
|
@ -90,7 +90,7 @@ class ClaimView(CreateView):
|
|||
form.save()
|
||||
return HttpResponseRedirect(reverse('rightsholders'))
|
||||
|
||||
def get_context_data(self, form):
|
||||
def get_context_data(self, form=None):
|
||||
try:
|
||||
work = form.cleaned_data['work']
|
||||
except AttributeError:
|
||||
|
@ -108,7 +108,7 @@ def claim(request):
|
|||
return ClaimView.as_view()(request)
|
||||
|
||||
def rh_tools(request, template_name='rh_intro.html'):
|
||||
if not request.user.is_authenticated() :
|
||||
if not request.user.is_authenticated:
|
||||
return render(request, 'rh_intro.html')
|
||||
claims = request.user.claim.filter(user=request.user)
|
||||
campaign_form = "xxx"
|
||||
|
@ -198,7 +198,7 @@ def manage_campaign(request, id, ebf=None, action='manage'):
|
|||
|
||||
campaign.not_manager = False
|
||||
campaign.problems = []
|
||||
if (not request.user.is_authenticated()) or \
|
||||
if (not request.user.is_authenticated) or \
|
||||
(not request.user in campaign.managers.all() and not request.user.is_staff):
|
||||
campaign.not_manager = True
|
||||
return render(request, 'manage_campaign.html', {'campaign': campaign})
|
||||
|
|
|
@ -6,4 +6,4 @@ class LibraryAuthConfig(AppConfig):
|
|||
name = 'regluit.libraryauth'
|
||||
|
||||
def ready(self):
|
||||
from . import signals
|
||||
from . import signals
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
from . import models
|
||||
|
||||
from selectable.forms import AutoCompleteSelectWidget,AutoCompleteSelectField
|
||||
from selectable.base import ModelLookup
|
||||
from selectable.registry import registry
|
||||
|
||||
from django import forms
|
||||
from django.contrib.admin import ModelAdmin, site
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from selectable.base import ModelLookup
|
||||
from selectable.forms import AutoCompleteSelectWidget, AutoCompleteSelectField
|
||||
from selectable.registry import registry
|
||||
|
||||
from . import models
|
||||
|
||||
class UserLookup(ModelLookup):
|
||||
model = User
|
||||
|
@ -16,21 +16,21 @@ registry.register(UserLookup)
|
|||
|
||||
class LibraryAdminForm(forms.ModelForm):
|
||||
user = AutoCompleteSelectField(
|
||||
UserLookup,
|
||||
widget=AutoCompleteSelectWidget(UserLookup),
|
||||
required=True,
|
||||
)
|
||||
UserLookup,
|
||||
widget=AutoCompleteSelectWidget(UserLookup),
|
||||
required=True,
|
||||
)
|
||||
owner = AutoCompleteSelectField(
|
||||
UserLookup,
|
||||
widget=AutoCompleteSelectWidget(UserLookup),
|
||||
required=True,
|
||||
)
|
||||
UserLookup,
|
||||
widget=AutoCompleteSelectWidget(UserLookup),
|
||||
required=True,
|
||||
)
|
||||
class Meta(object):
|
||||
model = models.Library
|
||||
widgets= {'group':forms.HiddenInput}
|
||||
widgets = {'group':forms.HiddenInput}
|
||||
exclude = ('group', )
|
||||
|
||||
|
||||
|
||||
|
||||
class LibraryAdmin(ModelAdmin):
|
||||
list_display = ('user', )
|
||||
form = LibraryAdminForm
|
||||
|
@ -51,4 +51,4 @@ class EmailPatternAdmin(ModelAdmin):
|
|||
site.register(models.Library, LibraryAdmin)
|
||||
site.register(models.Block, BlockAdmin)
|
||||
site.register(models.CardPattern, CardPatternAdmin)
|
||||
site.register(models.EmailPattern, EmailPatternAdmin)
|
||||
site.register(models.EmailPattern, EmailPatternAdmin)
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import logging
|
||||
|
||||
import requests
|
||||
from django.http import HttpResponse
|
||||
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.http import urlquote
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.files.storage import default_storage
|
||||
from social_core.pipeline.social_auth import associate_by_email
|
||||
from social_django.models import UserSocialAuth
|
||||
from social_django.middleware import SocialAuthExceptionMiddleware
|
||||
from social_core.exceptions import (AuthAlreadyAssociated, SocialAuthBaseException)
|
||||
from social_django.middleware import SocialAuthExceptionMiddleware
|
||||
|
||||
ANONYMOUS_AVATAR = '/static/images/header/avatar.png'
|
||||
(NO_AVATAR, GRAVATAR, TWITTER, FACEBOOK, PRIVATETAR) = (0, 1, 2, 3, 4)
|
||||
|
@ -26,7 +25,7 @@ def pic_storage_url(user, backend, url):
|
|||
pic_file = ContentFile(r.content)
|
||||
content_type = r.headers.get('content-type', '')
|
||||
if u'text' in content_type:
|
||||
logger.warning('Cover return text for pic_url={}'.format(pic_url))
|
||||
logger.warning('Cover return text for pic_url={}'.format(url))
|
||||
return None
|
||||
pic_file.content_type = content_type
|
||||
default_storage.save(pic_file_name, pic_file)
|
||||
|
@ -43,8 +42,8 @@ def selectively_associate_by_email(backend, details, user=None, *args, **kwargs)
|
|||
This pipeline entry is not 100% secure unless you know that the providers
|
||||
enabled enforce email verification on their side, otherwise a user can
|
||||
attempt to take over another user account by using the same (not validated)
|
||||
email address on some provider.
|
||||
|
||||
email address on some provider.
|
||||
|
||||
Not using Facebook or Twitter to authenticate a user.
|
||||
"""
|
||||
if backend.name in ('twitter', 'facebook'):
|
||||
|
@ -61,7 +60,7 @@ def facebook_extra_values(user, extra_data):
|
|||
return True
|
||||
except Exception, e:
|
||||
logger.exception(e)
|
||||
return
|
||||
return
|
||||
|
||||
def twitter_extra_values(user, extra_data):
|
||||
try:
|
||||
|
@ -74,19 +73,19 @@ def twitter_extra_values(user, extra_data):
|
|||
user.profile.avatar_source = TWITTER
|
||||
user.profile.save()
|
||||
return True
|
||||
except Exception,e:
|
||||
except Exception, e:
|
||||
logger.error(e)
|
||||
return False
|
||||
|
||||
|
||||
def deliver_extra_data(backend, user, social, response, *args, **kwargs):
|
||||
if backend.name is 'twitter':
|
||||
twitter_extra_values( user, social.extra_data)
|
||||
if backend.name is 'facebook':
|
||||
facebook_extra_values( user, response)
|
||||
if backend.name == 'twitter':
|
||||
twitter_extra_values(user, social.extra_data)
|
||||
if backend.name == 'facebook':
|
||||
facebook_extra_values(user, response)
|
||||
|
||||
# following is needed because of length limitations in a unique constrain for MySQL
|
||||
def chop_username(username, *args, **kwargs):
|
||||
if username and len(username)>222:
|
||||
if username and len(username) > 222:
|
||||
return {'username':username[0:222]}
|
||||
|
||||
def selective_social_user(backend, uid, user=None, *args, **kwargs):
|
||||
|
@ -111,9 +110,9 @@ class SocialAuthExceptionMiddlewareWithoutMessages(SocialAuthExceptionMiddleware
|
|||
"""
|
||||
a modification of SocialAuthExceptionMiddleware to pass backend and message without
|
||||
attempting django.messages
|
||||
"""
|
||||
"""
|
||||
def process_exception(self, request, exception):
|
||||
|
||||
|
||||
if isinstance(exception, SocialAuthBaseException):
|
||||
backend = getattr(request, 'backend', None)
|
||||
backend_name = getattr(backend, 'name', 'unknown-backend')
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
to make a backend named <backend> you need to...
|
||||
1. make a class <backend>
|
||||
2. with a function authenticate(self, request, library)
|
||||
returns true if can request.user can be authenticated to the library, and attaches a credential property to the library object
|
||||
returns true if can request.user can be authenticated to the library,
|
||||
and attaches a credential property to the library object
|
||||
returns fals if otherwise.
|
||||
3. with a class authenticator
|
||||
with a process((self, authenticator, success_url, deny_url) method which is expected to return a response
|
||||
4. make a libraryauth/<backend>_join.html template (authenticator will be in its context) to insert a link or form for a user to join the library
|
||||
5. if you need to show the user a form, define a model form class form with init method __init__(self, request, library, *args, **kwargs)
|
||||
with a process((self, authenticator, success_url, deny_url) method
|
||||
which is expected to return a response
|
||||
4. make a libraryauth/<backend>_join.html template (authenticator will be in its context)
|
||||
to insert a link or form for a user to join the library
|
||||
5. if you need to show the user a form, define a model form class form with init method
|
||||
__init__(self, request, library, *args, **kwargs)
|
||||
and model LibraryUser
|
||||
6. define an admin form to let the library configure its authentication
|
||||
7. add new auth choice to Library.backend choices and the admin as desired
|
||||
|
@ -20,75 +24,78 @@ from django.http import HttpResponseRedirect
|
|||
from django.shortcuts import render
|
||||
|
||||
from .models import Block, IP, LibraryUser, CardPattern, EmailPattern
|
||||
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ip:
|
||||
def authenticate(self,request, library):
|
||||
def authenticate(self, request, library):
|
||||
try:
|
||||
ip = IP(request.META['REMOTE_ADDR'])
|
||||
blocks = Block.objects.filter(Q(lower=ip) | Q(lower__lte=ip, upper__gte=ip))
|
||||
for block in blocks:
|
||||
if block.library==library:
|
||||
if block.library == library:
|
||||
logger.info('%s authenticated for %s from %s'%(request.user, library, ip))
|
||||
library.credential=ip
|
||||
library.credential = ip
|
||||
return True
|
||||
return False
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
|
||||
class authenticator():
|
||||
def process(self, caller, success_url, deny_url):
|
||||
return HttpResponseRedirect(deny_url)
|
||||
|
||||
|
||||
form = None
|
||||
|
||||
|
||||
class admin_form(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Block
|
||||
exclude = ("library",)
|
||||
|
||||
class cardnum:
|
||||
def authenticate(self,request, library):
|
||||
class cardnum:
|
||||
def authenticate(self, request, library):
|
||||
return False
|
||||
|
||||
class authenticator():
|
||||
def process(self, caller, success_url, deny_url):
|
||||
if caller.form and caller.request.method=='POST' and caller.form.is_valid():
|
||||
if caller.form and caller.request.method == 'POST' and caller.form.is_valid():
|
||||
library = caller.form.cleaned_data['library']
|
||||
library.credential = caller.form.cleaned_data['credential']
|
||||
logger.info('%s authenticated for %s from %s'%(caller.request.user, caller.library, caller.form.cleaned_data.get('number')))
|
||||
logger.info('%s authenticated for %s from %s' % (
|
||||
caller.request.user,
|
||||
caller.library,
|
||||
caller.form.cleaned_data.get('number'),
|
||||
))
|
||||
library.add_user(caller.form.cleaned_data['user'])
|
||||
return HttpResponseRedirect(success_url)
|
||||
else:
|
||||
return render(caller.request, 'libraryauth/library.html', {
|
||||
'library':caller.library,
|
||||
'authenticator':caller,
|
||||
})
|
||||
return render(caller.request, 'libraryauth/library.html', {
|
||||
'library':caller.library,
|
||||
'authenticator':caller,
|
||||
})
|
||||
|
||||
class admin_form(forms.ModelForm):
|
||||
class Meta:
|
||||
model = CardPattern
|
||||
exclude = ("library",)
|
||||
|
||||
|
||||
class form(forms.ModelForm):
|
||||
credential = forms.RegexField(
|
||||
label="Enter Your Library Card Number",
|
||||
max_length=20,
|
||||
regex=r'^\d+$',
|
||||
required = True,
|
||||
help_text = "(digits only)",
|
||||
error_messages = {'invalid': "digits only!",}
|
||||
)
|
||||
label="Enter Your Library Card Number",
|
||||
max_length=20,
|
||||
regex=r'^\d+$',
|
||||
required=True,
|
||||
help_text="(digits only)",
|
||||
error_messages={'invalid': "digits only!",}
|
||||
)
|
||||
def __init__(self, request, library, *args, **kwargs):
|
||||
if request.method=="POST":
|
||||
data=request.POST
|
||||
if request.method == "POST":
|
||||
data = request.POST
|
||||
super(cardnum.form, self).__init__(data=data)
|
||||
else:
|
||||
initial={'user':request.user, 'library':library}
|
||||
initial = {'user':request.user, 'library':library}
|
||||
super(cardnum.form, self).__init__(initial=initial)
|
||||
|
||||
|
||||
def clean(self):
|
||||
library = self.cleaned_data.get('library', None)
|
||||
credential = self.cleaned_data.get('credential', '')
|
||||
|
@ -96,23 +103,23 @@ class cardnum:
|
|||
if card_pattern.is_valid(credential):
|
||||
return self.cleaned_data
|
||||
raise forms.ValidationError("the library card number must be VALID.")
|
||||
|
||||
|
||||
class Meta:
|
||||
model = LibraryUser
|
||||
widgets = { 'library': forms.HiddenInput, 'user': forms.HiddenInput }
|
||||
widgets = {'library': forms.HiddenInput, 'user': forms.HiddenInput}
|
||||
exclude = ()
|
||||
class email:
|
||||
def authenticate(self,request, library):
|
||||
if request.user.is_anonymous():
|
||||
class email:
|
||||
def authenticate(self, request, library):
|
||||
if request.user.is_anonymous:
|
||||
return False
|
||||
email = request.user.email
|
||||
for email_pattern in library.email_auths.all():
|
||||
if email_pattern.is_valid(email):
|
||||
logger.info('%s authenticated for %s from %s'%(request.user, library, email))
|
||||
library.credential=email
|
||||
library.credential = email
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class authenticator():
|
||||
def process(self, caller, success_url, deny_url):
|
||||
return HttpResponseRedirect(deny_url)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
from django import forms
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm
|
||||
from django.contrib.auth.forms import PasswordResetForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from registration.forms import RegistrationForm
|
||||
|
@ -12,11 +12,11 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class UserData(forms.Form):
|
||||
username = forms.RegexField(
|
||||
label=_("New Username"),
|
||||
max_length=30,
|
||||
label=_("New Username"),
|
||||
max_length=30,
|
||||
regex=r'^[\w.@+-]+$',
|
||||
help_text = _("30 characters or fewer."),
|
||||
error_messages = {
|
||||
help_text=_("30 characters or fewer."),
|
||||
error_messages={
|
||||
'invalid': _("This value may contain only letters, numbers and @/./+/-/_ characters.")
|
||||
}
|
||||
)
|
||||
|
@ -35,11 +35,12 @@ class UserData(forms.Form):
|
|||
raise forms.ValidationError(_("Your username is already "+username))
|
||||
|
||||
class UserNamePass(UserData):
|
||||
password1 = forms.CharField(label=_("Password"),
|
||||
widget=forms.PasswordInput)
|
||||
password2 = forms.CharField(label=_("Password confirmation"),
|
||||
password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
|
||||
password2 = forms.CharField(
|
||||
label=_("Password confirmation"),
|
||||
widget=forms.PasswordInput,
|
||||
help_text = _("Enter the same password as above, for verification."))
|
||||
help_text=_("Enter the same password as above, for verification.")
|
||||
)
|
||||
allow_same = True
|
||||
def clean_password2(self):
|
||||
password1 = self.cleaned_data.get("password1", "")
|
||||
|
@ -59,14 +60,6 @@ class RegistrationFormNoDisposableEmail(RegistrationForm):
|
|||
raise forms.ValidationError(_("Please supply a permanent email address."))
|
||||
return self.cleaned_data['email']
|
||||
|
||||
class AuthForm(AuthenticationForm):
|
||||
def __init__(self, request=None, *args, **kwargs):
|
||||
if request and request.method == 'GET':
|
||||
saved_un= request.COOKIES.get('un', None)
|
||||
super(AuthForm, self).__init__(initial={"username":saved_un},*args, **kwargs)
|
||||
else:
|
||||
super(AuthForm, self).__init__(*args, **kwargs)
|
||||
|
||||
class SocialAwarePasswordResetForm(PasswordResetForm):
|
||||
def get_users(self, email):
|
||||
"""
|
||||
|
@ -81,40 +74,43 @@ class SocialAwarePasswordResetForm(PasswordResetForm):
|
|||
if not get_user_model().objects.filter(email__iexact=email, is_active=True).exists():
|
||||
raise forms.ValidationError("There aren't ungluers with that email address!")
|
||||
return email
|
||||
|
||||
|
||||
|
||||
class NewLibraryForm(forms.ModelForm):
|
||||
username = forms.RegexField(
|
||||
label=_("Library Username"),
|
||||
max_length=30,
|
||||
label=_("Library Username"),
|
||||
max_length=30,
|
||||
regex=r'^[\w.@+-]+$',
|
||||
help_text = _("30 characters or fewer."),
|
||||
error_messages = {
|
||||
help_text=_("30 characters or fewer."),
|
||||
error_messages={
|
||||
'invalid': _("This value may contain only letters, numbers and @/./+/-/_ characters.")
|
||||
},
|
||||
initial = '',
|
||||
initial='',
|
||||
)
|
||||
email = forms.EmailField(
|
||||
label=_("notification email address for library"),
|
||||
label=_("notification email address for library"),
|
||||
max_length=100,
|
||||
error_messages={'required': 'Please enter an email address for the library.'},
|
||||
)
|
||||
|
||||
def clean_username(self):
|
||||
username= self.cleaned_data['username']
|
||||
username = self.cleaned_data['username']
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
raise forms.ValidationError(_("That username is already in use, please choose another."))
|
||||
raise forms.ValidationError(_(
|
||||
"That username is already in use, please choose another."
|
||||
))
|
||||
except User.DoesNotExist:
|
||||
self.instance.user = User(username=username)
|
||||
return username
|
||||
|
||||
|
||||
|
||||
|
||||
class Meta:
|
||||
model = Library
|
||||
fields = 'name', 'backend', 'email', 'username'
|
||||
widgets = {'name':forms.TextInput(attrs={'size':'40'})}
|
||||
|
||||
class LibraryForm(forms.ModelForm):
|
||||
class LibraryForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Library
|
||||
fields = 'name', 'backend',
|
||||
fields = 'name', 'backend',
|
||||
|
|
|
@ -47,9 +47,9 @@ class Migration(migrations.Migration):
|
|||
('backend', models.CharField(default=b'ip', max_length=10, choices=[(b'ip', b'IP authentication'), (b'cardnum', b'Library Card Number check'), (b'email', b'e-mail pattern check')])),
|
||||
('name', models.CharField(default=b'', max_length=80)),
|
||||
('approved', models.BooleanField(default=False)),
|
||||
('group', models.OneToOneField(related_name='library', null=True, to='auth.Group')),
|
||||
('owner', models.ForeignKey(related_name='libraries', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.OneToOneField(related_name='library', to=settings.AUTH_USER_MODEL)),
|
||||
('group', models.OneToOneField(on_delete=models.CASCADE, related_name='library', null=True, to='auth.Group')),
|
||||
('owner', models.ForeignKey(on_delete=models.CASCADE, related_name='libraries', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.OneToOneField(on_delete=models.CASCADE, related_name='library', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -58,23 +58,23 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('credential', models.CharField(max_length=30, null=True)),
|
||||
('date_modified', models.DateTimeField(auto_now=True)),
|
||||
('library', models.ForeignKey(related_name='library_users', to='libraryauth.Library')),
|
||||
('user', models.ForeignKey(related_name='user_libraries', to=settings.AUTH_USER_MODEL)),
|
||||
('library', models.ForeignKey(on_delete=models.CASCADE, related_name='library_users', to='libraryauth.Library')),
|
||||
('user', models.ForeignKey(on_delete=models.CASCADE, related_name='user_libraries', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='emailpattern',
|
||||
name='library',
|
||||
field=models.ForeignKey(related_name='email_auths', to='libraryauth.Library'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='email_auths', to='libraryauth.Library'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cardpattern',
|
||||
name='library',
|
||||
field=models.ForeignKey(related_name='cardnum_auths', to='libraryauth.Library'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='cardnum_auths', to='libraryauth.Library'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='block',
|
||||
name='library',
|
||||
field=models.ForeignKey(related_name='ip_auths', to='libraryauth.Library'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='ip_auths', to='libraryauth.Library'),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,63 +1,75 @@
|
|||
# IP address part of this of this copied from https://github.com/benliles/django-ipauth/blob/master/ipauth/models.py
|
||||
# IP address part of this of this copied from
|
||||
# https://github.com/benliles/django-ipauth/blob/master/ipauth/models.py
|
||||
|
||||
import re
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.contrib.auth.models import Group
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core import validators
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.db.models.signals import post_save
|
||||
from django.forms import GenericIPAddressField as BaseIPAddressField
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
|
||||
class Library(models.Model):
|
||||
'''
|
||||
name and other things derive from the User
|
||||
'''
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='library')
|
||||
group = models.OneToOneField(Group, related_name='library', null = True)
|
||||
backend = models.CharField(max_length=10, choices=(
|
||||
('ip','IP authentication'),
|
||||
('cardnum', 'Library Card Number check'),
|
||||
('email', 'e-mail pattern check'),
|
||||
),default='ip')
|
||||
name = models.CharField(max_length=80, default='')
|
||||
user = models.OneToOneField(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='library',
|
||||
)
|
||||
group = models.OneToOneField(
|
||||
Group,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='library',
|
||||
null=True
|
||||
)
|
||||
backend = models.CharField(max_length=10, choices=(
|
||||
('ip', 'IP authentication'),
|
||||
('cardnum', 'Library Card Number check'),
|
||||
('email', 'e-mail pattern check'),
|
||||
), default='ip')
|
||||
name = models.CharField(max_length=80, default='')
|
||||
approved = models.BooleanField(default=False)
|
||||
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="libraries")
|
||||
owner = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="libraries",
|
||||
)
|
||||
credential = None
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.name)
|
||||
|
||||
|
||||
def add_user(self, user):
|
||||
user.groups.add(self.group)
|
||||
(library_user, created) = LibraryUser.objects.get_or_create(library=self, user=user)
|
||||
library_user.credential=self.credential
|
||||
library_user.credential = self.credential
|
||||
library_user.save()
|
||||
|
||||
|
||||
def has_user(self, user):
|
||||
return self.group in user.groups.all() or user == self.user
|
||||
|
||||
|
||||
@property
|
||||
def join_template(self):
|
||||
if self.approved:
|
||||
return 'libraryauth/' + self.backend + '_join.html'
|
||||
else:
|
||||
return 'libraryauth/unapproved.html'
|
||||
return 'libraryauth/unapproved.html'
|
||||
|
||||
@property
|
||||
def help_template(self):
|
||||
return 'libraryauth/' + self.backend + '_help.html'
|
||||
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('library', args=[self.user.username])
|
||||
|
||||
def add_group(sender, created, instance, **kwargs):
|
||||
if created:
|
||||
num=''
|
||||
num = ''
|
||||
while created:
|
||||
(group,created)=Group.objects.get_or_create(name=instance.user.username + num)
|
||||
(group, created) = Group.objects.get_or_create(name=instance.user.username + num)
|
||||
# make sure not using a group twice!
|
||||
if created:
|
||||
created = False
|
||||
|
@ -68,7 +80,7 @@ def add_group(sender, created, instance, **kwargs):
|
|||
created = True
|
||||
except Library.DoesNotExist:
|
||||
pass
|
||||
instance.group=group
|
||||
instance.group = group
|
||||
instance.save()
|
||||
|
||||
post_save.connect(add_group, sender=Library)
|
||||
|
@ -121,7 +133,7 @@ class IP(object):
|
|||
int = property(_get_int, _set_int)
|
||||
|
||||
def _get_str(self):
|
||||
if self.int!=None:
|
||||
if self.int != None:
|
||||
return long_to_ip(self.int)
|
||||
return ''
|
||||
|
||||
|
@ -166,7 +178,7 @@ class IPAddressFormField(BaseIPAddressField):
|
|||
return value
|
||||
|
||||
def to_python(self, value):
|
||||
if value==0:
|
||||
if value == 0:
|
||||
return IP(0)
|
||||
if value in validators.EMPTY_VALUES:
|
||||
return None
|
||||
|
@ -178,7 +190,6 @@ class IPAddressFormField(BaseIPAddressField):
|
|||
code='invalid')
|
||||
|
||||
class IPAddressModelField(models.GenericIPAddressField):
|
||||
__metaclass__ = models.SubfieldBase
|
||||
empty_strings_allowed = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -206,13 +217,14 @@ class IPAddressModelField(models.GenericIPAddressField):
|
|||
defaults = {'form_class': IPAddressFormField}
|
||||
defaults.update(kwargs)
|
||||
return super(models.GenericIPAddressField, self).formfield(**defaults)
|
||||
|
||||
|
||||
def deconstruct(self):
|
||||
name, path, args, kwargs = super(models.GenericIPAddressField, self).deconstruct()
|
||||
return name, path, args, kwargs
|
||||
|
||||
|
||||
class Block(models.Model):
|
||||
library = models.ForeignKey(Library, related_name='ip_auths')
|
||||
library = models.ForeignKey(Library, on_delete=models.CASCADE, related_name='ip_auths')
|
||||
lower = IPAddressModelField(db_index=True, unique=True)
|
||||
upper = IPAddressModelField(db_index=True, blank=True, null=True)
|
||||
|
||||
|
@ -247,36 +259,35 @@ def luhn_checksum(card_number):
|
|||
for d in even_digits:
|
||||
checksum += sum(digits_of(d*2))
|
||||
return checksum % 10
|
||||
|
||||
|
||||
class CardPattern(models.Model):
|
||||
library = models.ForeignKey(Library, related_name='cardnum_auths')
|
||||
library = models.ForeignKey(Library, on_delete=models.CASCADE, related_name='cardnum_auths')
|
||||
# match pattern ^\d+#+$
|
||||
pattern = models.CharField(max_length=20)
|
||||
checksum = models.BooleanField(default=True)
|
||||
|
||||
def is_valid(self, card_number):
|
||||
match_pattern='^' + self.pattern.replace('#','\d',20) + '$'
|
||||
if re.match(match_pattern,card_number) is None:
|
||||
match_pattern = '^' + self.pattern.replace('#', r'\d', 20) + '$'
|
||||
if re.match(match_pattern, card_number) is None:
|
||||
return False
|
||||
if self.checksum:
|
||||
return luhn_checksum(card_number) == 0
|
||||
else:
|
||||
return True
|
||||
return True
|
||||
|
||||
class LibraryUser(models.Model):
|
||||
library = models.ForeignKey(Library, related_name='library_users')
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='user_libraries')
|
||||
library = models.ForeignKey(Library, on_delete=models.CASCADE, related_name='library_users')
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='user_libraries',
|
||||
)
|
||||
credential = models.CharField(max_length=30, null=True)
|
||||
date_modified = models.DateTimeField(auto_now=True)
|
||||
|
||||
class EmailPattern(models.Model):
|
||||
library = models.ForeignKey(Library, related_name='email_auths')
|
||||
library = models.ForeignKey(Library, on_delete=models.CASCADE, related_name='email_auths')
|
||||
# email endswith string
|
||||
pattern = models.CharField(max_length=20)
|
||||
|
||||
def is_valid(self, email):
|
||||
if email.lower().endswith(self.pattern.lower()):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
return email.lower().endswith(self.pattern.lower())
|
||||
|
|
|
@ -8,16 +8,17 @@ logger = logging.getLogger(__name__)
|
|||
@receiver(registration.signals.user_activated)
|
||||
def handle_same_email_account(sender, user, **kwargs):
|
||||
logger.info('checking %s' % user.username)
|
||||
old_users=User.objects.exclude(id=user.id).filter(email=user.email)
|
||||
old_users = User.objects.exclude(id=user.id).filter(email=user.email)
|
||||
for old_user in old_users:
|
||||
# decide why there's a previous user with this email
|
||||
if not old_user.is_active:
|
||||
# never activated
|
||||
old_user.delete()
|
||||
elif old_user.date_joined < user.date_joined:
|
||||
# relax
|
||||
# relax
|
||||
pass
|
||||
else:
|
||||
# shouldn't happen; don't want to delete the user in case the user is being used for something
|
||||
old_user.email= '%s.unglue.it'% old_user.email
|
||||
|
||||
else:
|
||||
# shouldn't happen; don't want to delete the user
|
||||
# in case the user is being used for something
|
||||
old_user.email = '%s.unglue.it'% old_user.email
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import unicodedata
|
||||
|
||||
from django.template import Library
|
||||
from .. import models
|
||||
|
||||
|
@ -11,7 +9,7 @@ def libname(value):
|
|||
returns library name .
|
||||
"""
|
||||
try:
|
||||
vl = long( value )
|
||||
vl = long(value)
|
||||
lib = models.Library.objects.get(pk=vl)
|
||||
return lib.__unicode__()
|
||||
except models.Library.DoesNotExist:
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
import unittest
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
class TestLibraryAuth(TestCase):
|
||||
fixtures=['initial_data.json']
|
||||
fixtures = ['initial_data.json']
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def test_login(self):
|
||||
resp = self.client.get(reverse('superlogin'), data={'next': '/'})
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.client.cookies['un'] = 'bob'
|
||||
resp = self.client.get(reverse('superlogin'), data={'next': '/'})
|
||||
self.assertEqual(200, resp.status_code)
|
||||
resp = self.client.post(reverse('superlogin'), data={'username': 'bob'})
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
def test_pages(self):
|
||||
resp = self.client.get(reverse('registration_register'))
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
|
||||
def test_registration(self):
|
||||
"""
|
||||
LibraryAuth Registration creates a new inactive account and a new profile
|
||||
|
@ -30,12 +36,12 @@ class TestLibraryAuth(TestCase):
|
|||
|
||||
new_user = User.objects.get(username='bob')
|
||||
|
||||
self.failUnless(new_user.check_password('secret'))
|
||||
self.assertTrue(new_user.check_password('secret'))
|
||||
self.assertEqual(new_user.email, 'bob@example.com')
|
||||
|
||||
# New user must not be active.
|
||||
self.failIf(new_user.is_active)
|
||||
|
||||
self.assertFalse(new_user.is_active)
|
||||
|
||||
def test_bad_registration(self):
|
||||
"""
|
||||
LibraryAuth Registration rejects.
|
||||
|
@ -47,13 +53,11 @@ class TestLibraryAuth(TestCase):
|
|||
'password1': 'secret',
|
||||
'password2': 'secret'})
|
||||
self.assertTrue('Please supply a permanent email address' in resp.content)
|
||||
|
||||
|
||||
with self.assertRaises(User.DoesNotExist):
|
||||
User.objects.get(username='badbob')
|
||||
|
||||
|
||||
def test_is_disposable(self):
|
||||
from .emailcheck import is_disposable
|
||||
self.assertFalse(is_disposable('eric@hellman.net'))
|
||||
self.assertTrue(is_disposable('eric@mailnesia.com'))
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
from django.conf.urls import patterns, url, include
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.views import password_reset
|
||||
from . import views, models, forms
|
||||
from . import views, forms
|
||||
from .views import superlogin
|
||||
|
||||
# class to reproduce django 1.4 funtionality
|
||||
class ExtraContextTemplateView(TemplateView):
|
||||
extra_context = None
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(self.__class__, self).get_context_data(**kwargs)
|
||||
context = super(ExtraContextTemplateView, self).get_context_data(**kwargs)
|
||||
if self.extra_context is not None:
|
||||
for key, value in self.extra_context.items():
|
||||
if callable(value):
|
||||
|
@ -21,49 +21,59 @@ class ExtraContextTemplateView(TemplateView):
|
|||
|
||||
urlpatterns = [
|
||||
url(r'^libraryauth/(?P<library_id>\d+)/join/$', views.join_library, name='join_library'),
|
||||
url(r'^libraryauth/(?P<library_id>\d+)/deny/$', TemplateView.as_view(template_name='libraryauth/denied.html'), name='bad_library'),
|
||||
url(r'^libraryauth/(?P<library_id>\d+)/users/$', views.library, {'template':'libraryauth/users.html'}, name='library_users'),
|
||||
url(r'^libraryauth/(?P<library_id>\d+)/admin/$', login_required(views.UpdateLibraryView.as_view()), name='library_admin'),
|
||||
url(r'^libraryauth/(?P<library_id>\d+)/login/$', views.login_as_library, name='library_login'),
|
||||
url(r'^libraryauth/create/$', login_required(views.CreateLibraryView.as_view()), name='library_create'),
|
||||
url(r'^libraryauth/(?P<library_id>\d+)/deny/$',
|
||||
TemplateView.as_view(template_name='libraryauth/denied.html'),
|
||||
name='bad_library'),
|
||||
url(r'^libraryauth/(?P<library_id>\d+)/users/$',
|
||||
views.library, {'template':'libraryauth/users.html'},
|
||||
name='library_users'),
|
||||
url(r'^libraryauth/(?P<library_id>\d+)/admin/$',
|
||||
login_required(views.UpdateLibraryView.as_view()),
|
||||
name='library_admin'),
|
||||
url(r'^libraryauth/(?P<library_id>\d+)/login/$', views.login_as_library, name='library_login'),
|
||||
url(r'^libraryauth/create/$',
|
||||
login_required(views.CreateLibraryView.as_view()),
|
||||
name='library_create'),
|
||||
url(r'^libraryauth/list/$', ExtraContextTemplateView.as_view(
|
||||
template_name='libraryauth/list.html',
|
||||
extra_context={'libraries_to_show':'approved'}
|
||||
), name='library_list'),
|
||||
template_name='libraryauth/list.html',
|
||||
extra_context={'libraries_to_show':'approved'}
|
||||
), name='library_list'),
|
||||
url(r'^libraryauth/unapproved/$', ExtraContextTemplateView.as_view(
|
||||
template_name='libraryauth/list.html',
|
||||
extra_context={'libraries_to_show':'new'}
|
||||
), name='new_libraries'),
|
||||
url(r'^accounts/register/$', views.CustomRegistrationView.as_view(), name='registration_register'),
|
||||
template_name='libraryauth/list.html',
|
||||
extra_context={'libraries_to_show':'new'}
|
||||
), name='new_libraries'),
|
||||
url(r'^accounts/register/$',
|
||||
views.CustomRegistrationView.as_view(),
|
||||
name='registration_register'),
|
||||
url(r'^accounts/superlogin/$', views.superlogin, name='superlogin'),
|
||||
url(r'^accounts/superlogin/welcome/$', ExtraContextTemplateView.as_view(
|
||||
template_name='registration/welcome.html',
|
||||
extra_context={'suppress_search_box': True,}
|
||||
) ),
|
||||
template_name='registration/welcome.html',
|
||||
extra_context={'suppress_search_box': True,}
|
||||
)),
|
||||
url(r'^accounts/login/pledge/$', superlogin,
|
||||
{'template_name': 'registration/from_pledge.html'}),
|
||||
{'template_name': 'registration/from_pledge.html'}),
|
||||
url(r'^accounts/login/purchase/$', superlogin,
|
||||
{'template_name': 'registration/from_purchase.html'}),
|
||||
{'template_name': 'registration/from_purchase.html'}),
|
||||
url(r'^accounts/login/add/$', superlogin,
|
||||
{'template_name': 'registration/from_add.html'}),
|
||||
{'template_name': 'registration/from_add.html'}),
|
||||
url(r'^accounts/activate/complete/$', superlogin,
|
||||
{'template_name': 'registration/activation_complete.html'}),
|
||||
{'template_name': 'registration/activation_complete.html'}),
|
||||
url(r'^accounts/login-error/$', superlogin,
|
||||
{'template_name': 'registration/from_error.html'}),
|
||||
{'template_name': 'registration/from_error.html'}),
|
||||
url(r'^accounts/edit/$', views.edit_user, name='edit_user'),
|
||||
url(r'^accounts/login/welcome/$', ExtraContextTemplateView.as_view(
|
||||
template_name='registration/welcome.html',
|
||||
extra_context={'suppress_search_box': True,}
|
||||
) ),
|
||||
template_name='registration/welcome.html',
|
||||
extra_context={'suppress_search_box': True,}
|
||||
)),
|
||||
url(r'^accounts/password/change/$',
|
||||
views.social_aware_password_change,
|
||||
{'post_change_redirect': reverse_lazy('auth_password_change_done')},
|
||||
name='libraryauth_password_change'),
|
||||
views.social_aware_password_change,
|
||||
{'post_change_redirect': reverse_lazy('auth_password_change_done')},
|
||||
name='libraryauth_password_change'),
|
||||
url(r'^password/reset/$',
|
||||
password_reset,
|
||||
{'post_reset_redirect': reverse_lazy('auth_password_reset_done'),
|
||||
'password_reset_form': forms.SocialAwarePasswordResetForm},
|
||||
name='libraryauth_password_reset'),
|
||||
password_reset,
|
||||
{'post_reset_redirect': reverse_lazy('auth_password_reset_done'),
|
||||
'password_reset_form': forms.SocialAwarePasswordResetForm},
|
||||
name='libraryauth_password_reset'),
|
||||
|
||||
url(r'^socialauth/', include('social_django.urls', namespace='social')),
|
||||
url('accounts/', include('email_change.urls')),
|
||||
|
|
|
@ -1,25 +1,26 @@
|
|||
import logging
|
||||
import random
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.contrib.auth.forms import SetPasswordForm
|
||||
from django.contrib.auth.views import login, password_reset, password_change
|
||||
from django.contrib.auth import login as login_to_user
|
||||
from django.contrib.auth import load_backend
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.views.generic.edit import FormView, CreateView, UpdateView, SingleObjectMixin
|
||||
from django.contrib.auth.forms import SetPasswordForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.views import password_change, LoginView
|
||||
from django.http import HttpResponseRedirect, Http404
|
||||
|
||||
from django.views.generic.edit import CreateView, UpdateView
|
||||
|
||||
from registration.backends.model_activation.views import RegistrationView
|
||||
|
||||
from . import backends
|
||||
from .models import Library
|
||||
from .forms import AuthForm, LibraryForm, NewLibraryForm, RegistrationFormNoDisposableEmail, UserData
|
||||
from .forms import LibraryForm, NewLibraryForm, RegistrationFormNoDisposableEmail, UserData
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def get_library_or_404(library=None, library_id=None):
|
||||
def get_library_or_404(library=None, library_id=None):
|
||||
if library_id:
|
||||
try:
|
||||
return get_object_or_404(Library, id=library_id)
|
||||
|
@ -28,36 +29,53 @@ def get_library_or_404(library=None, library_id=None):
|
|||
else:
|
||||
return get_object_or_404(Library, user__username=library)
|
||||
|
||||
def library(request, library=None, library_id=None,
|
||||
extra_context={},
|
||||
template='libraryauth/library.html',
|
||||
def library(
|
||||
request, library=None, library_id=None,
|
||||
extra_context={}, template='libraryauth/library.html',
|
||||
**kwargs):
|
||||
library=get_library_or_404(library=library, library_id=library_id)
|
||||
context={ 'library':library,
|
||||
'is_admin': request.user.is_staff or request.user==library.user,
|
||||
'is_member': request.user.is_staff or library.has_user(request.user),
|
||||
}
|
||||
library = get_library_or_404(library=library, library_id=library_id)
|
||||
context = {
|
||||
'library':library,
|
||||
'is_admin': request.user.is_staff or request.user == library.user,
|
||||
'is_member': request.user.is_staff or library.has_user(request.user),
|
||||
}
|
||||
context.update(extra_context)
|
||||
return render(request, template, context)
|
||||
|
||||
def join_library(request, library_id):
|
||||
library=get_library_or_404(library_id=library_id)
|
||||
return Authenticator(request,library).process(
|
||||
reverse('library',args=[library.user]),
|
||||
reverse('bad_library',args=[library.id]),
|
||||
)
|
||||
library = get_library_or_404(library_id=library_id)
|
||||
return Authenticator(request, library).process(
|
||||
reverse('library', args=[library.user]),
|
||||
reverse('bad_library', args=[library.id]),
|
||||
)
|
||||
|
||||
class SuperLoginView(LoginView):
|
||||
def get_initial(self):
|
||||
initial = super(SuperLoginView, self).get_initial()
|
||||
if self.request.method == 'GET':
|
||||
saved_un = self.request.COOKIES.get('un', None)
|
||||
initial["username"] = saved_un
|
||||
return initial
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if 'add' in self.request.GET:
|
||||
self.request.session["add_wishlist"] = self.request.GET["add"]
|
||||
return super(SuperLoginView, self).get(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(SuperLoginView, self).get_context_data(**kwargs)
|
||||
if self.request.method == 'POST' and self.request.user.is_anonymous:
|
||||
username = self.request.POST.get("username", "")
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
context['socials'] = user.profile.social_auths
|
||||
except:
|
||||
pass
|
||||
return context
|
||||
|
||||
def superlogin(request, extra_context={}, **kwargs):
|
||||
if request.method == 'POST' and request.user.is_anonymous():
|
||||
username=request.POST.get("username", "")
|
||||
try:
|
||||
user=models.User.objects.get(username=username)
|
||||
extra_context={"socials":user.profile.social_auths}
|
||||
except:
|
||||
pass
|
||||
if request.GET.has_key("add"):
|
||||
request.session["add_wishlist"]=request.GET["add"]
|
||||
return login(request, extra_context=extra_context, authentication_form=AuthForm, **kwargs)
|
||||
return SuperLoginView.as_view(extra_context=extra_context, **kwargs)(request)
|
||||
|
||||
|
||||
def social_aware_password_change(request, **kwargs):
|
||||
if request.user.has_usable_password():
|
||||
|
@ -65,55 +83,56 @@ def social_aware_password_change(request, **kwargs):
|
|||
return password_change(request, password_change_form=SetPasswordForm, **kwargs)
|
||||
|
||||
class Authenticator:
|
||||
request=None
|
||||
library=None
|
||||
request = None
|
||||
library = None
|
||||
|
||||
def __init__(self, request, library, *args, **kwargs):
|
||||
self.request = request
|
||||
if isinstance(library , basestring):
|
||||
if isinstance(library, basestring):
|
||||
self.library = Library.objects.get(user__username=library)
|
||||
elif isinstance(library , Library):
|
||||
self.library=library
|
||||
elif isinstance(library, Library):
|
||||
self.library = library
|
||||
else:
|
||||
raise Exception
|
||||
self.backend_class=getattr(backends,self.library.backend)
|
||||
self.backend_class = getattr(backends, self.library.backend)
|
||||
form_class = self.backend_class.form
|
||||
if form_class:
|
||||
self.form = form_class(request, self.library, *args, **kwargs)
|
||||
else:
|
||||
self.form = None
|
||||
|
||||
|
||||
def process(self, success_url, deny_url):
|
||||
logger.info('authenticator for %s at %s.'%(self.request.user, self.library))
|
||||
if self.library.has_user(self.request.user):
|
||||
return HttpResponseRedirect(success_url)
|
||||
|
||||
|
||||
if self.backend_class().authenticate(self.request, self.library):
|
||||
if self.request.user.is_authenticated():
|
||||
if self.request.user.is_authenticated:
|
||||
self.library.add_user(self.request.user)
|
||||
return HttpResponseRedirect(success_url)
|
||||
else:
|
||||
return superlogin(self.request, extra_context={'library':self.library}, template_name='libraryauth/library_login.html')
|
||||
|
||||
else:
|
||||
return self.backend_class.authenticator().process(self, success_url, deny_url)
|
||||
|
||||
return superlogin(
|
||||
self.request,
|
||||
extra_context={'library':self.library},
|
||||
template_name='libraryauth/library_login.html'
|
||||
)
|
||||
return self.backend_class.authenticator().process(self, success_url, deny_url)
|
||||
|
||||
def allowed(self):
|
||||
return self.backend_class().authenticate(self.request, self.library)
|
||||
|
||||
|
||||
class BaseLibraryView:
|
||||
model = Library
|
||||
template_name="libraryauth/edit.html"
|
||||
|
||||
model = Library
|
||||
template_name = "libraryauth/edit.html"
|
||||
|
||||
|
||||
class CreateLibraryView(BaseLibraryView, CreateView):
|
||||
form_class = NewLibraryForm
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
return {'email': self.request.user.email}
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.owner = self.request.user
|
||||
form.instance.owner = self.request.user
|
||||
user = form.instance.user
|
||||
user.email = form.cleaned_data['email']
|
||||
user.save()
|
||||
|
@ -123,12 +142,12 @@ class CreateLibraryView(BaseLibraryView, CreateView):
|
|||
form.instance.add_user(self.request.user) # library.owner is a member of library
|
||||
context_data = self.get_context_data(form=form)
|
||||
context_data['status'] = 'Library Updated'
|
||||
return HttpResponseRedirect(reverse('library_admin',args=[form.instance.id]))
|
||||
return HttpResponseRedirect(reverse('library_admin', args=[form.instance.id]))
|
||||
|
||||
class UpdateLibraryView(BaseLibraryView, UpdateView):
|
||||
pk_url_kwarg = 'library_id'
|
||||
pk_url_kwarg = 'library_id'
|
||||
form_class = LibraryForm
|
||||
|
||||
|
||||
def form_valid(self, form):
|
||||
context_data = self.get_context_data(form=form)
|
||||
form.instance.save()
|
||||
|
@ -137,26 +156,33 @@ class UpdateLibraryView(BaseLibraryView, UpdateView):
|
|||
|
||||
def get_backend_form_class(self):
|
||||
if self.object and self.object.backend:
|
||||
backend_class=getattr(backends,self.object.backend)
|
||||
backend_class = getattr(backends, self.object.backend)
|
||||
return backend_class.admin_form
|
||||
else:
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
def get_backend_admin_forms(self):
|
||||
if self.object and self.object.backend:
|
||||
backend_models_name = '%s_auths' % self.object.backend
|
||||
backend_models = getattr(self.object,backend_models_name)
|
||||
backend_new_form = self.get_backend_form_class()(initial = {'library':self.object}, prefix="new")
|
||||
backend_old_forms = [self.get_backend_form_class()(instance = backend_model, prefix="backend_%s"%backend_model.id) for backend_model in backend_models.all()]
|
||||
backend_models = getattr(self.object, backend_models_name)
|
||||
backend_new_form = self.get_backend_form_class()(
|
||||
initial={'library': self.object},
|
||||
prefix="new",
|
||||
)
|
||||
backend_old_forms = [self.get_backend_form_class()(
|
||||
instance=backend_model,
|
||||
prefix="backend_%s"%backend_model.id,
|
||||
) for backend_model in backend_models.all()]
|
||||
return backend_old_forms + [backend_new_form]
|
||||
else:
|
||||
return []
|
||||
|
||||
return []
|
||||
|
||||
def get_context_data(self, backend_form=None, form=None, **kwargs):
|
||||
context = super(UpdateLibraryView,self).get_context_data(**kwargs)
|
||||
context = super(UpdateLibraryView, self).get_context_data(**kwargs)
|
||||
backend_admin_forms = self.get_backend_admin_forms()
|
||||
if backend_form:
|
||||
backend_admin_forms = [ backend_form if backend_form.prefix== backend_admin_form.prefix else backend_admin_form for backend_admin_form in backend_admin_forms]
|
||||
backend_admin_forms = [
|
||||
backend_form if backend_form.prefix == backend_admin_form.prefix \
|
||||
else backend_admin_form for backend_admin_form in backend_admin_forms
|
||||
]
|
||||
context['backend_admin_forms'] = backend_admin_forms
|
||||
if form:
|
||||
context['form'] = form
|
||||
|
@ -166,17 +192,17 @@ class UpdateLibraryView(BaseLibraryView, UpdateView):
|
|||
self.object = self.get_object()
|
||||
# check permissions
|
||||
if request.user not in [self.object.owner, self.object.user]:
|
||||
context_data={'status': 'You\'re not permitted to edit this library.'}
|
||||
context_data = {'status': 'You\'re not permitted to edit this library.'}
|
||||
return self.render_to_response(context_data)
|
||||
form = self.get_form(self.form_class)
|
||||
return self.render_to_response(self.get_context_data(form=form))
|
||||
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
# get the user instance (the library)
|
||||
self.object = self.get_object()
|
||||
# check permissions
|
||||
if request.user not in [self.object.owner, self.object.user]:
|
||||
context_data={'status': 'You\'re not permitted to edit this library.'}
|
||||
context_data = {'status': 'You\'re not permitted to edit this library.'}
|
||||
return self.render_to_response(context_data)
|
||||
# determine if backend form is being submitted
|
||||
# uses the name of the form's submit button
|
||||
|
@ -187,46 +213,53 @@ class UpdateLibraryView(BaseLibraryView, UpdateView):
|
|||
backend_id = request.POST['id']
|
||||
if 'backend_submit' in request.POST:
|
||||
# we're editing the backend
|
||||
if backend_id is None or backend_id=="None":
|
||||
if backend_id is None or backend_id == "None":
|
||||
backend_model_instance = form_model(library=self.object)
|
||||
form = form_class(data=request.POST, instance=backend_model_instance, prefix="new")
|
||||
form = form_class(
|
||||
data=request.POST,
|
||||
instance=backend_model_instance,
|
||||
prefix="new"
|
||||
)
|
||||
else:
|
||||
backend_model_instance = form_model.objects.get(id=backend_id)
|
||||
form = form_class(data=request.POST, instance=backend_model_instance, prefix="backend_%s"%request.POST['id'])
|
||||
form = form_class(
|
||||
data=request.POST,
|
||||
instance=backend_model_instance,
|
||||
prefix="backend_%s"%request.POST['id'],
|
||||
)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
status = 'User Validation Updated.'
|
||||
context_data = self.get_context_data( form=self.form_class(instance=self.object))
|
||||
context_data = self.get_context_data(
|
||||
form=self.form_class(instance=self.object))
|
||||
else:
|
||||
status = 'Problem with User Validation.'
|
||||
context_data = self.get_context_data(backend_form=form, form=self.form_class(instance=self.object))
|
||||
context_data = self.get_context_data(
|
||||
backend_form=form, form=self.form_class(instance=self.object))
|
||||
else:
|
||||
#deleting a backend
|
||||
if backend_id is not None and backend_id!="None":
|
||||
if backend_id is not None and backend_id != "None":
|
||||
backend_model_instance = form_model.objects.get(id=backend_id)
|
||||
backend_model_instance.delete()
|
||||
status = 'Deleted.'
|
||||
else:
|
||||
status = 'Nothing to delete.'
|
||||
context_data = self.get_context_data( form=self.form_class(instance=self.object))
|
||||
context_data = self.get_context_data(form=self.form_class(instance=self.object))
|
||||
context_data['status'] = status
|
||||
return self.render_to_response(context_data)
|
||||
else:
|
||||
# just use regular post handler
|
||||
# just use regular post handler
|
||||
form = self.get_form(self.form_class)
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
@login_required
|
||||
def login_as_library(request, library_id):
|
||||
library=get_library_or_404(library_id=library_id)
|
||||
def login_as_library(request, library_id):
|
||||
library = get_library_or_404(library_id=library_id)
|
||||
if request.user == library.owner:
|
||||
login_user(request, library.user)
|
||||
|
||||
return HttpResponseRedirect(reverse('library_admin',args=[library.id]))
|
||||
|
||||
return HttpResponseRedirect(reverse('library_admin', args=[library.id]))
|
||||
|
||||
def login_user(request, user):
|
||||
"""
|
||||
|
@ -244,36 +277,35 @@ def login_user(request, user):
|
|||
return login_to_user(request, user)
|
||||
|
||||
robot_qs = {
|
||||
'user',
|
||||
'user/register',
|
||||
'node/add',
|
||||
}
|
||||
|
||||
'user',
|
||||
'user/register',
|
||||
'node/add',
|
||||
}
|
||||
|
||||
class CustomRegistrationView(RegistrationView):
|
||||
form_class = RegistrationFormNoDisposableEmail
|
||||
def form_valid(self, form):
|
||||
q = self.request.session.get('q', False)
|
||||
q = self.request.session.get('q', False)
|
||||
if q and q in robot_qs:
|
||||
return self.render_to_response({'form':form})
|
||||
return super(CustomRegistrationView,self).form_valid(form)
|
||||
|
||||
return super(CustomRegistrationView, self).form_valid(form)
|
||||
|
||||
def edit_user(request, redirect_to=None):
|
||||
if not request.user.is_authenticated():
|
||||
return HttpResponseRedirect(reverse('superlogin'))
|
||||
form=UserData()
|
||||
if request.method == 'POST':
|
||||
if not request.user.is_authenticated:
|
||||
return HttpResponseRedirect(reverse('superlogin'))
|
||||
form = UserData()
|
||||
if request.method == 'POST':
|
||||
if 'change_username' in request.POST.keys():
|
||||
form = UserData(request.POST)
|
||||
form.oldusername = request.user.username
|
||||
if form.is_valid(): # All validation rules pass, go and change the username
|
||||
request.user.username=form.cleaned_data['username']
|
||||
request.user.username = form.cleaned_data['username']
|
||||
request.user.save()
|
||||
if 'set_password' in request.POST.keys() and form.cleaned_data.has_key('set_password'):
|
||||
if 'set_password' in request.POST.keys() and \
|
||||
form.cleaned_data.has_key('set_password'):
|
||||
if not request.user.has_usable_password():
|
||||
request.user.set_password(form.cleaned_data['set_password'])
|
||||
request.user.save()
|
||||
return HttpResponseRedirect(redirect_to if redirect_to else reverse('home')) # Redirect after POST
|
||||
return render(request,'registration/user_change_form.html', {'form': form})
|
||||
|
||||
|
||||
|
||||
# Redirect after POST
|
||||
return HttpResponseRedirect(redirect_to if redirect_to else reverse('home'))
|
||||
return render(request, 'registration/user_change_form.html', {'form': form})
|
||||
|
|
|
@ -11,7 +11,7 @@ from datetime import datetime
|
|||
from StringIO import StringIO
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
|
||||
import regluit.core.cc as cc
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('guts', models.TextField()),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('edition', models.ForeignKey(related_name='MARCRecords', to='core.Edition', null=True)),
|
||||
('user', models.ForeignKey(related_name='MARCRecords', to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('edition', models.ForeignKey(on_delete=models.CASCADE, related_name='MARCRecords', to='core.Edition', null=True)),
|
||||
('user', models.ForeignKey(on_delete=models.CASCADE, related_name='MARCRecords', to=settings.AUTH_USER_MODEL, null=True)),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -93,9 +93,9 @@ class MARCRecord(models.Model):
|
|||
_the_record = None
|
||||
|
||||
# note capitalization of related_name
|
||||
edition = models.ForeignKey(EDITION_MODEL, related_name="MARCRecords", null=True)
|
||||
edition = models.ForeignKey(EDITION_MODEL, on_delete=models.CASCADE, related_name="MARCRecords", null=True)
|
||||
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="MARCRecords", null=True )
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="MARCRecords", null=True )
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.conf.urls import patterns, url, include
|
||||
from django.conf.urls import url, include
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from . import views
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ from xml.sax import SAXParseException
|
|||
|
||||
from django.apps import apps
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse, reverse_lazy
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseNotFound
|
||||
from django.views.generic.edit import FormView
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ django imports
|
|||
"""
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.utils.timezone import now
|
||||
|
||||
"""
|
||||
|
@ -486,7 +486,7 @@ class PaymentManager( object ):
|
|||
else:
|
||||
transaction.error = p.error_string()
|
||||
transaction.save()
|
||||
logger.info("execute_transaction Error: " + p.error_string())
|
||||
logger.info("execute_transaction Error: {}".format(p.error_string()))
|
||||
return False
|
||||
|
||||
def cancel_transaction(self, transaction):
|
||||
|
@ -526,7 +526,7 @@ class PaymentManager( object ):
|
|||
else:
|
||||
transaction.error = p.error_string()
|
||||
transaction.save()
|
||||
logger.info("Cancel Transaction " + str(transaction.id) + " Failed with error: " + p.error_string())
|
||||
logger.info("Cancel Transaction {} Failed with error: {}".format(transaction.id, p.error_string()))
|
||||
return False
|
||||
|
||||
else:
|
||||
|
@ -665,7 +665,7 @@ class PaymentManager( object ):
|
|||
else:
|
||||
transaction.error = p.error_string()
|
||||
transaction.save()
|
||||
logger.info("Pay Error: " + p.error_string())
|
||||
logger.info("Pay Error: {}".format(p.error_string()))
|
||||
return transaction, None
|
||||
|
||||
|
||||
|
@ -711,7 +711,7 @@ class PaymentManager( object ):
|
|||
)
|
||||
t.save()
|
||||
# does user have enough credit to transact now?
|
||||
if user.is_authenticated() and user.credit.available >= amount :
|
||||
if user.is_authenticated and user.credit.available >= amount :
|
||||
# YES!
|
||||
return_path = "{0}?{1}".format(reverse('pledge_complete'),
|
||||
urllib.urlencode({'tid':t.id}))
|
||||
|
@ -958,7 +958,7 @@ class PaymentManager( object ):
|
|||
else:
|
||||
transaction.error = p.error_string()
|
||||
transaction.save()
|
||||
logger.info("Refund Transaction " + str(transaction.id) + " Failed with error: " + p.error_string())
|
||||
logger.info("Refund Transaction {} Failed with error: {}".format(str(transaction.id), p.error_string()))
|
||||
return False
|
||||
|
||||
def make_account(self, user=None, host=None, token=None):
|
||||
|
|
|
@ -31,7 +31,7 @@ class Migration(migrations.Migration):
|
|||
('date_modified', models.DateTimeField(auto_now=True)),
|
||||
('date_deactivated', models.DateTimeField(null=True)),
|
||||
('status', models.CharField(default=b'ACTIVE', max_length=11, choices=[(b'ACTIVE', b'ACTIVE'), (b'DEACTIVATED', b'DEACTIVATED'), (b'EXPIRED', b'EXPIRED'), (b'EXPIRING', b'EXPIRING'), (b'ERROR', b'ERROR')])),
|
||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('user', models.ForeignKey(on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -41,7 +41,7 @@ class Migration(migrations.Migration):
|
|||
('balance', models.DecimalField(default=Decimal('0.00'), max_digits=14, decimal_places=2)),
|
||||
('pledged', models.DecimalField(default=Decimal('0.00'), max_digits=14, decimal_places=2)),
|
||||
('last_activity', models.DateTimeField(auto_now=True)),
|
||||
('user', models.OneToOneField(related_name='credit', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.OneToOneField(on_delete=models.CASCADE, related_name='credit', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -52,7 +52,7 @@ class Migration(migrations.Migration):
|
|||
('timestamp', models.DateTimeField(auto_now=True)),
|
||||
('action', models.CharField(max_length=16)),
|
||||
('sent', models.IntegerField(null=True)),
|
||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('user', models.ForeignKey(on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -116,20 +116,20 @@ class Migration(migrations.Migration):
|
|||
('date_expired', models.DateTimeField(null=True)),
|
||||
('extra', jsonfield.fields.JSONField(default={}, null=True)),
|
||||
('anonymous', models.BooleanField(default=False)),
|
||||
('campaign', models.ForeignKey(to='core.Campaign', null=True)),
|
||||
('offer', models.ForeignKey(to='core.Offer', null=True)),
|
||||
('premium', models.ForeignKey(to='core.Premium', null=True)),
|
||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('campaign', models.ForeignKey(on_delete=models.CASCADE, to='core.Campaign', null=True)),
|
||||
('offer', models.ForeignKey(on_delete=models.CASCADE, to='core.Offer', null=True)),
|
||||
('premium', models.ForeignKey(on_delete=models.CASCADE, to='core.Premium', null=True)),
|
||||
('user', models.ForeignKey(on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='receiver',
|
||||
name='transaction',
|
||||
field=models.ForeignKey(to='payment.Transaction'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, to='payment.Transaction'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='paymentresponse',
|
||||
name='transaction',
|
||||
field=models.ForeignKey(to='payment.Transaction'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, to='payment.Transaction'),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -115,10 +115,10 @@ class Transaction(models.Model):
|
|||
date_expired = models.DateTimeField(null=True)
|
||||
|
||||
# associated User, Campaign, and Premium for this Transaction
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
|
||||
campaign = models.ForeignKey('core.Campaign', null=True)
|
||||
premium = models.ForeignKey('core.Premium', null=True)
|
||||
offer = models.ForeignKey('core.Offer', null=True)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
|
||||
campaign = models.ForeignKey('core.Campaign', on_delete=models.CASCADE, null=True)
|
||||
premium = models.ForeignKey('core.Premium', on_delete=models.CASCADE, null=True)
|
||||
offer = models.ForeignKey('core.Offer', on_delete=models.CASCADE, null=True)
|
||||
extra = JSONField(null=True, default={})
|
||||
|
||||
# whether the user wants to be not listed publicly
|
||||
|
@ -145,7 +145,7 @@ class Transaction(models.Model):
|
|||
|
||||
@property
|
||||
def needed_amount(self):
|
||||
if self.user is None or self.user.is_anonymous():
|
||||
if self.user is None or self.user.is_anonymous:
|
||||
return self.max_amount
|
||||
if self.user.credit.available >= self.max_amount:
|
||||
return 0
|
||||
|
@ -153,7 +153,7 @@ class Transaction(models.Model):
|
|||
|
||||
@property
|
||||
def credit_amount(self):
|
||||
if self.user is None or self.user.is_anonymous():
|
||||
if self.user is None or self.user.is_anonymous:
|
||||
return 0
|
||||
if self.user.credit.available >= self.max_amount:
|
||||
return self.max_amount
|
||||
|
@ -233,7 +233,7 @@ class Transaction(models.Model):
|
|||
def create(cls, amount=0.00, host=PAYMENT_HOST_NONE, max_amount=0.00, currency='USD',
|
||||
status=TRANSACTION_STATUS_NONE, campaign=None, user=None, pledge_extra=None,
|
||||
donation=False):
|
||||
if user and user.is_anonymous():
|
||||
if user and user.is_anonymous:
|
||||
user = None
|
||||
t = cls.objects.create(
|
||||
amount=amount,
|
||||
|
@ -265,7 +265,7 @@ class PaymentResponse(models.Model):
|
|||
# local status specific to the api call
|
||||
status = models.CharField(max_length=32, null=True)
|
||||
|
||||
transaction = models.ForeignKey(Transaction, null=False)
|
||||
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE, null=False)
|
||||
|
||||
def __unicode__(self):
|
||||
return u"PaymentResponse -- api: {0} correlation_id: {1} transaction: {2}".format(
|
||||
|
@ -287,7 +287,7 @@ class Receiver(models.Model):
|
|||
reason = models.CharField(max_length=64)
|
||||
primary = models.BooleanField(default=True)
|
||||
txn_id = models.CharField(max_length=64)
|
||||
transaction = models.ForeignKey(Transaction)
|
||||
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE,)
|
||||
|
||||
def __unicode__(self):
|
||||
return u"Receiver -- email: {0} status: {1} transaction: {2}".format(
|
||||
|
@ -298,7 +298,7 @@ class Receiver(models.Model):
|
|||
|
||||
class CreditLog(models.Model):
|
||||
# a write only record of Unglue.it Credit Transactions
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
|
||||
amount = models.DecimalField(default=Decimal('0.00'), max_digits=14, decimal_places=2) # max 999,999,999,999.99
|
||||
timestamp = models.DateTimeField(auto_now=True)
|
||||
action = models.CharField(max_length=16)
|
||||
|
@ -306,7 +306,7 @@ class CreditLog(models.Model):
|
|||
sent = models.IntegerField(null=True)
|
||||
|
||||
class Credit(models.Model):
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='credit')
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='credit')
|
||||
balance = models.DecimalField(default=Decimal('0.00'), max_digits=14, decimal_places=2) # max 999,999,999,999.99
|
||||
pledged = models.DecimalField(default=Decimal('0.00'), max_digits=14, decimal_places=2) # max 999,999,999,999.99
|
||||
last_activity = models.DateTimeField(auto_now=True)
|
||||
|
@ -421,7 +421,7 @@ class Account(models.Model):
|
|||
date_deactivated = models.DateTimeField(null=True)
|
||||
|
||||
# associated User if any
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
|
||||
|
||||
# status variable
|
||||
status = models.CharField(max_length=11, choices=STATUS_CHOICES, null=False, default='ACTIVE')
|
||||
|
|
|
@ -421,7 +421,7 @@ class StripeErrorTest(TestCase):
|
|||
self.fail("Attempt to create customer did not throw expected exception.")
|
||||
except stripe.CardError as e:
|
||||
self.assertEqual(e.code, "card_declined")
|
||||
self.assertEqual(e.message, "Your card was declined")
|
||||
self.assertEqual(e.args[0], "Your card was declined")
|
||||
|
||||
def test_charge_bad_cust(self):
|
||||
# expect the card to be declined -- and for us to get CardError
|
||||
|
@ -450,7 +450,7 @@ class StripeErrorTest(TestCase):
|
|||
self.fail("Attempt to create token with bad cc number did not throw expected exception.")
|
||||
except stripe.CardError as e:
|
||||
self.assertEqual(e.code, "incorrect_number")
|
||||
self.assertEqual(e.message, "Your card number is incorrect")
|
||||
self.assertEqual(e.args[0], "Your card number is incorrect")
|
||||
|
||||
def test_invalid_expiry_month(self):
|
||||
"""Use an invalid month e.g. 13."""
|
||||
|
@ -464,7 +464,7 @@ class StripeErrorTest(TestCase):
|
|||
self.fail("Attempt to create token with invalid expiry month did not throw expected exception.")
|
||||
except stripe.CardError as e:
|
||||
self.assertEqual(e.code, "invalid_expiry_month")
|
||||
self.assertEqual(e.message, "Your card's expiration month is invalid")
|
||||
self.assertEqual(e.args[0], "Your card's expiration month is invalid")
|
||||
|
||||
def test_invalid_expiry_year(self):
|
||||
"""Use a year in the past e.g. 1970."""
|
||||
|
@ -478,7 +478,7 @@ class StripeErrorTest(TestCase):
|
|||
self.fail("Attempt to create token with invalid expiry year did not throw expected exception.")
|
||||
except stripe.CardError as e:
|
||||
self.assertEqual(e.code, "invalid_expiry_year")
|
||||
self.assertEqual(e.message, "Your card's expiration year is invalid")
|
||||
self.assertEqual(e.args[0], "Your card's expiration year is invalid")
|
||||
|
||||
def test_invalid_cvc(self):
|
||||
"""Use a two digit number e.g. 99."""
|
||||
|
@ -492,7 +492,7 @@ class StripeErrorTest(TestCase):
|
|||
self.fail("Attempt to create token with invalid cvc did not throw expected exception.")
|
||||
except stripe.CardError as e:
|
||||
self.assertEqual(e.code, "invalid_cvc")
|
||||
self.assertEqual(e.message, "Your card's security code is invalid")
|
||||
self.assertEqual(e.args[0], "Your card's security code is invalid")
|
||||
|
||||
def test_missing_card(self):
|
||||
"""There is no card on a customer that is being charged"""
|
||||
|
@ -504,7 +504,7 @@ class StripeErrorTest(TestCase):
|
|||
sc.create_charge(10, customer = cust1.id, description="$10 for cust w/ no card")
|
||||
except stripe.CardError as e:
|
||||
self.assertEqual(e.code, "missing")
|
||||
self.assertEqual(e.message, "Cannot charge a customer that has no active card")
|
||||
self.assertEqual(e.args[0], "Cannot charge a customer that has no active card")
|
||||
|
||||
class PledgeScenarioTest(TestCase):
|
||||
@classmethod
|
||||
|
@ -578,7 +578,7 @@ class Processor(baseprocessor.Processor):
|
|||
else:
|
||||
customer = sc.create_customer(card=token, description='anonymous user', email=email)
|
||||
except stripe.StripeError as e:
|
||||
raise StripelibError(e.message, e)
|
||||
raise StripelibError(e.args, e)
|
||||
|
||||
account = Account(host = PAYMENT_HOST_STRIPE,
|
||||
account_id = customer.id,
|
||||
|
@ -696,7 +696,7 @@ class Processor(baseprocessor.Processor):
|
|||
transaction.save()
|
||||
else:
|
||||
self.errorMessage = p.errorMessage #pass error message up
|
||||
logger.info("execute_transaction Error: " + p.error_string())
|
||||
logger.info("execute_transaction Error: {}".format(p.error_string()))
|
||||
|
||||
def amount( self ):
|
||||
return self.transaction.amount
|
||||
|
@ -746,11 +746,11 @@ class Processor(baseprocessor.Processor):
|
|||
# use PaymentResponse to store error
|
||||
|
||||
r = PaymentResponse.objects.create(api="stripelib.Execute", correlation_id=None,
|
||||
timestamp=now(), info=e.message,
|
||||
timestamp=now(), info=e.args[0],
|
||||
status=TRANSACTION_STATUS_ERROR, transaction=transaction)
|
||||
|
||||
transaction.status = TRANSACTION_STATUS_ERROR
|
||||
self.errorMessage = e.message # manager puts this on transaction
|
||||
self.errorMessage = e.args # manager puts this on transaction
|
||||
transaction.save()
|
||||
|
||||
# fire off the fact that transaction failed -- should actually do so only if not a transient error
|
||||
|
@ -759,9 +759,8 @@ class Processor(baseprocessor.Processor):
|
|||
transaction_failed.send(sender=self, transaction=transaction)
|
||||
# otherwise, report exception to us
|
||||
else:
|
||||
logger.exception("transaction id {0}, exception: {1}".format(transaction.id, e.message))
|
||||
logger.exception("transaction id {0}, exception: {1}".format(transaction.id, e.args))
|
||||
|
||||
# raise StripelibError(e.message, e)
|
||||
|
||||
else:
|
||||
self.charge = charge
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.conf import settings
|
||||
from django.conf.urls import patterns, url, include
|
||||
from django.conf.urls import url, include
|
||||
|
||||
from regluit.payment import views
|
||||
|
||||
|
|
|
@ -14,15 +14,14 @@ django imports
|
|||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.requests import RequestSite
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.urls import reverse
|
||||
from django.http import (
|
||||
HttpResponse,
|
||||
HttpRequest,
|
||||
HttpResponseRedirect,
|
||||
HttpResponseBadRequest
|
||||
)
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.shortcuts import render
|
||||
from django.test.utils import setup_test_environment
|
||||
from django.utils.timezone import now
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
@ -278,7 +277,7 @@ def checkStatus(request):
|
|||
# https://raw.github.com/agiliq/merchant/master/example/app/views.py
|
||||
|
||||
def _render(request, template, template_vars={}):
|
||||
return render_to_response(template, template_vars, RequestContext(request))
|
||||
return render(request, template, template_vars)
|
||||
|
||||
class StripeView(FormView):
|
||||
template_name="stripe.html"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Django==1.8.14
|
||||
Django==1.11.14
|
||||
Fabric==1.6.0
|
||||
MySQL-python==1.2.5
|
||||
Pillow==3.4.2
|
||||
|
@ -18,28 +18,28 @@ chardet==3.0.4
|
|||
# pip installing pillow seems to delete distribute
|
||||
# but having distribute in requirements starting to cause problems
|
||||
# distribute==0.6.28
|
||||
django-celery==3.1.17
|
||||
django-ckeditor==4.5.1
|
||||
django-celery==3.2.2
|
||||
django-ckeditor==5.6.1
|
||||
#django-email-change==0.2.3
|
||||
git+git://github.com/eshellman/django-email-change.git@57169bdef1c8a41d122e2bab2dcd8564b8fb231d
|
||||
django-compat==1.0.10
|
||||
django-contrib-comments==1.7.1
|
||||
git+git://github.com/eshellman/django-email-change.git@830808b9b9db5f3ca9ec0cb22f8fda5cc2cef12d
|
||||
django-compat==1.0.15
|
||||
django-contrib-comments==1.8.0
|
||||
django-el-pagination==3.2.4
|
||||
django-extensions==1.6.1
|
||||
django-jsonfield==1.0.0
|
||||
#django-kombu==0.9.4
|
||||
django-maintenancemode==0.11.2
|
||||
django-mptt==0.8.5
|
||||
django-mptt==0.8.6
|
||||
#django-notification==0.2
|
||||
git+git://github.com/eshellman/django-notification.git@a4620e893e2da220994e0189bf5d980bfbdcf0ad
|
||||
django-registration==2.1.2
|
||||
django-selectable==0.9.0
|
||||
git+git://github.com/eshellman/django-notification.git@92cc14b737d4a10e7e866b2f467ef1f20a89c715
|
||||
django-registration==2.4.1
|
||||
django-selectable==1.1.0
|
||||
django-smtp-ssl==1.0
|
||||
django-storages==1.5.2
|
||||
django-tastypie==0.13.3
|
||||
django-tastypie==0.14.1
|
||||
#django-transmeta==0.7.3
|
||||
git+git://github.com/resulto/django-transmeta.git@ad4d7278ba330dcf8c8446f8ae9b2c769ae8684e
|
||||
fef-questionnaire==4.0.1
|
||||
#fef-questionnaire==4.0.1
|
||||
git+git://github.com/EbookFoundation/fef-questionnaire.git@8c3b630eb6171fe9242bf0d3b456dc41de958006
|
||||
#gitenberg.metadata==0.1.6
|
||||
git+git://github.com/gitenberg-dev/gitberg-build.git@61a5fb0011e1a547b1eac14dd845ce37dbb5f85a
|
||||
#git+ssh://git@github.com/gitenberg-dev/metadata.git@0.1.11
|
||||
|
@ -47,7 +47,7 @@ github3.py==0.9.5
|
|||
html5lib==1.0.1
|
||||
httplib2==0.11.3
|
||||
isodate==0.5.1
|
||||
kombu==3.0.35
|
||||
kombu==3.0.37
|
||||
lxml==4.2.1
|
||||
defusedxml==0.4.1
|
||||
mechanize==0.2.5
|
||||
|
@ -94,7 +94,7 @@ cryptography==2.2.2
|
|||
enum34==1.1.6
|
||||
idna==2.6
|
||||
ipaddress==1.0.16
|
||||
ndg-httpsclient==0.4.2
|
||||
ndg-httpsclient==0.5.1
|
||||
pyOpenSSL==18.0.0
|
||||
pyasn1==0.1.9
|
||||
pycparser==2.14
|
||||
|
|
|
@ -40,8 +40,9 @@ MEDIA_ROOT = ''
|
|||
MEDIA_URL = '/media/'
|
||||
|
||||
# set once instead of in all the templates
|
||||
JQUERY_HOME = "/static/js/jquery-1.7.1.min.js"
|
||||
JQUERY_UI_HOME = "/static/js/jquery-ui-1.8.16.custom.min.js"
|
||||
JQUERY_HOME = "/static/js/jquery-1.12.4.min.js"
|
||||
JQUERY_UI_HOME = "/static/js/jquery-ui-1.12.1.custom.min.js"
|
||||
JQUERY_UI_THEME = "/static/css/ui-lightness/jquery-ui-1.11.4.min.css"
|
||||
|
||||
CKEDITOR_UPLOAD_PATH = ''
|
||||
CKEDITOR_RESTRICT_BY_USER = True
|
||||
|
@ -124,13 +125,12 @@ TEMPLATES = [
|
|||
]
|
||||
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
MIDDLEWARE = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'maintenancemode.middleware.MaintenanceModeMiddleware',
|
||||
'regluit.libraryauth.auth.SocialAuthExceptionMiddlewareWithoutMessages',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
'questionnaire.request_cache.RequestCacheMiddleware',
|
||||
|
@ -166,6 +166,7 @@ INSTALLED_APPS = (
|
|||
'notification',
|
||||
'email_change',
|
||||
'ckeditor',
|
||||
'ckeditor_uploader',
|
||||
'storages',
|
||||
'sorl.thumbnail',
|
||||
'mptt',
|
||||
|
@ -187,11 +188,6 @@ SASS_PROCESSOR_INCLUDE_DIRS = [
|
|||
]
|
||||
SASS_PROCESSOR_AUTO_INCLUDE = False
|
||||
|
||||
# A sample logging configuration. The only tangible logging
|
||||
# performed by this configuration is to send an email to
|
||||
# the site admins on every HTTP 500 error.
|
||||
# See http://docs.djangoproject.com/en/dev/topics/logging for
|
||||
# more details on how to customize your logging configuration.
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': True,
|
||||
|
@ -199,6 +195,10 @@ LOGGING = {
|
|||
'brief': {
|
||||
'format': '%(asctime)s %(levelname)s %(name)s[%(funcName)s]: %(message)s',
|
||||
},
|
||||
'django.server': {
|
||||
'()': 'django.utils.log.ServerFormatter',
|
||||
'format': '[%(server_time)s] %(message)s',
|
||||
},
|
||||
},
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
|
@ -219,6 +219,11 @@ LOGGING = {
|
|||
'backupCount': 5,
|
||||
'formatter': 'brief',
|
||||
},
|
||||
'django.server': {
|
||||
'level': 'INFO',
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'django.server',
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'django.request': {
|
||||
|
@ -226,10 +231,15 @@ LOGGING = {
|
|||
'level': 'ERROR',
|
||||
'propagate': True,
|
||||
},
|
||||
'django.server': {
|
||||
'handlers': ['django.server'],
|
||||
'level': 'INFO',
|
||||
'propagate': False,
|
||||
},
|
||||
'': {
|
||||
'handlers': ['file'],
|
||||
'level': 'INFO',
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,13 +421,6 @@ NOTIFICATION_QUEUE_ALL = True
|
|||
PAYMENT_PROCESSOR = 'stripelib'
|
||||
|
||||
|
||||
# by default, we are not in maintenance mode -- set True in overriding settings files for maintenance mode
|
||||
# http://pypi.python.org/pypi/django-maintenancemode/
|
||||
MAINTENANCE_MODE = False
|
||||
# Sequence of URL path regexes to exclude from the maintenance mode.
|
||||
MAINTENANCE_IGNORE_URLS = {}
|
||||
|
||||
|
||||
# we should suppress Google Analytics outside of production
|
||||
SHOW_GOOGLE_ANALYTICS = False
|
||||
|
||||
|
|
|
@ -71,8 +71,6 @@ CELERYD_HIJACK_ROOT_LOGGER = False
|
|||
# a debug_toolbar setting
|
||||
INTERNAL_IPS = ('127.0.0.1',)
|
||||
|
||||
CELERYD_LOG_LEVEL = "INFO"
|
||||
|
||||
# decide which of the period tasks to add to the schedule
|
||||
#CELERYBEAT_SCHEDULE['send_test_email'] = SEND_TEST_EMAIL_JOB
|
||||
#CELERYBEAT_SCHEDULE['refresh_acqs'] = REFRESH_ACQS_JOB
|
||||
|
|
|
@ -20,7 +20,9 @@ DATABASES = {
|
|||
'PASSWORD': '',
|
||||
'HOST': '',
|
||||
'PORT': '',
|
||||
'TEST_CHARSET': 'utf8',
|
||||
'TEST': {
|
||||
'CHARSET': 'utf8',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
urls.py
6
urls.py
|
@ -1,9 +1,9 @@
|
|||
from django.conf.urls import patterns, url, include
|
||||
from django.conf.urls import url, include
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.sitemaps.views import index, sitemap
|
||||
from django.views.decorators.cache import never_cache
|
||||
|
||||
from ckeditor import views as ckedit_views
|
||||
from ckeditor_uploader import views as ckedit_views
|
||||
|
||||
from regluit.admin import site
|
||||
from regluit.core.sitemaps import WorkSitemap, PublisherSitemap
|
||||
|
@ -21,7 +21,7 @@ urlpatterns = [
|
|||
url(r'', include('regluit.marc.urls')),
|
||||
url(r'^bisac/', include('regluit.bisac.urls')),
|
||||
url(r'^selectable/', include('selectable.urls')),
|
||||
url(r'^admin/', include(site.urls)),
|
||||
url(r'^admin/', site.urls),
|
||||
url(r'^comments/', include('django_comments.urls')),
|
||||
url(r"^notification/", include('notification.urls')),
|
||||
url(r'^ckeditor/upload/', login_required(ckedit_views.upload), name='ckeditor_upload'),
|
||||
|
|
Loading…
Reference in New Issue