Skip to content

Commit

Permalink
Merge pull request #29 from rdmorganiser/api
Browse files Browse the repository at this point in the history
Api
  • Loading branch information
jochenklar authored Apr 26, 2017
2 parents 536f003 + 7cafe9a commit 77a9b2a
Show file tree
Hide file tree
Showing 93 changed files with 3,247 additions and 2,143 deletions.
31 changes: 31 additions & 0 deletions apps/accounts/migrations/0009_proxyuser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.6 on 2017-04-21 13:56
from __future__ import unicode_literals

import django.contrib.auth.models
from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('auth', '0008_alter_user_username_max_length'),
('accounts', '0008_related_name'),
]

operations = [
migrations.CreateModel(
name='ProxyUser',
fields=[
],
options={
'default_permissions': (),
'proxy': True,
'permissions': (('view_user', 'Can view user'),),
},
bases=('auth.user',),
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]
8 changes: 8 additions & 0 deletions apps/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
from apps.core.models import TranslationMixin


class ProxyUser(User):

class Meta:
proxy = True
default_permissions = ()
permissions = (('view_user', 'Can view user'),)


@python_2_unicode_compatible
class AdditionalField(models.Model, TranslationMixin):

Expand Down
Empty file.
16 changes: 16 additions & 0 deletions apps/accounts/serializers/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django.contrib.auth.models import User

from rest_framework import serializers


class UserSerializer(serializers.ModelSerializer):

class Meta:
model = User
fields = (
'id',
'username',
'first_name',
'last_name',
'email'
)
103 changes: 103 additions & 0 deletions apps/accounts/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
GROUPS = (
('editor', (
'add_attributeentity',
'change_attributeentity',
'delete_attributeentity',
'view_attributeentity',
'add_range',
'change_range',
'delete_range',
'view_range',
'add_verbosename',
'change_verbosename',
'delete_verbosename',
'view_verbosename',
'add_attribute',
'change_attribute',
'delete_attribute',
'view_attribute',
'add_option',
'change_option',
'delete_option',
'view_option',
'add_optionset',
'change_optionset',
'delete_optionset',
'view_optionset',
'add_condition',
'change_condition',
'delete_condition',
'view_condition',
'add_section',
'change_section',
'delete_section',
'view_section',
'add_catalog',
'change_catalog',
'delete_catalog',
'view_catalog',
'add_questionentity',
'change_questionentity',
'delete_questionentity',
'view_questionentity',
'add_subsection',
'change_subsection',
'delete_subsection',
'view_subsection',
'add_question',
'change_question',
'delete_question',
'view_question',
'add_task',
'change_task',
'delete_task',
'view_task',
'add_timeframe',
'change_timeframe',
'delete_timeframe',
'view_timeframe',
'add_view',
'change_view',
'delete_view',
'view_view',
)),
('reviewer', (
'view_attributeentity',
'view_range',
'view_verbosename',
'view_attribute',
'view_option',
'view_optionset',
'view_condition',
'view_section',
'view_catalog',
'view_questionentity',
'view_subsection',
'view_question',
'view_task',
'view_timeframe',
'view_view',
)),
('api', (
'view_user',
'view_attributeentity',
'view_range',
'view_verbosename',
'view_attribute',
'view_option',
'view_optionset',
'view_membership',
'view_project',
'view_snapshot',
'view_value',
'view_condition',
'view_section',
'view_catalog',
'view_questionentity',
'view_subsection',
'view_question',
'view_task',
'view_timeframe',
'view_view',
))
)
30 changes: 29 additions & 1 deletion apps/accounts/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
from django.core.urlresolvers import reverse
from django.core import mail

from apps.core.testing.mixins import TestModelStringMixin
from apps.accounts.utils import set_group_permissions
from apps.core.testing.mixins import (
TestModelStringMixin,
TestListAPIViewMixin,
TestRetrieveAPIViewMixin
)


class AccountsTestCase(TestCase):
Expand All @@ -20,6 +25,22 @@ class AccountsTestCase(TestCase):
'accounts.json'
)

users = (
('editor', 'editor'),
('reviewer', 'reviewer'),
('user', 'user'),
('api', 'api'),
('anonymous', None),
)

api_status_map = {
'list': {'editor': 403, 'reviewer': 403, 'api': 200, 'user': 403, 'anonymous': 403},
'retrieve': {'editor': 403, 'reviewer': 403, 'api': 200, 'user': 403, 'anonymous': 403},
}

def setUp(self):
set_group_permissions()


class ProfileTests(TestModelStringMixin, AccountsTestCase):

Expand Down Expand Up @@ -228,3 +249,10 @@ def test_password_reset_post_valid(self):
# get the password_reset page
response = self.client.get(urls[0])
self.assertEqual(response.status_code, 200)


class UserAPITests(TestListAPIViewMixin, TestRetrieveAPIViewMixin, AccountsTestCase):

instances = User.objects.all()

api_url_name = 'api-v1-accounts:user'
20 changes: 17 additions & 3 deletions apps/accounts/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,34 @@
from django.conf.urls import url, include
from django.contrib.auth import views as auth_views

from rest_framework import routers

from .views import profile_update
from .viewsets import UserApiViewSet

# regular views

urlpatterns = [
accounts_patterns = [
# edit own profile
url(r'^$', profile_update, name='profile_update'),
]

if settings.ACCOUNT or settings.SOCIALACCOUNT:
# include django-allauth urls
urlpatterns += [
accounts_patterns += [
url(r'^', include('allauth.urls')),
]
else:
urlpatterns += [
accounts_patterns += [
url('^login/', auth_views.login, {'template_name': 'account/login.html'}, name='account_login'),
url('^logout/', auth_views.logout, {'next_page': settings.LOGIN_REDIRECT_URL}, name='account_logout'),
]

# programmable API

api_router = routers.DefaultRouter()
api_router.register(r'users', UserApiViewSet, base_name='user')

accounts_patterns_api = [
url(r'^', include(api_router.urls)),
]
12 changes: 12 additions & 0 deletions apps/accounts/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
from django.contrib.auth.models import Group, Permission

from .settings import GROUPS


def get_full_name(user):
if user.first_name and user.last_name:
return '%s %s' % (user.first_name, user.last_name)
else:
return user.username


def set_group_permissions():
for name, permissions in GROUPS:
group = Group.objects.get(name=name)
for codename in permissions:
group.permissions.add(Permission.objects.get(codename=codename))
25 changes: 25 additions & 0 deletions apps/accounts/viewsets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from django.contrib.auth.models import User

from rest_framework.viewsets import ReadOnlyModelViewSet
from rest_framework.filters import DjangoFilterBackend
from rest_framework.authentication import SessionAuthentication, TokenAuthentication

from apps.core.permissions import HasModelPermission

from .serializers.api import (
UserSerializer as UserApiSerializer,
)


class UserApiViewSet(ReadOnlyModelViewSet):
permission_classes = (HasModelPermission, )
authentication_classes = (SessionAuthentication, TokenAuthentication)
queryset = User.objects.all()
serializer_class = UserApiSerializer

filter_backends = (DjangoFilterBackend,)
filter_fields = (
'username',
'email',
'project'
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from apps.domain.models import Attribute
from apps.options.models import OptionSet, Option

from .models import Condition
from .validators import ConditionUniqueKeyValidator
from ..models import Condition
from ..validators import ConditionUniqueKeyValidator


class ConditionIndexSerializer(serializers.ModelSerializer):
Expand Down
23 changes: 23 additions & 0 deletions apps/conditions/serializers/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from rest_framework import serializers

from ..models import Condition


class ConditionSerializer(serializers.ModelSerializer):

source = serializers.HyperlinkedRelatedField(view_name='api-v1-domain:attribute-detail', read_only=True)
target_option = serializers.HyperlinkedRelatedField(view_name='api-v1-options:option-detail', read_only=True)

class Meta:
model = Condition
fields = (
'id',
'uri',
'uri_prefix',
'key',
'comment',
'source',
'relation',
'target_text',
'target_option'
)
20 changes: 20 additions & 0 deletions apps/conditions/serializers/export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from rest_framework import serializers

from ..models import Condition


class ConditionSerializer(serializers.ModelSerializer):

source = serializers.CharField(source='source.uri')
target_option = serializers.CharField(source='target_option.uri')

class Meta:
model = Condition
fields = (
'uri',
'comment',
'source',
'relation',
'target_text',
'target_option'
)
8 changes: 4 additions & 4 deletions apps/conditions/static/conditions/js/conditions.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ angular.module('conditions', ['core'])
/* configure resources */

var resources = {
conditions: $resource(baseurl + 'api/conditions/conditions/:list_route/:id/'),
attributes: $resource(baseurl + 'api/conditions/attributes/:id/'),
optionsets: $resource(baseurl + 'api/conditions/optionsets/:id/'),
relations: $resource(baseurl + 'api/conditions/relations/:id/')
conditions: $resource(baseurl + 'api/internal/conditions/conditions/:list_route/:id/'),
attributes: $resource(baseurl + 'api/internal/conditions/attributes/:id/'),
optionsets: $resource(baseurl + 'api/internal/conditions/optionsets/:id/'),
relations: $resource(baseurl + 'api/internal/conditions/relations/:id/')
};

/* configure factories */
Expand Down
Loading

0 comments on commit 77a9b2a

Please sign in to comment.