Skip to content

Commit

Permalink
Merge pull request #6 from 42cc/t33_supporter_roles
Browse files Browse the repository at this point in the history
T33 supporter roles
  • Loading branch information
alekzvik committed Feb 6, 2014
2 parents 2875205 + d4a9d38 commit 1d0fb08
Show file tree
Hide file tree
Showing 19 changed files with 343 additions and 52 deletions.
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
-include Makefile.def

TEST_APP?=events

# targets
.PHONY: manage run mailserver syncdb shell test clean migrate init_migrate loaddata help

Expand Down Expand Up @@ -34,7 +32,10 @@ shell:
$(MANAGE) shell

test:
TESTING=1 $(MANAGE) test $(TEST_OPTIONS) $(TEST_APP)
TESTING=1 $(MANAGE) test $(TEST_OPTIONS)

testone:
$(TEST) $(MANAGE) test $(filter-out $@,$(MAKECMDGOALS))

clean:
@echo Cleaning up...
Expand Down
4 changes: 0 additions & 4 deletions Makefile.def.buildbot
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,4 @@ BIND_TO?=0.0.0.0
BIND_PORT?=8000
MAILSERVER_PORT?=1025
DJANGO_SETTINGS=p2psafety.settings


TEST_APP?=events

MANAGE= DJANGO_SETTINGS_MODULE=$(DJANGO_SETTINGS) python p2psafety_django/manage.py
4 changes: 0 additions & 4 deletions Makefile.def.default
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,4 @@ BIND_TO?=0.0.0.0
BIND_PORT?=8000
MAILSERVER_PORT?=1025
DJANGO_SETTINGS=p2psafety.settings


TEST_APP?=events

MANAGE= DJANGO_SETTINGS_MODULE=$(DJANGO_SETTINGS) python p2psafety_django/manage.py
7 changes: 0 additions & 7 deletions p2psafety_django/events/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
from tastypie.api import Api

from .resources import EventResource, EventUpdateResource


api_v1 = Api(api_name='v1')
api_v1.register(EventResource())
api_v1.register(EventUpdateResource())
15 changes: 1 addition & 14 deletions p2psafety_django/events/api/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import logging

from django.conf import settings
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404

from tastypie import http, fields
Expand All @@ -18,6 +17,7 @@
from .authentication import PostFreeSessionAuthentication
from .authorization import CreateFreeDjangoAuthorization
from ..models import Event, EventUpdate
from users.api.resources import UserResource


logger = logging.getLogger(__name__)
Expand All @@ -41,19 +41,6 @@ def deserialize(self, request, data, format=None):
return super(MultipartResource, self).deserialize(request, data, format)


class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'users'
fields = ['id']

full_name = fields.CharField('get_full_name')

def dehydrate_full_name(self, bundle):
value = bundle.data['full_name']
return value if value else bundle.obj.username


class EventValidation(Validation):
def is_valid(self, bundle, request=None):
if not bundle.data:
Expand Down
22 changes: 3 additions & 19 deletions p2psafety_django/events/tests/helpers/factories.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,8 @@
from factory import SubFactory, Sequence
from factory import SubFactory
from factory.django import DjangoModelFactory, FileField

from django.contrib.auth.models import User

from events.models import Event, EventUpdate


class UserFactory(DjangoModelFactory):
FACTORY_FOR = User
FACTORY_DJANGO_GET_OR_CREATE = ('username',)

username = Sequence(lambda n: 'user%d' % n)
password = Sequence(lambda n: 'user%d' % n)

@classmethod
def _create(cls, target_class, *args, **kwargs):
manager = cls._get_manager(target_class)
user = manager.create_user(*args, **kwargs)
user.real_password = kwargs.get('password')
return user
from users.tests.helpers import UserFactory


class EventFactory(DjangoModelFactory):
Expand All @@ -31,4 +15,4 @@ class EventUpdateFactory(DjangoModelFactory):
FACTORY_FOR = EventUpdate

audio = FileField()
video = FileField()
video = FileField()
1 change: 1 addition & 0 deletions p2psafety_django/p2psafety/settings/django.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
'django.contrib.gis',

'events',
'users',

'tastypie',
'social.apps.django_app.default',
Expand Down
12 changes: 11 additions & 1 deletion p2psafety_django/p2psafety/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns

from events.api import api_v1
from tastypie.api import Api

from events.api import EventResource, EventUpdateResource
from users.api import UserResource, RoleResource


admin.autodiscover()


api_v1 = Api(api_name='v1')
api_v1.register(EventResource())
api_v1.register(EventUpdateResource())
api_v1.register(UserResource())
api_v1.register(RoleResource())


urlpatterns = patterns('',
url(r'^$', 'p2psafety.views.index', name='index'),
url(r'^', include('events.urls', namespace='events')),
Expand Down
Empty file.
Empty file added p2psafety_django/users/admin.py
Empty file.
1 change: 1 addition & 0 deletions p2psafety_django/users/api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .resources import *
78 changes: 78 additions & 0 deletions p2psafety_django/users/api/resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from django import http as django_http
from django.conf.urls import url
from django.contrib.auth.models import User
from django.core.paginator import Paginator
from django.shortcuts import get_object_or_404

from tastypie import exceptions, fields, http
from tastypie.authorization import Authorization
from tastypie.resources import ModelResource
from tastypie.utils import trailing_slash

from ..models import Role


class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'users'
fields = ['id']
detail_allowed_methods = []
list_allowed_methods = []

full_name = fields.CharField('get_full_name')

def dehydrate_full_name(self, bundle):
value = bundle.data['full_name']
return value if value else bundle.obj.username

def prepend_urls(self):
return [
url(r'^(?P<resource_name>%s)/(?P<pk>\d+)/roles%s$' %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('roles'), name='api_users_roles'),
]

def roles(self, request, pk=None, **kwargs):
"""
For GET method, returns user's roles as list of ids.
For POST method, sets user's roles to given list of ids as
``role_id`` POST param.
Raises 403 if ``role_id`` is not found within POST params dict or it is
not a list of valid ids.
Raises 404 if user is not found.
"""
self.method_check(request, allowed=['get', 'post'])
self.throttle_check(request)

try:
user = get_object_or_404(User, pk=pk)
except django_http.Http404:
return http.HttpNotFound()
else:
self.log_throttled_access(request)
if request.method == 'POST':
if 'role_id' not in request.POST:
return http.HttpBadRequest()

try:
role_ids = map(int, request.POST.getlist('role_id'))
except ValueError:
return http.HttpBadRequest()

roles = Role.objects.filter(id__in=role_ids)
user.roles.clear()
user.roles.add(*roles)
return http.HttpAccepted()
else:
objects = [role.id for role in user.roles.all()]
return self.create_response(request, objects)


class RoleResource(ModelResource):
class Meta:
queryset = Role.objects.all()
resource_name = 'roles'
detail_allowed_methods = []
include_resource_uri = False
81 changes: 81 additions & 0 deletions p2psafety_django/users/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'Role'
db.create_table(u'users_role', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=30)),
))
db.send_create_signal(u'users', ['Role'])

# Adding M2M table for field users on 'Role'
m2m_table_name = db.shorten_name(u'users_role_users')
db.create_table(m2m_table_name, (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('role', models.ForeignKey(orm[u'users.role'], null=False)),
('user', models.ForeignKey(orm[u'auth.user'], null=False))
))
db.create_unique(m2m_table_name, ['role_id', 'user_id'])


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

# Removing M2M table for field users on 'Role'
db.delete_table(db.shorten_name(u'users_role_users'))


models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'users.role': {
'Meta': {'object_name': 'Role'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'roles'", 'symmetrical': 'False', 'to': u"orm['auth.User']"})
}
}

complete_apps = ['users']
Empty file.
15 changes: 15 additions & 0 deletions p2psafety_django/users/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import ugettext_lazy as _


class Role(models.Model):
class Meta:
verbose_name = _('Role')
verbose_name_plural = _('Roles')

name = models.CharField(_('name'), max_length=30, unique=True)
users = models.ManyToManyField(User, related_name='roles')

def __unicode__(self):
return unicode(self.name)
Empty file.
52 changes: 52 additions & 0 deletions p2psafety_django/users/tests/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User

from factory import Sequence
from factory.django import DjangoModelFactory

from ..models import Role


class UserFactory(DjangoModelFactory):
FACTORY_FOR = User
FACTORY_DJANGO_GET_OR_CREATE = ('username',)

username = Sequence(lambda n: 'user%d' % n)
password = Sequence(lambda n: 'user%d' % n)

@classmethod
def _create(cls, target_class, *args, **kwargs):
manager = cls._get_manager(target_class)
user = manager.create_user(*args, **kwargs)
user.real_password = kwargs.get('password')
return user


class RoleFactory(DjangoModelFactory):
FACTORY_FOR = Role

name = Sequence(lambda n: 'role%d' % n)


class ModelsMixin(object):
@property
def roles_list_url(self):
return reverse('api_dispatch_list', kwargs=dict(resource_name='roles',
api_name='v1'))

def roles_detail_url(self, role_id):
kwargs = dict(resource_name='roles', api_name='v1', pk=role_id)
return reverse('api_dispatch_detail', kwargs=kwargs)

@property
def users_list_url(self):
kwargs = dict(resource_name='users', api_name='v1')
return reverse('api_dispatch_list', kwargs=kwargs)

def users_detail_url(self, user_id):
kwargs = dict(resource_name='users', api_name='v1', pk=user_id)
return reverse('api_dispatch_detail', kwargs=kwargs)

def users_roles_url(self, user_id):
kwargs = dict(resource_name='users', api_name='v1', pk=user_id)
return reverse('api_users_roles', kwargs=kwargs)
Loading

0 comments on commit 1d0fb08

Please sign in to comment.