Add support for primary address in user.

Closes #35

Fixes #35
This commit is contained in:
Nico Schottelius 2020-05-10 21:47:44 +02:00
parent ca2065a94d
commit ec447e0dc4
8 changed files with 106 additions and 13 deletions

View file

@ -63,7 +63,6 @@ router.register(r'v1/my/order', payviews.OrderViewSet, basename='order')
router.register(r'v1/my/payment', payviews.PaymentViewSet, basename='payment') router.register(r'v1/my/payment', payviews.PaymentViewSet, basename='payment')
router.register(r'v1/my/payment-method', payviews.PaymentMethodViewSet, basename='payment-method') router.register(r'v1/my/payment-method', payviews.PaymentMethodViewSet, basename='payment-method')
# admin/staff urls # admin/staff urls
router.register(r'v1/admin/bill', payviews.AdminBillViewSet, basename='admin/bill') router.register(r'v1/admin/bill', payviews.AdminBillViewSet, basename='admin/bill')
router.register(r'v1/admin/payment', payviews.AdminPaymentViewSet, basename='admin/payment') router.register(r'v1/admin/payment', payviews.AdminPaymentViewSet, basename='admin/payment')

View file

@ -0,0 +1,20 @@
# Generated by Django 3.0.6 on 2020-05-10 17:31
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0014_paymentsettings'),
('uncloud_auth', '0003_auto_20200318_1345'),
]
operations = [
migrations.AddField(
model_name='user',
name='primary_billing_address',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='uncloud_pay.BillingAddress'),
),
]

View file

@ -0,0 +1,20 @@
# Generated by Django 3.0.6 on 2020-05-10 17:36
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0014_paymentsettings'),
('uncloud_auth', '0004_user_primary_billing_address'),
]
operations = [
migrations.AlterField(
model_name='user',
name='primary_billing_address',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='uncloud_pay.BillingAddress'),
),
]

View file

@ -3,7 +3,6 @@ from django.db import models
from django.core.validators import MinValueValidator from django.core.validators import MinValueValidator
from uncloud_pay import AMOUNT_DECIMALS, AMOUNT_MAX_DIGITS from uncloud_pay import AMOUNT_DECIMALS, AMOUNT_MAX_DIGITS
from uncloud_pay.models import get_balance_for_user from uncloud_pay.models import get_balance_for_user
class User(AbstractUser): class User(AbstractUser):
@ -18,6 +17,12 @@ class User(AbstractUser):
decimal_places=AMOUNT_DECIMALS, decimal_places=AMOUNT_DECIMALS,
validators=[MinValueValidator(0)]) validators=[MinValueValidator(0)])
# Need to use the string here to prevent a circular import
primary_billing_address = models.ForeignKey('uncloud_pay.BillingAddress',
on_delete=models.PROTECT,
blank=True,
null=True)
@property @property
def balance(self): def balance(self):
return get_balance_for_user(self) return get_balance_for_user(self)

View file

@ -2,15 +2,24 @@ from django.contrib.auth import get_user_model
from rest_framework import serializers from rest_framework import serializers
from uncloud_pay import AMOUNT_DECIMALS, AMOUNT_MAX_DIGITS from uncloud_pay import AMOUNT_DECIMALS, AMOUNT_MAX_DIGITS
from uncloud_pay.models import BillingAddress
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
balance = serializers.DecimalField(max_digits=AMOUNT_MAX_DIGITS,
decimal_places=AMOUNT_DECIMALS)
class Meta: class Meta:
model = get_user_model() model = get_user_model()
fields = ['username', 'email', 'balance', 'maximum_credit' ] read_only_fields = [ 'username', 'balance', 'maximum_credit' ]
fields = read_only_fields + [ 'email', 'primary_billing_address' ]
def validate(self, data):
"""
Ensure that the primary billing address belongs to the user
"""
if 'primary_billing_address' in data:
if not data['primary_billing_address'].owner == self.instance:
raise serializers.ValidationError("Invalid data")
return data
class ImportUserSerializer(serializers.Serializer): class ImportUserSerializer(serializers.Serializer):
username = serializers.CharField() username = serializers.CharField()

View file

@ -3,24 +3,37 @@ from .serializers import *
from django_auth_ldap.backend import LDAPBackend from django_auth_ldap.backend import LDAPBackend
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import mixins
class UserViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): class UserViewSet(viewsets.GenericViewSet):
permission_classes = [permissions.IsAuthenticated] permission_classes = [permissions.IsAuthenticated]
serializer_class = UserSerializer serializer_class = UserSerializer
def get_queryset(self):
return self.request.user
def list(self, request, format=None): def list(self, request, format=None):
# This is a bit stupid: we have a user, we create a queryset by # This is a bit stupid: we have a user, we create a queryset by
# matching on the username. But I don't know a "nicer" way. # matching on the username. But I don't know a "nicer" way.
# Nico, 2020-03-18 # Nico, 2020-03-18
user = get_user_model().objects.get( user = request.user
username=self.request.user.username)
serializer = self.get_serializer(user, context = {'request': request}) serializer = self.get_serializer(user, context = {'request': request})
return Response(serializer.data) return Response(serializer.data)
def create(self, request):
"""
Modify existing user data
"""
user = request.user
serializer = self.get_serializer(user,
context = {'request': request},
data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
class AdminUserViewSet(viewsets.ReadOnlyModelViewSet): class AdminUserViewSet(viewsets.ReadOnlyModelViewSet):
# FIXME: make this admin permission_classes = [permissions.IsAdminUser]
permission_classes = [permissions.IsAuthenticated]
def get_serializer_class(self): def get_serializer_class(self):
if self.action == 'import_from_ldap': if self.action == 'import_from_ldap':

View file

@ -0,0 +1,25 @@
# Generated by Django 3.0.6 on 2020-05-10 13:53
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('uncloud_pay', '0013_auto_20200508_1446'),
]
operations = [
migrations.CreateModel(
name='PaymentSettings',
fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('owner', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('primary_billing_address', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='uncloud_pay.BillingAddress')),
],
),
]

View file

@ -1,6 +1,8 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from rest_framework import serializers from rest_framework import serializers
from uncloud_auth.serializers import UserSerializer from uncloud_auth.serializers import UserSerializer
from django.utils.translation import gettext_lazy as _
from .models import * from .models import *
### ###