mirror of
https://github.com/pinry/pinry.git
synced 2025-11-16 18:05:51 +01:00
Refactor apps to be in repo folder
This commit is contained in:
1
users/__init__.py
Normal file
1
users/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
7
users/apps.py
Normal file
7
users/apps.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class UsersConfig(AppConfig):
|
||||
name = 'users'
|
||||
0
users/auth/__init__.py
Normal file
0
users/auth/__init__.py
Normal file
43
users/auth/backends.py
Normal file
43
users/auth/backends.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import re
|
||||
|
||||
from core.models import Pin
|
||||
from users.models import User
|
||||
|
||||
email_re = re.compile(
|
||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
|
||||
# quoted-string, see also http://tools.ietf.org/html/rfc2822#section-3.2.5
|
||||
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"'
|
||||
r')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)$)'
|
||||
# domain
|
||||
r'|\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$', re.IGNORECASE) # literal form, ipv4 address (SMTP 4.1.3)
|
||||
|
||||
|
||||
class CombinedAuthBackend(object):
|
||||
def authenticate(self, username=None, password=None):
|
||||
is_email = email_re.match(username)
|
||||
if is_email:
|
||||
qs = User.objects.filter(email=username)
|
||||
else:
|
||||
qs = User.objects.filter(username=username)
|
||||
|
||||
try:
|
||||
user = qs.get()
|
||||
except User.DoesNotExist:
|
||||
return None
|
||||
if user.check_password(password):
|
||||
return user
|
||||
return None
|
||||
|
||||
def get_user(self, user_id):
|
||||
try:
|
||||
return User.objects.get(pk=user_id)
|
||||
except User.DoesNotExist:
|
||||
return None
|
||||
|
||||
def has_perm(self, user, perm, obj=None):
|
||||
"""
|
||||
A very simplistic authorization mechanism for now. Basically a pin owner can do anything with the pin.
|
||||
"""
|
||||
if obj and isinstance(obj, Pin):
|
||||
return obj.submitter == user
|
||||
return False
|
||||
38
users/forms.py
Normal file
38
users/forms.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
class UserCreationForm(forms.ModelForm):
|
||||
"""
|
||||
A form that creates a user, with no privileges, from the given username,
|
||||
email, and password.
|
||||
"""
|
||||
error_messages = {
|
||||
'duplicate_username': _("A user with that username already exists."),
|
||||
}
|
||||
username = forms.RegexField(label=_("Username"), max_length=30,
|
||||
regex=r'^[\w-]+$')
|
||||
password = forms.CharField(label=_("Password"),
|
||||
widget=forms.PasswordInput)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ("username", "email")
|
||||
|
||||
def clean_username(self):
|
||||
# Since User.username is unique, this check is redundant,
|
||||
# but it sets a nicer error message than the ORM. See #13147.
|
||||
username = self.cleaned_data["username"]
|
||||
try:
|
||||
User._default_manager.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
return username
|
||||
raise forms.ValidationError(self.error_messages['duplicate_username'])
|
||||
|
||||
def save(self, commit=True):
|
||||
user = super(UserCreationForm, self).save(commit=False)
|
||||
user.set_password(self.cleaned_data["password"])
|
||||
if commit:
|
||||
user.save()
|
||||
return user
|
||||
15
users/middleware.py
Normal file
15
users/middleware.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
|
||||
class Public(object):
|
||||
def process_request(self, request):
|
||||
if settings.PUBLIC == False and not request.user.is_authenticated():
|
||||
acceptable_paths = [
|
||||
'/login/',
|
||||
'/private/',
|
||||
'/register/',
|
||||
]
|
||||
if request.path not in acceptable_paths:
|
||||
return HttpResponseRedirect(reverse('users:private'))
|
||||
27
users/migrations/0001_initial.py
Normal file
27
users/migrations/0001_initial.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.contrib.auth.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0006_require_contenttypes_0002'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('auth.user',),
|
||||
managers=[
|
||||
('objects', django.contrib.auth.models.UserManager()),
|
||||
],
|
||||
),
|
||||
]
|
||||
0
users/migrations/__init__.py
Normal file
0
users/migrations/__init__.py
Normal file
12
users/models.py
Normal file
12
users/models.py
Normal file
@@ -0,0 +1,12 @@
|
||||
import hashlib
|
||||
|
||||
from django.contrib.auth.models import User as BaseUser
|
||||
|
||||
|
||||
class User(BaseUser):
|
||||
@property
|
||||
def gravatar(self):
|
||||
return hashlib.md5(self.email.encode('utf-8')).hexdigest()
|
||||
|
||||
class Meta:
|
||||
proxy = True
|
||||
77
users/tests.py
Normal file
77
users/tests.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
|
||||
import mock
|
||||
|
||||
from .auth.backends import CombinedAuthBackend
|
||||
from ..core.models import Image, Pin
|
||||
from .models import User
|
||||
|
||||
|
||||
def mock_requests_get(url):
|
||||
response = mock.Mock(content=open('logo.png', 'rb').read())
|
||||
return response
|
||||
|
||||
|
||||
class CombinedAuthBackendTest(TestCase):
|
||||
def setUp(self):
|
||||
self.backend = CombinedAuthBackend()
|
||||
self.username = 'jdoe'
|
||||
self.email = 'jdoe@example.com'
|
||||
self.password = 'password'
|
||||
User.objects.create_user(username=self.username, email=self.email, password=self.password)
|
||||
|
||||
def test_authenticate_username(self):
|
||||
self.assertTrue(self.backend.authenticate(username=self.username, password=self.password))
|
||||
|
||||
def test_authenticate_email(self):
|
||||
self.assertTrue(self.backend.authenticate(username=self.email, password=self.password))
|
||||
|
||||
def test_authenticate_wrong_password(self):
|
||||
self.assertIsNone(self.backend.authenticate(username=self.username, password='wrong-password'))
|
||||
|
||||
def test_authenticate_unknown_user(self):
|
||||
self.assertIsNone(self.backend.authenticate(username='wrong-username', password='wrong-password'))
|
||||
|
||||
@mock.patch('requests.get', mock_requests_get)
|
||||
def test_has_perm_on_pin(self):
|
||||
image = Image.objects.create_for_url('http://testserver/mocked/screenshot.png')
|
||||
user = User.objects.get(username=self.username)
|
||||
pin = Pin.objects.create(submitter=user, image=image)
|
||||
self.assertTrue(self.backend.has_perm(user, 'add_pin', pin))
|
||||
|
||||
@mock.patch('requests.get', mock_requests_get)
|
||||
def test_has_perm_on_pin_unauthorized(self):
|
||||
image = Image.objects.create_for_url('http://testserver/mocked/screenshot.png')
|
||||
user = User.objects.get(username=self.username)
|
||||
other_user = User.objects.create_user('test', 'test@example.com', 'test')
|
||||
pin = Pin.objects.create(submitter=user, image=image)
|
||||
self.assertFalse(self.backend.has_perm(other_user, 'add_pin', pin))
|
||||
|
||||
|
||||
class CreateUserTest(TestCase):
|
||||
def test_create_post(self):
|
||||
data = {
|
||||
'username': 'jdoe',
|
||||
'email': 'jdoe@example.com',
|
||||
'password': 'password'
|
||||
}
|
||||
response = self.client.post(reverse('users:register'), data=data)
|
||||
self.assertRedirects(response, reverse('core:recent-pins'))
|
||||
self.assertIn('_auth_user_id', self.client.session)
|
||||
|
||||
@override_settings(ALLOW_NEW_REGISTRATIONS=False)
|
||||
def test_create_post_not_allowed(self):
|
||||
response = self.client.get(reverse('users:register'))
|
||||
self.assertRedirects(response, reverse('core:recent-pins'))
|
||||
|
||||
|
||||
class LogoutViewTest(TestCase):
|
||||
def setUp(self):
|
||||
User.objects.create_user(username='jdoe', password='password')
|
||||
self.client.login(username='jdoe', password='password')
|
||||
|
||||
def test_logout_view(self):
|
||||
response = self.client.get(reverse('users:logout'))
|
||||
self.assertRedirects(response, reverse('core:recent-pins'))
|
||||
11
users/urls.py
Normal file
11
users/urls.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from .views import CreateUser
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^private/$', 'users.views.private', name='private'),
|
||||
url(r'^register/$', CreateUser.as_view(), name='register'),
|
||||
url(r'^login/$', 'django.contrib.auth.views.login',
|
||||
{'template_name': 'users/login.html'}, name='login'),
|
||||
url(r'^logout/$', 'users.views.logout_user', name='logout'),
|
||||
)
|
||||
49
users/views.py
Normal file
49
users/views.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.functional import lazy
|
||||
from django.views.generic import CreateView
|
||||
|
||||
from .forms import UserCreationForm
|
||||
from users.models import User
|
||||
|
||||
|
||||
reverse_lazy = lambda name=None, *args: lazy(reverse, str)(name, args=args)
|
||||
|
||||
|
||||
class CreateUser(CreateView):
|
||||
template_name = 'users/register.html'
|
||||
model = User
|
||||
form_class = UserCreationForm
|
||||
success_url = reverse_lazy('core:recent-pins')
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if not settings.ALLOW_NEW_REGISTRATIONS:
|
||||
messages.error(request, "The admin of this service is not allowing new registrations.")
|
||||
return HttpResponseRedirect(reverse('core:recent-pins'))
|
||||
return super(CreateUser, self).get(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
redirect = super(CreateUser, self).form_valid(form)
|
||||
permissions = Permission.objects.filter(codename__in=['add_pin', 'add_image'])
|
||||
user = authenticate(username=form.cleaned_data['username'],
|
||||
password=form.cleaned_data['password'])
|
||||
user.user_permissions = permissions
|
||||
login(self.request, user)
|
||||
return redirect
|
||||
|
||||
|
||||
@login_required
|
||||
def logout_user(request):
|
||||
logout(request)
|
||||
messages.success(request, 'You have successfully logged out.')
|
||||
return HttpResponseRedirect(reverse('core:recent-pins'))
|
||||
|
||||
|
||||
def private(request):
|
||||
return TemplateResponse(request, 'users/private.html', None)
|
||||
Reference in New Issue
Block a user