-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from 42cc/t33_supporter_roles
T33 supporter roles
- Loading branch information
Showing
19 changed files
with
343 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,6 +69,7 @@ | |
'django.contrib.gis', | ||
|
||
'events', | ||
'users', | ||
|
||
'tastypie', | ||
'social.apps.django_app.default', | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .resources import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Oops, something went wrong.