Archived
Starts MeResource, groupprofile, misc
This commit is contained in:
1 parent
e9002dc035
commit
945f3ac607
12 files changed
+145
-31
No files matched your search
@@ -26,12 +26,9 @@ class MemberAdmin(admin.ModelAdmin):
|
||||
return self.readonly_fields + ('username', )
|
||||
return self.readonly_fields
|
||||
|
||||
admin.site.unregister(django.contrib.auth.models.Group)
|
||||
|
||||
admin.site.register(Address)
|
||||
admin.site.register(Country)
|
||||
admin.site.register(Division)
|
||||
admin.site.register(Group)
|
||||
admin.site.register(Institution)
|
||||
admin.site.register(Member, MemberAdmin)
|
||||
admin.site.register(MemberMeta)
|
||||
|
||||
@@ -5,7 +5,8 @@ from tastypie.bundle import Bundle
|
||||
from tastypie.exceptions import ImmediateHttpResponse
|
||||
from tastypie.http import HttpNotFound, HttpAccepted, HttpCreated, HttpResponse, HttpBadRequest, HttpNoContent
|
||||
from tastypie.resources import Resource
|
||||
from dusken.models import Member, Group
|
||||
from dusken.models import Member
|
||||
from django.contrib.auth.models import Group
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
from tastypie.resources import ModelResource
|
||||
from tastypie import fields
|
||||
|
||||
from dusken.models import Address
|
||||
from dusken.authorization import MyDjangoAuthorization
|
||||
from dusken.authentication import OAuth20Authentication
|
||||
|
||||
class AddressResource(ModelResource):
|
||||
class Meta:
|
||||
queryset = Address.objects.all()
|
||||
resource_name = 'address'
|
||||
authorization = MyDjangoAuthorization()
|
||||
authentication = OAuth20Authentication()
|
||||
@@ -0,0 +1,13 @@
|
||||
from tastypie.resources import ModelResource
|
||||
from tastypie import fields
|
||||
|
||||
from dusken.models import Division
|
||||
from dusken.authorization import MyDjangoAuthorization
|
||||
from dusken.authentication import OAuth20Authentication
|
||||
|
||||
class DivisionResource(ModelResource):
|
||||
class Meta:
|
||||
queryset = Division.objects.all()
|
||||
resource_name = 'division'
|
||||
authorization = MyDjangoAuthorization()
|
||||
authentication = OAuth20Authentication()
|
||||
+1
-1
@@ -2,7 +2,7 @@ from django.conf.urls import url
|
||||
from tastypie.authorization import Authorization
|
||||
from tastypie.resources import ModelResource, ALL
|
||||
|
||||
from dusken.models import Group
|
||||
from django.contrib.auth.models import Group
|
||||
from dusken.api.membersbygroup import MembersByGroupResource
|
||||
|
||||
class GroupResource(ModelResource):
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from django.shortcuts import get_object_or_404
|
||||
from dusken.api.abstract_groupmember import GroupMemberObject, AbstractGroupMemberResource
|
||||
from dusken.models import Member, Group
|
||||
from dusken.models import Member
|
||||
from django.contrib.auth.models import Group
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
from django.conf.urls import url
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import IntegrityError
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from tastypie.authorization import Authorization
|
||||
from tastypie.exceptions import ImmediateHttpResponse, BadRequest
|
||||
from tastypie.http import HttpForbidden, HttpNoContent, HttpResponse, HttpAccepted
|
||||
from tastypie import fields
|
||||
from tastypie.resources import ModelResource, ALL
|
||||
from tastypie.validation import CleanedDataFormValidation
|
||||
|
||||
from dusken.authentication import ServiceAuthentication, OAuth20Authentication
|
||||
from dusken.authorization import MyDjangoAuthorization
|
||||
from dusken.models import *
|
||||
from dusken.utils.api import generate_username, random_string
|
||||
from dusken.forms import MemberCreateForm
|
||||
|
||||
from dusken.api.division import DivisionResource
|
||||
from dusken.api.membership import MembershipResource
|
||||
from dusken.api.address import AddressResource
|
||||
from dusken.api.groupsbymember import GroupsByMemberResource
|
||||
|
||||
class MeResource(ModelResource):
|
||||
"""
|
||||
This class provides following endpoints:
|
||||
(1) /api/v1/me/
|
||||
"""
|
||||
groups = fields.ToManyField(GroupsByMemberResource, 'groups')
|
||||
divisions = fields.ToManyField(DivisionResource, 'division_set')
|
||||
memberships = fields.ToManyField(MembershipResource, 'membership_set')
|
||||
#address = fields.ForeignKey(AddressResource, 'address')
|
||||
|
||||
class Meta:
|
||||
queryset = Member.objects.all()
|
||||
resource_name = 'me'
|
||||
list_allowed_methods = [ 'get' ]
|
||||
detail_allowed_methods = [ 'get']
|
||||
authentication = OAuth20Authentication() # Who are you?
|
||||
authorization = MyDjangoAuthorization() # What are you allowed to do?
|
||||
excludes = [ 'date_joined', 'password', 'is_active', 'is_staff', 'is_superuser', 'last_login' ]
|
||||
|
||||
def get_object_list(self, request):
|
||||
# Only return the authenticated user's member object
|
||||
return super(MeResource, self).get_object_list(request).filter(pk=request.user.id)
|
||||
|
||||
def detail_groups(self, request, **kwargs):
|
||||
resource = GroupsByMemberResource()
|
||||
return resource.dispatch_detail(request, **kwargs)
|
||||
|
||||
def dehydrate(self, bundle):
|
||||
"""
|
||||
Catches GET requests and adds more data.
|
||||
"""
|
||||
bundle.data['has_valid_membership'] = bundle.obj.has_valid_membership()
|
||||
# Add address:
|
||||
#address = bundle.obj.address
|
||||
#if address is None:
|
||||
# bundle.data['address'] = None
|
||||
#else:
|
||||
# # TODO: There has to be a better way...
|
||||
# bundle.data['address'] = {
|
||||
# 'city' : address.city,
|
||||
# 'country' : address.country.name,
|
||||
# 'postal_code' : address.postal_code,
|
||||
# 'street_address' : address.street_address,
|
||||
# }
|
||||
|
||||
return bundle
|
||||
@@ -1,6 +1,7 @@
|
||||
from django.shortcuts import get_object_or_404
|
||||
from dusken.api.abstract_groupmember import GroupMemberObject, AbstractGroupMemberResource
|
||||
from dusken.models import Member, Group
|
||||
from dusken.models import Member
|
||||
from django.contrib.auth.models import Group
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ from tastypie.authentication import Authentication
|
||||
from tastypie.authorization import DjangoAuthorization
|
||||
from tastypie.exceptions import Unauthorized
|
||||
|
||||
# TODO add django-guardian for object level/row level permissions.
|
||||
# TODO add django-guardian for object level/row level permissions (apply_limit).
|
||||
# Ref: https://gist.github.com/7wonders/6557760
|
||||
# Usage example: User in group x is admin of group y
|
||||
# Literal usage example: Runar in group KAK-styret is admin of group KAK.
|
||||
@@ -74,3 +74,8 @@ class MyDjangoAuthorization(DjangoAuthorization):
|
||||
raise Unauthorized("You are not allowed to access that resource.")
|
||||
|
||||
return True
|
||||
|
||||
#def apply_limit(self):
|
||||
# pass
|
||||
# TODO limit objects which a user are allowed to do crud operations on with django-guardian.
|
||||
# apply_limit is called by apply_authorization_limits
|
||||
@@ -8,11 +8,12 @@
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "dusken.group",
|
||||
"model": "dusken.groupprofile",
|
||||
"fields": {
|
||||
"updated": "2013-09-18T18:31:27.377Z",
|
||||
"created": "2013-09-18T18:14:49.159Z",
|
||||
"posix_name": "EDB"
|
||||
"posix_name": "EDB",
|
||||
"group": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -24,11 +25,12 @@
|
||||
},
|
||||
{
|
||||
"pk": 2,
|
||||
"model": "dusken.group",
|
||||
"model": "dusken.groupprofile",
|
||||
"fields": {
|
||||
"updated": "2013-09-18T18:32:02.861Z",
|
||||
"created": "2013-09-18T18:32:02.861Z",
|
||||
"posix_name": "KAK"
|
||||
"posix_name": "KAK",
|
||||
"group": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
+28
-19
@@ -1,8 +1,10 @@
|
||||
import django
|
||||
import datetime
|
||||
|
||||
from django.db import models
|
||||
from tastypie.models import create_api_key
|
||||
|
||||
class BaseModel(models.Model):
|
||||
class AbstractBaseModel(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
|
||||
@@ -28,9 +30,14 @@ class Member(django.contrib.auth.models.AbstractUser):
|
||||
|
||||
def owner(self):
|
||||
return self
|
||||
|
||||
def has_valid_membership(self):
|
||||
# FIXME more than one membership?
|
||||
# FIXME membership_type?
|
||||
membership = self.membership_set.filter(end_date__gt=datetime.datetime.now())
|
||||
return len(membership) == 1 and membership.is_valid()
|
||||
|
||||
|
||||
class Membership(BaseModel):
|
||||
class Membership(AbstractBaseModel):
|
||||
def __unicode__(self):
|
||||
return u"{0}: {1} - {2}".format(
|
||||
self.member,
|
||||
@@ -46,10 +53,13 @@ class Membership(BaseModel):
|
||||
def expires(self):
|
||||
return self.end_date
|
||||
|
||||
def is_valid(self):
|
||||
return self.payment is not None
|
||||
|
||||
def owner(self):
|
||||
return self.member
|
||||
|
||||
class MembershipType(BaseModel):
|
||||
class MembershipType(AbstractBaseModel):
|
||||
def __unicode__(self):
|
||||
return u"{}".format(self.name)
|
||||
|
||||
@@ -57,7 +67,7 @@ class MembershipType(BaseModel):
|
||||
is_active = models.BooleanField(default=True)
|
||||
does_not_expire = models.BooleanField(default=False)
|
||||
|
||||
class PaymentType(models.Model):
|
||||
class PaymentType(AbstractBaseModel):
|
||||
def __unicode__(self):
|
||||
return u"{}".format(self.name)
|
||||
|
||||
@@ -65,7 +75,7 @@ class PaymentType(models.Model):
|
||||
is_active = models.BooleanField(default=True)
|
||||
|
||||
|
||||
class Payment(BaseModel):
|
||||
class Payment(AbstractBaseModel):
|
||||
def __unicode__(self):
|
||||
return self.payment_type #TODO
|
||||
|
||||
@@ -74,7 +84,7 @@ class Payment(BaseModel):
|
||||
value = models.IntegerField()
|
||||
transaction_id = models.IntegerField(unique=True, null=True, blank=True)
|
||||
|
||||
class Address(BaseModel):
|
||||
class Address(AbstractBaseModel):
|
||||
class Meta:
|
||||
verbose_name_plural = "Addresses"
|
||||
|
||||
@@ -86,13 +96,13 @@ class Address(BaseModel):
|
||||
country=self.country)
|
||||
|
||||
street_address = models.CharField(max_length=255)
|
||||
street_address_two = models.CharField(max_length=255)
|
||||
street_address_two = models.CharField(max_length=255, null=True, blank=True)
|
||||
postal_code = models.CharField(max_length=10)
|
||||
city = models.CharField(max_length=100)
|
||||
country = models.ForeignKey('dusken.Country', null=True, blank=True)
|
||||
|
||||
|
||||
class Country(BaseModel):
|
||||
class Country(AbstractBaseModel):
|
||||
class Meta:
|
||||
verbose_name_plural = "Countries"
|
||||
|
||||
@@ -103,7 +113,7 @@ class Country(BaseModel):
|
||||
code = models.CharField(max_length=3, unique=True) #ISO 3166-1 alpha 2
|
||||
|
||||
|
||||
class PlaceOfStudy(BaseModel):
|
||||
class PlaceOfStudy(AbstractBaseModel):
|
||||
def __unicode__(self):
|
||||
return u"{institution}, {year}".format(
|
||||
institution=self.institution,
|
||||
@@ -113,30 +123,29 @@ class PlaceOfStudy(BaseModel):
|
||||
institution = models.ForeignKey('dusken.Institution')
|
||||
|
||||
|
||||
class Institution(BaseModel):
|
||||
class Institution(AbstractBaseModel):
|
||||
def __unicode__(self):
|
||||
return u'%s - %s' % (self.short_name, self.name)
|
||||
|
||||
name = models.CharField(max_length=255)
|
||||
short_name = models.CharField(max_length=16)
|
||||
|
||||
class MemberMeta(BaseModel):
|
||||
class MemberMeta(AbstractBaseModel):
|
||||
key = models.CharField(max_length=255)
|
||||
value = models.TextField(blank=True)
|
||||
member = models.ForeignKey('dusken.Member')
|
||||
|
||||
class Group(django.contrib.auth.models.Group):
|
||||
class GroupProfile(AbstractBaseModel):
|
||||
"""
|
||||
django.contrib.auth.model.Group extended with additional fields.
|
||||
"""
|
||||
def __unicode__(self):
|
||||
return u"{} ({})".format(self.name, self.posix_name)
|
||||
return u"{}".format(self.posix_name)
|
||||
|
||||
posix_name = models.CharField(max_length=255, unique=True)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
group = models.OneToOneField(django.contrib.auth.models.Group)
|
||||
|
||||
class Division(BaseModel):
|
||||
class Division(AbstractBaseModel):
|
||||
"""
|
||||
Associations, comittee or similar
|
||||
"""
|
||||
@@ -147,9 +156,9 @@ class Division(BaseModel):
|
||||
is_active = models.BooleanField(default=True)
|
||||
members = models.ManyToManyField('dusken.Member', null=True, blank=True)
|
||||
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
|
||||
groups = models.ManyToManyField('dusken.Group', null=True, blank=True) # permissions
|
||||
groups = models.ManyToManyField(django.contrib.auth.models.Group, null=True, blank=True) # permissions
|
||||
|
||||
class ServiceHook(BaseModel):
|
||||
class ServiceHook(AbstractBaseModel):
|
||||
"""
|
||||
Events with callback_urls
|
||||
"""
|
||||
|
||||
@@ -2,6 +2,7 @@ from django.conf.urls import patterns, include, url
|
||||
from django.contrib import admin
|
||||
from tastypie.api import Api
|
||||
|
||||
from dusken.api.me import MeResource
|
||||
from dusken.api.member import MemberResource, MemberCreateResource
|
||||
from dusken.api.membership import MembershipResource
|
||||
from dusken.api.group import GroupResource
|
||||
@@ -10,6 +11,7 @@ from dusken.api.institution import InstitutionResource
|
||||
admin.autodiscover()
|
||||
|
||||
v1_api = Api(api_name='v1')
|
||||
v1_api.register(MeResource())
|
||||
v1_api.register(MemberResource())
|
||||
v1_api.register(MembershipResource())
|
||||
v1_api.register(GroupResource())
|
||||
|
||||
Reference in new issue
Block a user