Fixes on REST API

This commit is contained in:
Marc 2014-09-30 16:39:47 +00:00
parent 774422a41b
commit f984d28709
12 changed files with 37 additions and 35 deletions

View File

@ -131,7 +131,9 @@ Remember that, as always with QuerySets, any subsequent chained methods which im
* AccountAdminMixin auto adds 'account__name' on searchfields and handle account_link on fieldsets
* Separate panel from server passwords? Store passwords on panel?
* Separate panel from server passwords? Store passwords on panel? set_password special backend operation?
* be more explicit about which backends are resources and which are service handling
* What fields we really need on contacts? name email phone and what more?

View File

@ -22,18 +22,17 @@ class APIRoot(views.APIView):
singleton_pk = getattr(viewset, 'singleton_pk', False)
if singleton_pk:
url_name = detail_name.format(basename=basename)
kwargs = { 'pk': singleton_pk(viewset(), request) }
kwargs = {
'pk': singleton_pk(viewset(), request)
}
else:
url_name = list_name.format(basename=basename)
kwargs = {}
url = reverse(url_name, request=request, format=format, kwargs=kwargs)
links.append('<%s>; rel="%s"' % (url, url_name))
# Add user link
url_name = detail_name.format(basename='user')
kwargs = { 'pk': request.user.pk }
url = reverse(url_name, request=request, format=format, kwargs=kwargs)
links.append('<%s>; rel="%s"' % (url, url_name))
headers = { 'Link': ', '.join(links) }
headers = {
'Link': ', '.join(links)
}
body = {
name.lower(): getattr(settings, name, None) for name in self.names
}

View File

@ -19,7 +19,7 @@ class AccountViewSet(viewsets.ModelViewSet):
def get_queryset(self):
qs = super(AccountViewSet, self).get_queryset()
return qs.filter(id=self.request.user)
return qs.filter(id=self.request.user.pk)
router.register(r'accounts', AccountViewSet)

View File

@ -62,8 +62,8 @@ class Account(auth.AbstractBaseUser):
def save(self, *args, **kwargs):
created = not self.pk
super(Account, self).save(*args, **kwargs)
if created and hasattr(self, 'groups'):
self.groups.create(name=self.username, account=self)
if created and hasattr(self, 'systemgroups'):
self.systemgroups.create(name=self.username, account=self)
def send_email(self, template, context, contacts=[], attachments=[], html=None):
contacts = self.contacts.filter(email_usages=contacts)

View File

@ -7,7 +7,7 @@ class AccountSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Account
fields = (
'url', 'username', 'type', 'language', 'register_date', 'is_active'
'url', 'username', 'type', 'language', 'date_joined', 'is_active'
)

View File

@ -17,6 +17,6 @@ class BillSerializer(AccountSerializerMixin, serializers.HyperlinkedModelSeriali
class Meta:
model = Bill
fields = (
'url', 'number', 'bill_type', 'status', 'created_on', 'due_on',
'url', 'number', 'type', 'total', 'is_sent', 'created_on', 'due_on',
'comments', 'html', 'lines'
)

View File

@ -29,7 +29,7 @@ class TicketViewSet(viewsets.ModelViewSet):
qs = super(TicketViewSet, self).get_queryset()
qs = qs.select_related('creator', 'queue')
qs = qs.prefetch_related('messages__author')
return qs.filter(creator__account=self.request.user.account_id)
return qs.filter(creator=self.request.user)
class QueueViewSet(mixins.ListModelMixin,

View File

@ -18,10 +18,10 @@ class AddressSerializer(AccountSerializerMixin, serializers.HyperlinkedModelSeri
def get_fields(self, *args, **kwargs):
fields = super(AddressSerializer, self).get_fields(*args, **kwargs)
account = self.context['view'].request.user.account_id
account = self.context['view'].request.user.pk
mailboxes = fields['mailboxes'].queryset
fields['mailboxes'].queryset = mailboxes.filter(account=account)
# TODO do it on permissions or in self.filter_by_account_field ?
domain = fields['domain'].queryset
fields['domain'].queryset = domain .filter(account=account)
fields['domain'].queryset = domain.filter(account=account)
return fields

View File

@ -6,13 +6,13 @@ from django.utils.translation import ugettext, ugettext_lazy as _
from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.utils import wrap_admin_view
from orchestra.apps.accounts.admin import AccountAdminMixin
from orchestra.apps.accounts.admin import SelectAccountAdminMixin
from .forms import UserCreationForm, UserChangeForm
from .models import SystemUser
class SystemUserAdmin(AccountAdminMixin, ExtendedModelAdmin):
class SystemUserAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
list_display = ('username', 'account_link', 'shell', 'home', 'is_active',)
list_filter = ('is_active', 'shell')
fieldsets = (
@ -32,7 +32,7 @@ class SystemUserAdmin(AccountAdminMixin, ExtendedModelAdmin):
}),
)
search_fields = ['username']
readonly_fields = ('is_main', 'account_link',)
readonly_fields = ('account_link',)
change_readonly_fields = ('username',)
filter_horizontal = ('groups',)
filter_by_account_fields = ('groups',)

View File

@ -1,15 +1,15 @@
from django.contrib.auth import get_user_model
from rest_framework import viewsets
from orchestra.api import router, SetPasswordApiMixin
from orchestra.apps.accounts.api import AccountApiMixin
from .serializers import UserSerializer
from .models import SystemUser
from .serializers import SystemUserSerializer
class UserViewSet(AccountApiMixin, SetPasswordApiMixin, viewsets.ModelViewSet):
model = get_user_model()
serializer_class = UserSerializer
class SystemUserViewSet(AccountApiMixin, SetPasswordApiMixin, viewsets.ModelViewSet):
model = SystemUser
serializer_class = SystemUserSerializer
router.register(r'users', UserViewSet)
router.register(r'systemusers', SystemUserViewSet)

View File

@ -29,10 +29,9 @@ class SystemUser(models.Model):
help_text=_("Home directory relative to account's ~main_user"))
shell = models.CharField(_("shell"), max_length=32,
choices=settings.USERS_SHELLS, default=settings.USERS_DEFAULT_SHELL)
groups = models.ManyToManyField('systemusers.Group', blank=True,
groups = models.ManyToManyField('systemusers.SystemGroup', blank=True,
help_text=_("A new group will be created for the user. "
"Which additional groups would you like them to be a member of?"))
is_main = models.BooleanField(_("is main"), default=False)
is_active = models.BooleanField(_("active"), default=True,
help_text=_("Designates whether this account should be treated as active. "
"Unselect this instead of deleting accounts."))
@ -54,7 +53,7 @@ class SystemUser(models.Model):
created = not self.pk
super(SystemUser, self).save(*args, **kwargs)
if created:
self.groups.get_or_create(name=self.username, account=self.account)
self.groups.create(name=self.username, account=self.account)
def set_password(self, raw_password):
self.password = make_password(raw_password)
@ -63,13 +62,13 @@ class SystemUser(models.Model):
return self.account.is_active and self.is_active
class Group(models.Model):
class SystemGroup(models.Model):
name = models.CharField(_("name"), max_length=64, unique=True,
help_text=_("Required. 30 characters or fewer. Letters, digits and ./-/_ only."),
validators=[validators.RegexValidator(r'^[\w.-]+$',
_("Enter a valid group name."), 'invalid')])
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
related_name='groups')
related_name='systemgroups')
def __unicode__(self):
return self.name

View File

@ -6,17 +6,19 @@ from rest_framework import serializers
from orchestra.apps.accounts.serializers import AccountSerializerMixin
from orchestra.core.validators import validate_password
from .models import SystemUser
class UserSerializer(AccountSerializerMixin, serializers.HyperlinkedModelSerializer):
class SystemUserSerializer(AccountSerializerMixin, serializers.HyperlinkedModelSerializer):
password = serializers.CharField(max_length=128, label=_('Password'),
validators=[validate_password], write_only=True, required=False,
widget=widgets.PasswordInput)
groups = serializers.RelatedField(many=True)
class Meta:
model = get_user_model()
model = SystemUser
fields = (
'url', 'username', 'password', 'first_name', 'last_name', 'email',
'is_admin', 'is_active',
'url', 'username', 'password', 'home', 'shell', 'groups', 'is_active',
)
def validate_password(self, attrs, source):
@ -32,4 +34,4 @@ class UserSerializer(AccountSerializerMixin, serializers.HyperlinkedModelSeriali
# FIXME this method will be called when saving nested serializers :(
if not obj.pk:
obj.set_password(obj.password)
super(UserSerializer, self).save_object(obj, **kwargs)
super(SystemUserSerializer, self).save_object(obj, **kwargs)