Merged code from siarheipuhach/dynamicweb
This commit is contained in:
		
				commit
				
					
						c8cf166571
					
				
			
		
					 66 changed files with 372 additions and 419 deletions
				
			
		|  | @ -4,8 +4,10 @@ python: | ||||||
|     - "3.6" |     - "3.6" | ||||||
| 
 | 
 | ||||||
| env: | env: | ||||||
|     # Set a dummy secret key  |     # Set a dummy secret key | ||||||
|     - DJANGO_SECRET_KEY=0 |     - DJANGO_SECRET_KEY=0 | ||||||
| # install dependencies | # install dependencies | ||||||
| install: "pip install -r requirements.txt" | install: "pip install -r requirements.txt" | ||||||
| script: python manage.py test | script: | ||||||
|  | - flake8 | ||||||
|  | - python manage.py test | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| from django.contrib import admin | # from django.contrib import admin | ||||||
| 
 | 
 | ||||||
| # Register your models here. | # Register your models here. | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| from django.db import models | # from django.db import models | ||||||
| 
 | 
 | ||||||
| # Create your models here. | # Create your models here. | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| from django.test import TestCase | # from django.test import TestCase | ||||||
| 
 | 
 | ||||||
| # Create your tests here. | # Create your tests here. | ||||||
|  |  | ||||||
|  | @ -7,6 +7,6 @@ urlpatterns = [ | ||||||
|     url(r'^/?$', IndexView.as_view(), name='index'), |     url(r'^/?$', IndexView.as_view(), name='index'), | ||||||
|     url(r'/login/', LoginView.as_view(), name='login'), |     url(r'/login/', LoginView.as_view(), name='login'), | ||||||
|     url(r'/contact', ContactView.as_view(), name='contact'), |     url(r'/contact', ContactView.as_view(), name='contact'), | ||||||
| #     url(r'^/beta-program/?$', BetaProgramView.as_view(), name='beta'), |     #     url(r'^/beta-program/?$', BetaProgramView.as_view(), name='beta'), | ||||||
| #     url(r'^/landing/?$', LandingProgramView.as_view(), name='landing'), |     #     url(r'^/landing/?$', LandingProgramView.as_view(), name='landing'), | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  | @ -4,11 +4,11 @@ from django.utils.translation import get_language, get_language_info | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| from django.views.generic.edit import FormView | from django.views.generic.edit import FormView | ||||||
| from django.contrib import messages | from django.contrib import messages | ||||||
| from django.core.urlresolvers import reverse_lazy, reverse |  | ||||||
| from django.shortcuts import render | from django.shortcuts import render | ||||||
| 
 | 
 | ||||||
| from utils.forms import ContactUsForm | from utils.forms import ContactUsForm | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class IndexView(TemplateView): | class IndexView(TemplateView): | ||||||
|     template_name = "alplora/index.html" |     template_name = "alplora/index.html" | ||||||
| 
 | 
 | ||||||
|  | @ -18,6 +18,7 @@ class IndexView(TemplateView): | ||||||
|         context.update(languages) |         context.update(languages) | ||||||
|         return context |         return context | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class ContactView(FormView): | class ContactView(FormView): | ||||||
|     template_name = 'alplora/contact.html' |     template_name = 'alplora/contact.html' | ||||||
|     form_class = ContactUsForm |     form_class = ContactUsForm | ||||||
|  | @ -33,7 +34,8 @@ class ContactView(FormView): | ||||||
|         form.save() |         form.save() | ||||||
|         form.send_email(email_to='info@alplora.ch') |         form.send_email(email_to='info@alplora.ch') | ||||||
|         messages.add_message(self.request, messages.SUCCESS, self.success_message) |         messages.add_message(self.request, messages.SUCCESS, self.success_message) | ||||||
|         return render(self.request, 'alplora/contact_success.html', {})  |         return render(self.request, 'alplora/contact_success.html', {}) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class LoginView(TemplateView): | class LoginView(TemplateView): | ||||||
|     template_name = "alplora/login.html" |     template_name = "alplora/login.html" | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| from django import forms | from django import forms | ||||||
| 
 | 
 | ||||||
| from .models import BetaAccess, BetaAccessVM | from .models import BetaAccess | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BetaAccessForm(forms.ModelForm): | class BetaAccessForm(forms.ModelForm): | ||||||
|  |  | ||||||
|  | @ -5,22 +5,20 @@ from django.utils.translation import activate, get_language | ||||||
| register = template.Library() | register = template.Library() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| @register.simple_tag(takes_context=True) | @register.simple_tag(takes_context=True) | ||||||
| def change_lang(context, lang=None, *args, **kwargs): | def change_lang(context, lang=None, *args, **kwargs): | ||||||
| 
 | 
 | ||||||
|     path = context['request'].path |     path = context['request'].path | ||||||
|     url_parts = resolve( path ) |     url_parts = resolve(path) | ||||||
| 
 | 
 | ||||||
|     url = path |     url = path | ||||||
|     cur_language = get_language() |     cur_language = get_language() | ||||||
|     try: |     try: | ||||||
|         activate(lang) |         activate(lang) | ||||||
|         url = reverse( url_parts.view_name, kwargs=url_parts.kwargs ) |         url = reverse(url_parts.view_name, kwargs=url_parts.kwargs) | ||||||
|     finally: |     finally: | ||||||
|         activate(cur_language) |         activate(cur_language) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     return "%s" % url |     return "%s" % url | ||||||
| 
 | 
 | ||||||
| @register.filter('get_value_from_dict') | @register.filter('get_value_from_dict') | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| from django.test import TestCase | # from django.test import TestCase | ||||||
| 
 | 
 | ||||||
| # Create your tests here. | # Create your tests here. | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| from django.conf.urls import url | from django.conf.urls import url | ||||||
| 
 | 
 | ||||||
| from .views import IndexView, BetaProgramView, LandingProgramView, BetaAccessView, PricingView, SuccessView, PaymentOrderView, OrderConfirmationView | from .views import IndexView, BetaProgramView, LandingProgramView, \ | ||||||
|  |     BetaAccessView, PricingView, SuccessView, PaymentOrderView, OrderConfirmationView | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ from django.http import HttpResponseRedirect | ||||||
| from .forms import BetaAccessForm | from .forms import BetaAccessForm | ||||||
| from .models import BetaAccess, BetaAccessVMType, BetaAccessVM | from .models import BetaAccess, BetaAccessVMType, BetaAccessVM | ||||||
| from django.contrib import messages | from django.contrib import messages | ||||||
| from django.core.urlresolvers import reverse_lazy, reverse | from django.core.urlresolvers import reverse | ||||||
| from django.core.mail import EmailMessage | from django.core.mail import EmailMessage | ||||||
| from utils.mailer import BaseEmail | from utils.mailer import BaseEmail | ||||||
| from django.shortcuts import render | from django.shortcuts import render | ||||||
|  | @ -19,13 +19,15 @@ from hosting.models import HostingOrder, HostingBill | ||||||
| from utils.stripe_utils import StripeUtils | from utils.stripe_utils import StripeUtils | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
| from membership.models import CustomUser, StripeCustomer | from membership.models import CustomUser, StripeCustomer | ||||||
| 
 | from oca.pool import WrongIdError | ||||||
| from opennebula_api.models import OpenNebulaManager | from opennebula_api.models import OpenNebulaManager | ||||||
| from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer | from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class LandingProgramView(TemplateView): | class LandingProgramView(TemplateView): | ||||||
|     template_name = "datacenterlight/landing.html" |     template_name = "datacenterlight/landing.html" | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class SuccessView(TemplateView): | class SuccessView(TemplateView): | ||||||
|     template_name = "datacenterlight/success.html" |     template_name = "datacenterlight/success.html" | ||||||
| 
 | 
 | ||||||
|  | @ -54,17 +56,16 @@ class PricingView(TemplateView): | ||||||
|                 'templates': VirtualMachineTemplateSerializer(templates, many=True).data, |                 'templates': VirtualMachineTemplateSerializer(templates, many=True).data, | ||||||
|             } |             } | ||||||
|         except: |         except: | ||||||
|             messages.error( request, |             messages.error(request, | ||||||
|                 'We have a temporary problem to connect to our backend. \ |                            'We have a temporary problem to connect to our backend. \ | ||||||
|                 Please try again in a few minutes' |                            Please try again in a few minutes' | ||||||
|                 ) |                            ) | ||||||
|             context = { |             context = { | ||||||
|                 'error' : 'connection' |                 'error': 'connection' | ||||||
|                     } |             } | ||||||
| 
 | 
 | ||||||
|         return render(request, self.template_name, context) |         return render(request, self.template_name, context) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def post(self, request): |     def post(self, request): | ||||||
| 
 | 
 | ||||||
|         cores = request.POST.get('cpu') |         cores = request.POST.get('cpu') | ||||||
|  | @ -83,7 +84,7 @@ class PricingView(TemplateView): | ||||||
|             request.session['next'] = reverse('hosting:payment') |             request.session['next'] = reverse('hosting:payment') | ||||||
| 
 | 
 | ||||||
|         request.session['specs'] = { |         request.session['specs'] = { | ||||||
|             'cpu':cores, |             'cpu': cores, | ||||||
|             'memory': memory, |             'memory': memory, | ||||||
|             'disk_size': storage, |             'disk_size': storage, | ||||||
|             'price': price, |             'price': price, | ||||||
|  | @ -98,7 +99,6 @@ class BetaAccessView(FormView): | ||||||
|     success_message = "Thank you, we will contact you as soon as possible" |     success_message = "Thank you, we will contact you as soon as possible" | ||||||
| 
 | 
 | ||||||
|     def form_valid(self, form): |     def form_valid(self, form): | ||||||
| 
 |  | ||||||
|         context = { |         context = { | ||||||
|             'base_url': "{0}://{1}".format(self.request.scheme, self.request.get_host()) |             'base_url': "{0}://{1}".format(self.request.scheme, self.request.get_host()) | ||||||
|         } |         } | ||||||
|  | @ -133,6 +133,7 @@ class BetaAccessView(FormView): | ||||||
|         messages.add_message(self.request, messages.SUCCESS, self.success_message) |         messages.add_message(self.request, messages.SUCCESS, self.success_message) | ||||||
|         return render(self.request, 'datacenterlight/beta_success.html', {}) |         return render(self.request, 'datacenterlight/beta_success.html', {}) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class BetaProgramView(CreateView): | class BetaProgramView(CreateView): | ||||||
|     template_name = "datacenterlight/beta.html" |     template_name = "datacenterlight/beta.html" | ||||||
|     model = BetaAccessVM |     model = BetaAccessVM | ||||||
|  | @ -191,12 +192,12 @@ class IndexView(CreateView): | ||||||
|     form_class = BetaAccessForm |     form_class = BetaAccessForm | ||||||
|     success_url = "/datacenterlight#requestform" |     success_url = "/datacenterlight#requestform" | ||||||
|     success_message = "Thank you, we will contact you as soon as possible" |     success_message = "Thank you, we will contact you as soon as possible" | ||||||
|      | 
 | ||||||
|     @cache_control(no_cache=True, must_revalidate=True, no_store=True) |     @cache_control(no_cache=True, must_revalidate=True, no_store=True) | ||||||
|     def get(self, request, *args, **kwargs): |     def get(self, request, *args, **kwargs): | ||||||
|         if 'specs' in request.session : |         if 'specs' in request.session: | ||||||
|             del request.session['specs'] |             del request.session['specs'] | ||||||
|         if 'user' in request.session : |         if 'user' in request.session: | ||||||
|             del request.session['user'] |             del request.session['user'] | ||||||
|         if 'billing_address_data' in request.session : |         if 'billing_address_data' in request.session : | ||||||
|             del request.session['billing_address_data'] |             del request.session['billing_address_data'] | ||||||
|  | @ -204,16 +205,16 @@ class IndexView(CreateView): | ||||||
|             manager = OpenNebulaManager() |             manager = OpenNebulaManager() | ||||||
|             templates = manager.get_templates() |             templates = manager.get_templates() | ||||||
|             context = { |             context = { | ||||||
|                 'templates': VirtualMachineTemplateSerializer(templates, many=True).data |                 'templates': VirtualMachineTemplateSerializer(templates, many=True).data, | ||||||
|             } |             } | ||||||
|         except: |         except: | ||||||
|             messages.error( request, |             messages.error(request, | ||||||
|                 'We have a temporary problem to connect to our backend. \ |                            'We have a temporary problem to connect to our backend. \ | ||||||
|                 Please try again in a few minutes' |                            Please try again in a few minutes' | ||||||
|                 ) |                            ) | ||||||
|             context = { |             context = { | ||||||
|                 'error' : 'connection' |                 'error': 'connection' | ||||||
|                     } |             } | ||||||
|         return render(request, self.template_name, context) |         return render(request, self.template_name, context) | ||||||
| 
 | 
 | ||||||
|     def post(self, request): |     def post(self, request): | ||||||
|  | @ -225,7 +226,7 @@ class IndexView(CreateView): | ||||||
|         manager = OpenNebulaManager() |         manager = OpenNebulaManager() | ||||||
|         template = manager.get_template(template_id) |         template = manager.get_template(template_id) | ||||||
|         template_data = VirtualMachineTemplateSerializer(template).data |         template_data = VirtualMachineTemplateSerializer(template).data | ||||||
|          | 
 | ||||||
|         name = request.POST.get('name') |         name = request.POST.get('name') | ||||||
|         email = request.POST.get('email') |         email = request.POST.get('email') | ||||||
|         name_field = forms.CharField() |         name_field = forms.CharField() | ||||||
|  | @ -236,7 +237,7 @@ class IndexView(CreateView): | ||||||
|             messages.add_message(self.request, messages.ERROR, '%(value) is not a proper name.'.format(name)) |             messages.add_message(self.request, messages.ERROR, '%(value) is not a proper name.'.format(name)) | ||||||
|             return HttpResponseRedirect(reverse('datacenterlight:index')) |             return HttpResponseRedirect(reverse('datacenterlight:index')) | ||||||
| 
 | 
 | ||||||
|         try:     |         try: | ||||||
|             email = email_field.clean(email) |             email = email_field.clean(email) | ||||||
|         except ValidationError as err: |         except ValidationError as err: | ||||||
|             messages.add_message(self.request, messages.ERROR, '%(value) is not a proper email.'.format(email)) |             messages.add_message(self.request, messages.ERROR, '%(value) is not a proper email.'.format(email)) | ||||||
|  | @ -248,12 +249,12 @@ class IndexView(CreateView): | ||||||
|             'disk_size': storage, |             'disk_size': storage, | ||||||
|             'price': price |             'price': price | ||||||
|         } |         } | ||||||
|          | 
 | ||||||
|         this_user = { |         this_user = { | ||||||
|             'name': name, |             'name': name, | ||||||
|             'email': email |             'email': email | ||||||
|         } |         } | ||||||
|          | 
 | ||||||
|         request.session['specs'] = specs |         request.session['specs'] = specs | ||||||
|         request.session['template'] = template_data |         request.session['template'] = template_data | ||||||
|         request.session['user'] = this_user |         request.session['user'] = this_user | ||||||
|  | @ -354,10 +355,10 @@ class PaymentOrderView(FormView): | ||||||
|             except CustomUser.DoesNotExist: |             except CustomUser.DoesNotExist: | ||||||
|                 password = CustomUser.get_random_password() |                 password = CustomUser.get_random_password() | ||||||
|                 # Register the user, and do not send emails |                 # Register the user, and do not send emails | ||||||
|                 CustomUser.register(user.get('name'),  |                 CustomUser.register(user.get('name'), | ||||||
|                                     password,  |                                     password, | ||||||
|                                     user.get('email'),  |                                     user.get('email'), | ||||||
|                                     app='dcl',  |                                     app='dcl', | ||||||
|                                     base_url=None, send_email=False) |                                     base_url=None, send_email=False) | ||||||
| 
 | 
 | ||||||
|             # Get or create stripe customer |             # Get or create stripe customer | ||||||
|  | @ -377,6 +378,7 @@ class PaymentOrderView(FormView): | ||||||
|         else: |         else: | ||||||
|             return self.form_invalid(form) |             return self.form_invalid(form) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class OrderConfirmationView(DetailView): | class OrderConfirmationView(DetailView): | ||||||
|     template_name = "datacenterlight/order_detail.html" |     template_name = "datacenterlight/order_detail.html" | ||||||
|     payment_template_name = 'hosting/payment.html' |     payment_template_name = 'hosting/payment.html' | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| from django.contrib import admin | from django.contrib import admin | ||||||
| from .models import Supporter, DGGallery, DGPicture, Booking, BookingPrice,\ | from .models import DGGallery, DGPicture, Booking, BookingPrice,\ | ||||||
|     MembershipOrder, Membership, MembershipType, BookingOrder, BookingCancellation |     MembershipOrder, Membership, MembershipType, BookingOrder, BookingCancellation | ||||||
| 
 | 
 | ||||||
| from django.core.urlresolvers import reverse | from django.core.urlresolvers import reverse | ||||||
|  |  | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| from cms.plugin_base import CMSPluginBase | from cms.plugin_base import CMSPluginBase | ||||||
| from cms.plugin_pool import plugin_pool | from cms.plugin_pool import plugin_pool | ||||||
| from cms.wizards import wizard_base |  | ||||||
| from .models import DGGalleryPlugin, DGSupportersPlugin, Supporter | from .models import DGGalleryPlugin, DGSupportersPlugin, Supporter | ||||||
| from django.utils.translation import ugettext as _ | from django.utils.translation import ugettext as _ | ||||||
| # | 
 | ||||||
|  | 
 | ||||||
| class CMSGalleryPlugin(CMSPluginBase): | class CMSGalleryPlugin(CMSPluginBase): | ||||||
|     model = DGGalleryPlugin |     model = DGGalleryPlugin | ||||||
|     name = _("Digital Glarus Gallery") |     name = _("Digital Glarus Gallery") | ||||||
|  | @ -11,12 +11,13 @@ class CMSGalleryPlugin(CMSPluginBase): | ||||||
| 
 | 
 | ||||||
|     def render(self, context, instance, placeholder): |     def render(self, context, instance, placeholder): | ||||||
|         context.update({ |         context.update({ | ||||||
|             'gallery':instance.dgGallery, |             'gallery': instance.dgGallery, | ||||||
|             'object':instance, |             'object': instance, | ||||||
|             'placeholder':placeholder |             'placeholder': placeholder | ||||||
|         }) |         }) | ||||||
|         return context |         return context | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class CMSSupportersPlugin(CMSPluginBase): | class CMSSupportersPlugin(CMSPluginBase): | ||||||
|     name = _("Digital Glarus Supporters") |     name = _("Digital Glarus Supporters") | ||||||
|     model = DGSupportersPlugin |     model = DGSupportersPlugin | ||||||
|  | @ -26,11 +27,10 @@ class CMSSupportersPlugin(CMSPluginBase): | ||||||
|         context.update({ |         context.update({ | ||||||
|             'supporters': Supporter.objects.all().order_by('name'), |             'supporters': Supporter.objects.all().order_by('name'), | ||||||
|             'object': instance, |             'object': instance, | ||||||
|             'placeholder':placeholder |             'placeholder': placeholder | ||||||
|         }) |         }) | ||||||
|         return context |         return context | ||||||
| # | 
 | ||||||
| # | 
 | ||||||
| # |  | ||||||
| plugin_pool.register_plugin(CMSGalleryPlugin) | plugin_pool.register_plugin(CMSGalleryPlugin) | ||||||
| plugin_pool.register_plugin(CMSSupportersPlugin) | plugin_pool.register_plugin(CMSSupportersPlugin) | ||||||
|  |  | ||||||
|  | @ -1,7 +1,6 @@ | ||||||
| from django import forms | from django import forms | ||||||
| from django.db.models import Q | from django.db.models import Q | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| from datetime import datetime |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| from utils.models import BillingAddress | from utils.models import BillingAddress | ||||||
|  | @ -92,7 +91,7 @@ class CancelBookingForm(forms.ModelForm): | ||||||
| class BookingDateForm(forms.Form): | class BookingDateForm(forms.Form): | ||||||
|     start_date = forms.DateField(required=False, |     start_date = forms.DateField(required=False, | ||||||
|                                  widget=forms.TextInput(attrs={'id': 'booking-date-1', |                                  widget=forms.TextInput(attrs={'id': 'booking-date-1', | ||||||
|                                                                      'value': 'Select your date'})) |                                                                'value': 'Select your date'})) | ||||||
|     end_date = forms.DateField(required=False, |     end_date = forms.DateField(required=False, | ||||||
|                                widget=forms.TextInput(attrs={'id': 'booking-date-2'})) |                                widget=forms.TextInput(attrs={'id': 'booking-date-2'})) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ from django.conf import settings | ||||||
| import stripe | import stripe | ||||||
| stripe.api_key = settings.STRIPE_API_PRIVATE_KEY | stripe.api_key = settings.STRIPE_API_PRIVATE_KEY | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class Command(BaseCommand): | class Command(BaseCommand): | ||||||
|     help = "Record payment plans for Digital Glarus on stripe" |     help = "Record payment plans for Digital Glarus on stripe" | ||||||
| 
 | 
 | ||||||
|  | @ -10,5 +11,3 @@ class Command(BaseCommand): | ||||||
|         print("Available plans:") |         print("Available plans:") | ||||||
|         for plan in stripe.Plan.all(): |         for plan in stripe.Plan.all(): | ||||||
|             print(plan) |             print(plan) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -11,11 +11,11 @@ PAYMENT_PLANS = [ | ||||||
|                      'id': "spontaneus" |                      'id': "spontaneus" | ||||||
|                      }), |                      }), | ||||||
|     ('committed', { |     ('committed', { | ||||||
|         'amount':36000, |         'amount': 36000, | ||||||
|         'interval':'year', |         'interval': 'year', | ||||||
|         'name':'The Committed', |         'name': 'The Committed', | ||||||
|         'currency':'chf', |         'currency': 'chf', | ||||||
|         'id':'committed' |         'id': 'committed' | ||||||
|     }) |     }) | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | @ -26,8 +26,6 @@ class Command(BaseCommand): | ||||||
|     def handle(self, *args, **options): |     def handle(self, *args, **options): | ||||||
|         for payment_plan, data in PAYMENT_PLANS: |         for payment_plan, data in PAYMENT_PLANS: | ||||||
|             try: |             try: | ||||||
|                 res = stripe.Plan.create(**data) |                 stripe.Plan.create(**data) | ||||||
|             except stripe.InvalidRequestError as e: |             except stripe.InvalidRequestError as e: | ||||||
|                 print(e) |                 print(e) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -105,7 +105,7 @@ class Membership(models.Model): | ||||||
|         has_order_current_month = Q(membershiporder__customer__user=user, |         has_order_current_month = Q(membershiporder__customer__user=user, | ||||||
|                                     membershiporder__created_at__month=datetime.today().month) |                                     membershiporder__created_at__month=datetime.today().month) | ||||||
|         # has_order_past_month = Q(membershiporder__customer__user=user, |         # has_order_past_month = Q(membershiporder__customer__user=user, | ||||||
|                                  # membershiporder__created_at__month=past_month) |         #  membershiporder__created_at__month=past_month) | ||||||
|         active_membership = Q(active=True) |         active_membership = Q(active=True) | ||||||
|         # return cls.objects.filter(has_order_past_month | has_order_current_month).\ |         # return cls.objects.filter(has_order_past_month | has_order_current_month).\ | ||||||
|         return cls.objects.filter(has_order_current_month).\ |         return cls.objects.filter(has_order_current_month).\ | ||||||
|  | @ -316,17 +316,20 @@ class DGGallery(models.Model): | ||||||
| 
 | 
 | ||||||
|     class Meta: |     class Meta: | ||||||
|         verbose_name_plural = 'dgGallery' |         verbose_name_plural = 'dgGallery' | ||||||
| # | 
 | ||||||
|  | 
 | ||||||
| class DGPicture(models.Model): | class DGPicture(models.Model): | ||||||
|     gallery = models.ForeignKey(DGGallery) |     gallery = models.ForeignKey(DGGallery) | ||||||
|     image =  FilerImageField(related_name='dg_gallery') |     image = FilerImageField(related_name='dg_gallery') | ||||||
|     description = models.CharField(max_length=60) |     description = models.CharField(max_length=60) | ||||||
| 
 | 
 | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|         return "%s" % (self.image.name) |         return "%s" % (self.image.name) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class DGGalleryPlugin(CMSPlugin): | class DGGalleryPlugin(CMSPlugin): | ||||||
|     dgGallery = models.ForeignKey(DGGallery) |     dgGallery = models.ForeignKey(DGGallery) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class DGSupportersPlugin(CMSPlugin): | class DGSupportersPlugin(CMSPlugin): | ||||||
|     pass |     pass | ||||||
|  |  | ||||||
|  | @ -1,4 +1,3 @@ | ||||||
| import json |  | ||||||
| from model_mommy import mommy | from model_mommy import mommy | ||||||
| from unittest import mock | from unittest import mock | ||||||
| 
 | 
 | ||||||
|  | @ -150,7 +149,7 @@ class MembershipPaymentViewTest(BaseTestCase): | ||||||
|         # self.assertTrue(HostingOrder.objects.filter(customer=stripe_customer).exists()) |         # self.assertTrue(HostingOrder.objects.filter(customer=stripe_customer).exists()) | ||||||
|         # hosting_order = HostingOrder.objects.filter(customer=stripe_customer)[0] |         # hosting_order = HostingOrder.objects.filter(customer=stripe_customer)[0] | ||||||
|         # vm_plan = { |         # vm_plan = { | ||||||
|             # 'cores': hosting_order.vm_plan.cores, |         #  'cores': hosting_order.vm_plan.cores, | ||||||
|         #     'memory': hosting_order.vm_plan.memory, |         #     'memory': hosting_order.vm_plan.memory, | ||||||
|         #     'disk_size': hosting_order.vm_plan.disk_size, |         #     'disk_size': hosting_order.vm_plan.disk_size, | ||||||
|         #     'price': hosting_order.vm_plan.price, |         #     'price': hosting_order.vm_plan.price, | ||||||
|  |  | ||||||
|  | @ -720,7 +720,9 @@ class ContactView(FormView): | ||||||
|         messages.add_message(self.request, messages.SUCCESS, self.success_message) |         messages.add_message(self.request, messages.SUCCESS, self.success_message) | ||||||
|         return super(ContactView, self).form_valid(form) |         return super(ContactView, self).form_valid(form) | ||||||
| 
 | 
 | ||||||
| ############## OLD VIEWS  | 
 | ||||||
|  | # OLD VIEWS | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| def blog(request): | def blog(request): | ||||||
|     tags = ["digitalglarus"] |     tags = ["digitalglarus"] | ||||||
|  | @ -751,6 +753,3 @@ def supporters(request): | ||||||
|         'supporters': Supporter.objects.order_by('name') |         'supporters': Supporter.objects.order_by('name') | ||||||
|     } |     } | ||||||
|     return render(request, 'supporters.html', context) |     return render(request, 'supporters.html', context) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -9,12 +9,15 @@ from django.utils.translation import ugettext_lazy as _ | ||||||
| # dotenv | # dotenv | ||||||
| import dotenv | import dotenv | ||||||
| 
 | 
 | ||||||
| gettext = lambda s: s | 
 | ||||||
|  | def gettext(s): | ||||||
|  |     return s | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def env(env_name): | def env(env_name): | ||||||
|     return os.environ.get(env_name) |     return os.environ.get(env_name) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||||||
| 
 | 
 | ||||||
| PROJECT_DIR = os.path.abspath( | PROJECT_DIR = os.path.abspath( | ||||||
|  | @ -83,7 +86,7 @@ INSTALLED_APPS = ( | ||||||
|     'django_select2', |     'django_select2', | ||||||
|     'meta', |     'meta', | ||||||
|     'meta_mixin', |     'meta_mixin', | ||||||
| #    'admin_enhancer', |     # 'admin_enhancer', | ||||||
|     'djangocms_blog', |     'djangocms_blog', | ||||||
|     'bootstrap3', |     'bootstrap3', | ||||||
|     'compressor', |     'compressor', | ||||||
|  | @ -433,5 +436,5 @@ MANAGERS = ADMINS | ||||||
| 
 | 
 | ||||||
| ALLOWED_HOSTS = [ | ALLOWED_HOSTS = [ | ||||||
|     ".ungleich.ch", |     ".ungleich.ch", | ||||||
|     "digital.glarus.ungleich.ch" , |     "digital.glarus.ungleich.ch", | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| from .base import * | # from .base import * | ||||||
|  |  | ||||||
|  | @ -11,7 +11,9 @@ from django.utils.translation import ugettext_lazy as _ | ||||||
| # dotenv | # dotenv | ||||||
| import dotenv | import dotenv | ||||||
| 
 | 
 | ||||||
| gettext = lambda s: s | 
 | ||||||
|  | def gettext(s): | ||||||
|  |     return s | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def env(env_name): | def env(env_name): | ||||||
|  | @ -186,7 +188,11 @@ CMS_TEMPLATES = ( | ||||||
| DATABASES = { | DATABASES = { | ||||||
|     'default': { |     'default': { | ||||||
|         'ENGINE': 'django.db.backends.postgresql_psycopg2', |         'ENGINE': 'django.db.backends.postgresql_psycopg2', | ||||||
|         'NAME': 'app' |         'NAME': 'app', | ||||||
|  |         'HOST': 'localhost', | ||||||
|  |         'USER': 'ubuntu', | ||||||
|  |         'PASSWORD': 'Qwerty123', | ||||||
|  | 
 | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -462,17 +468,20 @@ STRIPE_DESCRIPTION_ON_PAYMENT = "Payment for ungleich GmbH services" | ||||||
| 
 | 
 | ||||||
| # EMAIL MESSAGES | # EMAIL MESSAGES | ||||||
| REGISTRATION_MESSAGE = {'subject': "Validation mail", | REGISTRATION_MESSAGE = {'subject': "Validation mail", | ||||||
|                         'message': 'Thank You for registering for account on Digital Glarus.\nPlease verify Your account under following link http://{host}/en-us/digitalglarus/login/validate/{slug}', |                         'message': 'Thank You for registering for account on Digital Glarus.\n' | ||||||
|  |                                    'Please verify Your account under following link ' | ||||||
|  |                                    'http://{host}/en-us/digitalglarus/login/validate/{slug}', | ||||||
|                         } |                         } | ||||||
| STRIPE_API_PRIVATE_KEY = env('STRIPE_API_PRIVATE_KEY') | STRIPE_API_PRIVATE_KEY = env('STRIPE_API_PRIVATE_KEY') | ||||||
| STRIPE_API_PUBLIC_KEY = env('STRIPE_API_PUBLIC_KEY') | STRIPE_API_PUBLIC_KEY = env('STRIPE_API_PUBLIC_KEY') | ||||||
| 
 | 
 | ||||||
| DEBUG = True | DEBUG = True | ||||||
| 
 | 
 | ||||||
| if DEBUG: | # not used | ||||||
|     from .local import * | # if DEBUG: | ||||||
| else: | #     from .local import * | ||||||
|     from .prod import * | # # else: | ||||||
|  | # #     from .prod import * | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ANONYMOUS_USER_NAME = 'anonymous@ungleich.ch' | ANONYMOUS_USER_NAME = 'anonymous@ungleich.ch' | ||||||
|  |  | ||||||
|  | @ -1,5 +1,7 @@ | ||||||
| from .base import * | from .base import * # flake8: noqa | ||||||
| REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='dynamicweb-development.ungleich.ch',slug='{slug}') | 
 | ||||||
|  | REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='dynamicweb-development.ungleich.ch', | ||||||
|  |                                                                          slug='{slug}') | ||||||
| ALLOWED_HOSTS = [ | ALLOWED_HOSTS = [ | ||||||
|     "*" |     "*" | ||||||
|     ] |     ] | ||||||
|  | @ -13,9 +15,9 @@ CACHES = { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MIDDLEWARE_CLASSES+=("debug_toolbar.middleware.DebugToolbarMiddleware",) | MIDDLEWARE_CLASSES += ("debug_toolbar.middleware.DebugToolbarMiddleware",) | ||||||
| 
 | 
 | ||||||
| INSTALLED_APPS+=( | INSTALLED_APPS += ( | ||||||
|     'django_extensions', |     'django_extensions', | ||||||
|     'debug_toolbar' |     'debug_toolbar' | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  | @ -1,15 +1,16 @@ | ||||||
| from .base import * | from .base import * # flake8: noqa | ||||||
| 
 | 
 | ||||||
| # List of people that get admin messages | # List of people that get admin messages | ||||||
| ADMINS = ( (x, x + "@ungleich.ch") for x in ["web-team"] ) | ADMINS = ((x, x + "@ungleich.ch") for x in ["web-team"]) | ||||||
| 
 | 
 | ||||||
| DEBUG=False | DEBUG = False | ||||||
| 
 | 
 | ||||||
| EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' | EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' | ||||||
| 
 | 
 | ||||||
| #MANAGERS = ADMINS | # MANAGERS = ADMINS | ||||||
| 
 | 
 | ||||||
| REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='digitalglarus.ungleich.ch',slug='{slug}') | REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='digitalglarus.ungleich.ch', | ||||||
|  |                                                                          slug='{slug}')  # flake8: noqa | ||||||
| 
 | 
 | ||||||
| ALLOWED_HOSTS = [ | ALLOWED_HOSTS = [ | ||||||
|     ".ungleich.ch", |     ".ungleich.ch", | ||||||
|  |  | ||||||
|  | @ -12,30 +12,31 @@ from django.views.generic import RedirectView | ||||||
| from django.core.urlresolvers import reverse_lazy | from django.core.urlresolvers import reverse_lazy | ||||||
| import debug_toolbar | import debug_toolbar | ||||||
| 
 | 
 | ||||||
| urlpatterns = [   url(r'^index.html$', LandingView.as_view()), | urlpatterns = [url(r'^index.html$', LandingView.as_view()), | ||||||
|                   url(r'^hosting/', include('hosting.urls', namespace="hosting")), |                url(r'^hosting/', include('hosting.urls', namespace="hosting")), | ||||||
|                   url(r'^open_api/', include('opennebula_api.urls', |                url(r'^open_api/', include('opennebula_api.urls', | ||||||
|                       namespace='opennebula_api')), |                                           namespace='opennebula_api')), | ||||||
|                   url(r'^railshosting/', RailsHostingView.as_view(), name="rails.hosting"), |                url(r'^railshosting/', RailsHostingView.as_view(), name="rails.hosting"), | ||||||
|                   url(r'^nodehosting/', NodeJSHostingView.as_view(), name="node.hosting"), |                url(r'^nodehosting/', NodeJSHostingView.as_view(), name="node.hosting"), | ||||||
|                   url(r'^djangohosting/', DjangoHostingView.as_view(), name="django.hosting"), |                url(r'^djangohosting/', DjangoHostingView.as_view(), name="django.hosting"), | ||||||
|                   url(r'^nosystemd/', include('nosystemd.urls', namespace="nosystemd")), |                url(r'^nosystemd/', include('nosystemd.urls', namespace="nosystemd")), | ||||||
|                   url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')), |                url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')), | ||||||
|                   url(r'^jsi18n/(?P<packages>\S+?)/$', |                url(r'^jsi18n/(?P<packages>\S+?)/$', | ||||||
|                       'django.views.i18n.javascript_catalog'), |                    'django.views.i18n.javascript_catalog'), | ||||||
|               ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) |                ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) | ||||||
| 
 | 
 | ||||||
| # note the django CMS URLs included via i18n_patterns | # note the django CMS URLs included via i18n_patterns | ||||||
| urlpatterns += i18n_patterns('', | urlpatterns += i18n_patterns('', | ||||||
|                              url(r'^/?$', LandingView.as_view()), |                              url(r'^/?$', LandingView.as_view()), | ||||||
|                              url(r'^admin/', include(admin.site.urls)), |                              url(r'^admin/', include(admin.site.urls)), | ||||||
|                              url(r'^datacenterlight', include('datacenterlight.urls', namespace="datacenterlight")), |                              url(r'^datacenterlight', include('datacenterlight.urls', namespace="datacenterlight")), | ||||||
|                              url(r'^hosting/', RedirectView.as_view(url=reverse_lazy('hosting:login')), name='redirect_hosting_login'), |                              url(r'^hosting/', RedirectView.as_view( | ||||||
|  |                                  url=reverse_lazy('hosting:login')), name='redirect_hosting_login'), | ||||||
|                              url(r'^alplora', include('alplora.urls', namespace="alplora")), |                              url(r'^alplora', include('alplora.urls', namespace="alplora")), | ||||||
|                              url(r'^membership/', include(membership_urls)), |                              url(r'^membership/', include(membership_urls)), | ||||||
|                              url(r'^digitalglarus/', include('digitalglarus.urls', |                              url(r'^digitalglarus/', include('digitalglarus.urls', | ||||||
|                                                              namespace="digitalglarus")), |                                                              namespace="digitalglarus")), | ||||||
|                              #url(r'^blog/', include('ungleich.urls', namespace='ungleich')), |                              # url(r'^blog/', include('ungleich.urls', namespace='ungleich')), | ||||||
|                              url(r'^', |                              url(r'^', | ||||||
|                                  include('ungleich_page.urls', namespace='ungleich_page'), |                                  include('ungleich_page.urls', namespace='ungleich_page'), | ||||||
|                                  name='ungleich_page'), |                                  name='ungleich_page'), | ||||||
|  | @ -50,4 +51,4 @@ if settings.DEBUG: | ||||||
|                                     'document_root': settings.MEDIA_ROOT, |                                     'document_root': settings.MEDIA_ROOT, | ||||||
|                                 }), |                                 }), | ||||||
|                             ) |                             ) | ||||||
|     urlpatterns += patterns('',url(r'^__debug__/', include(debug_toolbar.urls))) |     urlpatterns += patterns('', url(r'^__debug__/', include(debug_toolbar.urls))) | ||||||
|  |  | ||||||
|  | @ -7,13 +7,13 @@ For more information on this file, see | ||||||
| https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ | https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
| import os,sys | import os | ||||||
| #sys.path.append(os.path.dirname(__file__)) | import sys | ||||||
|  | from django.core.wsgi import get_wsgi_application | ||||||
|  | 
 | ||||||
|  | # sys.path.append(os.path.dirname(__file__)) | ||||||
| sys.path.append('/home/app/pyvenv/lib/python3.4/site-packages/') | sys.path.append('/home/app/pyvenv/lib/python3.4/site-packages/') | ||||||
| 
 | 
 | ||||||
| os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dynamicweb.settings.prod") | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dynamicweb.settings.prod") | ||||||
| 
 | 
 | ||||||
| from django.core.wsgi import get_wsgi_application |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| application = get_wsgi_application() | application = get_wsgi_application() | ||||||
|  |  | ||||||
|  | @ -1,8 +1,4 @@ | ||||||
| from django.contrib import admin | from django.contrib import admin | ||||||
| from django.utils.html import format_html |  | ||||||
| from django.core.urlresolvers import reverse |  | ||||||
| 
 |  | ||||||
| from utils.mailer import BaseEmail |  | ||||||
| 
 | 
 | ||||||
| from .models import HostingOrder, HostingBill, HostingPlan | from .models import HostingOrder, HostingBill, HostingPlan | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,14 +1,11 @@ | ||||||
| import random |  | ||||||
| import string |  | ||||||
| from django import forms | from django import forms | ||||||
| from membership.models import CustomUser | from membership.models import CustomUser | ||||||
| from django.contrib.auth import authenticate | from django.contrib.auth import authenticate | ||||||
| 
 | 
 | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| 
 | 
 | ||||||
| from utils.stripe_utils import StripeUtils | from .models import UserHostingKey | ||||||
| 
 | 
 | ||||||
| from .models import HostingOrder, UserHostingKey |  | ||||||
| 
 | 
 | ||||||
| class HostingUserLoginForm(forms.Form): | class HostingUserLoginForm(forms.Form): | ||||||
| 
 | 
 | ||||||
|  | @ -62,9 +59,9 @@ class HostingUserSignupForm(forms.ModelForm): | ||||||
| class UserHostingKeyForm(forms.ModelForm): | class UserHostingKeyForm(forms.ModelForm): | ||||||
|     private_key = forms.CharField(widget=forms.HiddenInput(), required=False) |     private_key = forms.CharField(widget=forms.HiddenInput(), required=False) | ||||||
|     public_key = forms.CharField(widget=forms.Textarea(), required=False, |     public_key = forms.CharField(widget=forms.Textarea(), required=False, | ||||||
|             help_text=_('Paste here your public key')) |                                  help_text=_('Paste here your public key')) | ||||||
|     user = forms.models.ModelChoiceField(queryset=CustomUser.objects.all(), |     user = forms.models.ModelChoiceField(queryset=CustomUser.objects.all(), | ||||||
|             required=False, widget=forms.HiddenInput()) |                                          required=False, widget=forms.HiddenInput()) | ||||||
|     name = forms.CharField(required=True) |     name = forms.CharField(required=True) | ||||||
| 
 | 
 | ||||||
|     def __init__(self, *args, **kwargs): |     def __init__(self, *args, **kwargs): | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| from django.core.management.base import BaseCommand, CommandError | from django.core.management.base import BaseCommand | ||||||
| from hosting.models import VirtualMachineType | from hosting.models import VirtualMachineType | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -55,15 +55,15 @@ class Command(BaseCommand): | ||||||
|             }, |             }, | ||||||
|         ] |         ] | ||||||
| 
 | 
 | ||||||
| 
 |         # not used | ||||||
|         hetzner = { |         #  hetzner = { | ||||||
|             'base_price': 10, |         #     'base_price': 10, | ||||||
|             'core_price': 5, |         #     'core_price': 5, | ||||||
|             'memory_price': 2, |         #     'memory_price': 2, | ||||||
|             'disk_size_price': 0.6, |         #     'disk_size_price': 0.6, | ||||||
|             'description': 'VM auf einzelner HW, Raid1, kein HA', |         #     'description': 'VM auf einzelner HW, Raid1, kein HA', | ||||||
|             'location': 'DE' |         #     'location': 'DE' | ||||||
|         } |         # } | ||||||
| 
 | 
 | ||||||
|         # return { |         # return { | ||||||
|         #     # 'hetzner_nug': { |         #     # 'hetzner_nug': { | ||||||
|  |  | ||||||
|  | @ -1,22 +1,16 @@ | ||||||
| import os | import os | ||||||
| import socket |  | ||||||
| import logging | import logging | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| import oca |  | ||||||
| from django.db import models | from django.db import models | ||||||
| from django.utils.translation import ugettext_lazy as _ |  | ||||||
| from django.utils.functional import cached_property | from django.utils.functional import cached_property | ||||||
| 
 | 
 | ||||||
| from django.conf import settings |  | ||||||
| 
 | 
 | ||||||
| from Crypto.PublicKey import RSA | from Crypto.PublicKey import RSA | ||||||
| from stored_messages.settings import stored_messages_settings |  | ||||||
| 
 | 
 | ||||||
| from membership.models import StripeCustomer, CustomUser | from membership.models import StripeCustomer, CustomUser | ||||||
| from utils.models import BillingAddress | from utils.models import BillingAddress | ||||||
| from utils.mixins import AssignPermissionsMixin | from utils.mixins import AssignPermissionsMixin | ||||||
| from .managers import VMPlansManager |  | ||||||
| 
 | 
 | ||||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||||
| 
 | 
 | ||||||
|  | @ -29,7 +23,7 @@ class HostingPlan(models.Model): | ||||||
|     def serialize(self): |     def serialize(self): | ||||||
|         return { |         return { | ||||||
|             'id': self.id, |             'id': self.id, | ||||||
|             'cpu':self.cpu_cores, |             'cpu': self.cpu_cores, | ||||||
|             'memory': self.memory, |             'memory': self.memory, | ||||||
|             'disk_size': self.disk_size, |             'disk_size': self.disk_size, | ||||||
|             'price': self.price(), |             'price': self.price(), | ||||||
|  | @ -46,6 +40,7 @@ class HostingPlan(models.Model): | ||||||
|         price += self.memory * 2 |         price += self.memory * 2 | ||||||
|         return price |         return price | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class HostingOrder(AssignPermissionsMixin, models.Model): | class HostingOrder(AssignPermissionsMixin, models.Model): | ||||||
| 
 | 
 | ||||||
|     ORDER_APPROVED_STATUS = 'Approved' |     ORDER_APPROVED_STATUS = 'Approved' | ||||||
|  | @ -128,6 +123,7 @@ class UserHostingKey(models.Model): | ||||||
|         # self.save(update_fields=['public_key']) |         # self.save(update_fields=['public_key']) | ||||||
|         return private_key, public_key |         return private_key, public_key | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class HostingBill(AssignPermissionsMixin, models.Model): | class HostingBill(AssignPermissionsMixin, models.Model): | ||||||
|     customer = models.ForeignKey(StripeCustomer) |     customer = models.ForeignKey(StripeCustomer) | ||||||
|     billing_address = models.ForeignKey(BillingAddress) |     billing_address = models.ForeignKey(BillingAddress) | ||||||
|  | @ -147,4 +143,3 @@ class HostingBill(AssignPermissionsMixin, models.Model): | ||||||
|     def create(cls, customer=None, billing_address=None): |     def create(cls, customer=None, billing_address=None): | ||||||
|         instance = cls.objects.create(customer=customer, billing_address=billing_address) |         instance = cls.objects.create(customer=customer, billing_address=billing_address) | ||||||
|         return instance |         return instance | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| {% extends "hosting/base_short.html" %} | {% extends "hosting/base_short.html" %} | ||||||
| {% load staticfiles bootstrap3 i18n %} | {% load staticfiles bootstrap3 i18n %} | ||||||
| {% block content %}  | {% block content %} | ||||||
| <!-- Credit card form --> | <!-- Credit card form --> | ||||||
| <div> | <div> | ||||||
| 	<div class="payment-container"> | 	<div class="payment-container"> | ||||||
|  | @ -32,7 +32,7 @@ | ||||||
| 						</div> | 						</div> | ||||||
| 					</div> | 					</div> | ||||||
| 				</form> | 				</form> | ||||||
| 				 | 
 | ||||||
| 			</div> | 			</div> | ||||||
| 			<div class="col-xs-12 col-md-4  billing"> | 			<div class="col-xs-12 col-md-4  billing"> | ||||||
| 				<h3><b>{%trans "Billing Address"%}</b></h3> | 				<h3><b>{%trans "Billing Address"%}</b></h3> | ||||||
|  | @ -59,7 +59,7 @@ | ||||||
|                         <h5 class="membership-lead">Last 4: *****{{credit_card_data.last4}}</h5> |                         <h5 class="membership-lead">Last 4: *****{{credit_card_data.last4}}</h5> | ||||||
|                         <h5 class="membership-lead">Type: {{credit_card_data.cc_brand}}</h5> |                         <h5 class="membership-lead">Type: {{credit_card_data.cc_brand}}</h5> | ||||||
|                         <input type="hidden" name="credit_card_needed" value="false"/> |                         <input type="hidden" name="credit_card_needed" value="false"/> | ||||||
|                       </form>   |                       </form> | ||||||
|                       <div class="col-xs-6"> |                       <div class="col-xs-6"> | ||||||
|                         <button id="payment_button_with_creditcard" class="btn btn-success btn-sm btn-block" type="submit"> |                         <button id="payment_button_with_creditcard" class="btn btn-success btn-sm btn-block" type="submit"> | ||||||
| 							 {% trans "Submit Payment" %} | 							 {% trans "Submit Payment" %} | ||||||
|  | @ -89,7 +89,7 @@ | ||||||
| 											placeholder="{%trans "Valid Card Number"%}" required autofocus data-stripe="number" /> | 											placeholder="{%trans "Valid Card Number"%}" required autofocus data-stripe="number" /> | ||||||
| 	                                        <span class="input-group-addon"><i class="fa fa-credit-card"></i></span> | 	                                        <span class="input-group-addon"><i class="fa fa-credit-card"></i></span> | ||||||
| 	                                    </div> | 	                                    </div> | ||||||
| 	                                </div>                             | 	                                </div> | ||||||
| 	                            </div> | 	                            </div> | ||||||
| 	                        </div> | 	                        </div> | ||||||
| 	                        <div class="row"> | 	                        <div class="row"> | ||||||
|  | @ -131,7 +131,7 @@ | ||||||
| 	                        </div> | 	                        </div> | ||||||
| 	                        {% endif %} | 	                        {% endif %} | ||||||
| 
 | 
 | ||||||
|                             | 
 | ||||||
| 	                    </form> | 	                    </form> | ||||||
|                     {% endif %} |                     {% endif %} | ||||||
| 
 | 
 | ||||||
|  | @ -146,7 +146,7 @@ | ||||||
| <!-- stripe key data --> | <!-- stripe key data --> | ||||||
| {% if stripe_key %} | {% if stripe_key %} | ||||||
| {% get_current_language as LANGUAGE_CODE %} | {% get_current_language as LANGUAGE_CODE %} | ||||||
| <script type="text/javascript">  | <script type="text/javascript"> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|      (function () { |      (function () { | ||||||
|  | @ -157,7 +157,7 @@ | ||||||
| {%endif%} | {%endif%} | ||||||
| 
 | 
 | ||||||
| {% if credit_card_data.last4 and credit_card_data.cc_brand %} | {% if credit_card_data.last4 and credit_card_data.cc_brand %} | ||||||
| <script type="text/javascript">  | <script type="text/javascript"> | ||||||
|      (function () {window.hasCreditcard = true;})(); |      (function () {window.hasCreditcard = true;})(); | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ from django.test import TestCase | ||||||
| from django.core.urlresolvers import reverse | from django.core.urlresolvers import reverse | ||||||
| from django.core.urlresolvers import resolve | from django.core.urlresolvers import resolve | ||||||
| from django.contrib.auth.tokens import default_token_generator | from django.contrib.auth.tokens import default_token_generator | ||||||
| from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode | from django.utils.http import urlsafe_base64_encode | ||||||
| from django.utils.encoding import force_bytes | from django.utils.encoding import force_bytes | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| from django.test import TestCase | # from django.test import TestCase | ||||||
| 
 | 
 | ||||||
| # Create your tests here. | # Create your tests here. | ||||||
| 
 | 
 | ||||||
| test_user_can_add_ssh_key() | # test_user_can_add_ssh_key() | ||||||
| 
 | # | ||||||
| test_user_can_delete_ssh_ke() | # test_user_can_delete_ssh_ke() | ||||||
|  |  | ||||||
|  | @ -1,13 +1,11 @@ | ||||||
| from collections import namedtuple | from oca.pool import WrongNameError, WrongIdError | ||||||
| 
 |  | ||||||
| from django.shortcuts import render | from django.shortcuts import render | ||||||
| from django.http import Http404 | from django.http import Http404 | ||||||
| from django.core.urlresolvers import reverse_lazy, reverse | from django.core.urlresolvers import reverse_lazy, reverse | ||||||
| from django.contrib.auth.mixins import LoginRequiredMixin | from django.contrib.auth.mixins import LoginRequiredMixin | ||||||
| from django.views.generic import View, CreateView, FormView, ListView, DetailView,\ | from django.views.generic import View, CreateView, FormView, ListView, DetailView, \ | ||||||
|     DeleteView, TemplateView, UpdateView |     DeleteView, TemplateView, UpdateView | ||||||
| from django.http import HttpResponseRedirect | from django.http import HttpResponseRedirect | ||||||
| from django.contrib.auth import authenticate, login |  | ||||||
| from django.contrib import messages | from django.contrib import messages | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.shortcuts import redirect | from django.shortcuts import redirect | ||||||
|  | @ -30,14 +28,11 @@ from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyFo | ||||||
| from .mixins import ProcessVMSelectionMixin | from .mixins import ProcessVMSelectionMixin | ||||||
| 
 | 
 | ||||||
| from opennebula_api.models import OpenNebulaManager | from opennebula_api.models import OpenNebulaManager | ||||||
| from opennebula_api.serializers import VirtualMachineSerializer,\ | from opennebula_api.serializers import VirtualMachineSerializer, \ | ||||||
|     VirtualMachineTemplateSerializer |     VirtualMachineTemplateSerializer | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| from oca.exceptions import OpenNebulaException |  | ||||||
| from oca.pool import WrongNameError, WrongIdError |  | ||||||
| 
 |  | ||||||
| CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a backend \ | CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a backend \ | ||||||
|                     connection error. please try again in a few minutes." |                     connection error. please try again in a few minutes." | ||||||
| 
 | 
 | ||||||
|  | @ -142,7 +137,6 @@ class HostingPricingView(ProcessVMSelectionMixin, View): | ||||||
|             'templates': templates, |             'templates': templates, | ||||||
|             'configuration_options': configuration_options, |             'configuration_options': configuration_options, | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return context |         return context | ||||||
|  | @ -173,7 +167,6 @@ class IndexView(View): | ||||||
|         return context |         return context | ||||||
| 
 | 
 | ||||||
|     def get(self, request, *args, **kwargs): |     def get(self, request, *args, **kwargs): | ||||||
| 
 |  | ||||||
|         context = self.get_context_data() |         context = self.get_context_data() | ||||||
| 
 | 
 | ||||||
|         return render(request, self.template_name, context) |         return render(request, self.template_name, context) | ||||||
|  | @ -205,44 +198,48 @@ class SignupView(CreateView): | ||||||
| 
 | 
 | ||||||
|         return HttpResponseRedirect(reverse_lazy('hosting:signup-validate')) |         return HttpResponseRedirect(reverse_lazy('hosting:signup-validate')) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class SignupValidateView(TemplateView): | class SignupValidateView(TemplateView): | ||||||
|     template_name = "hosting/signup_validate.html" |     template_name = "hosting/signup_validate.html" | ||||||
|      | 
 | ||||||
|     def get_context_data(self, **kwargs): |     def get_context_data(self, **kwargs): | ||||||
|         context = super(SignupValidateView, self).get_context_data(**kwargs) |         context = super(SignupValidateView, self).get_context_data(**kwargs) | ||||||
|         login_url = '<a href="' + reverse('hosting:login') + '">' + str(_('login')) +'</a>' |         login_url = '<a href="' + reverse('hosting:login') + '">' + str(_('login')) + '</a>' | ||||||
|         home_url = '<a href="' + reverse('datacenterlight:index') + '">Data Center Light</a>' |         home_url = '<a href="' + reverse('datacenterlight:index') + '">Data Center Light</a>' | ||||||
|         message='{signup_success_message} {lurl}</a> \ |         message = '{signup_success_message} {lurl}</a> \ | ||||||
|                  <br />{go_back} {hurl}.'.format( |                  <br />{go_back} {hurl}.'.format( | ||||||
|                   signup_success_message = _('Thank you for signing up. We have sent an email to you. Please follow the instructions in it to activate your account. Once activated, you can login using'), |             signup_success_message=_( | ||||||
|                   go_back = _('Go back to'), |                 'Thank you for signing up. We have sent an email to you. ' | ||||||
|                   lurl = login_url, |                 'Please follow the instructions in it to activate your account. Once activated, you can login using'), | ||||||
|                   hurl = home_url |             go_back=_('Go back to'), | ||||||
|                   ) |             lurl=login_url, | ||||||
|  |             hurl=home_url | ||||||
|  |         ) | ||||||
|         context['message'] = mark_safe(message) |         context['message'] = mark_safe(message) | ||||||
|         context['section_title'] = _('Sign up') |         context['section_title'] = _('Sign up') | ||||||
|         return context |         return context | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class SignupValidatedView(SignupValidateView): | class SignupValidatedView(SignupValidateView): | ||||||
|     template_name = "hosting/signup_validate.html" |     template_name = "hosting/signup_validate.html" | ||||||
|      | 
 | ||||||
|     def get_context_data(self, **kwargs): |     def get_context_data(self, **kwargs): | ||||||
|         context = super(SignupValidateView, self).get_context_data(**kwargs) |         context = super(SignupValidateView, self).get_context_data(**kwargs) | ||||||
|         validated = CustomUser.validate_url(self.kwargs['validate_slug']) |         validated = CustomUser.validate_url(self.kwargs['validate_slug']) | ||||||
|         login_url = '<a href="' + reverse('hosting:login') + '">' + str(_('login')) +'</a>' |         login_url = '<a href="' + reverse('hosting:login') + '">' + str(_('login')) + '</a>' | ||||||
|         section_title=_('Account activation') |         section_title = _('Account activation') | ||||||
|         if validated: |         if validated: | ||||||
|             message='{account_activation_string} <br /> {login_string} {lurl}.'.format( |             message = '{account_activation_string} <br /> {login_string} {lurl}.'.format( | ||||||
|                              account_activation_string = _("Your account has been activated."), |                 account_activation_string=_("Your account has been activated."), | ||||||
|                              login_string = _("You can now"), |                 login_string=_("You can now"), | ||||||
|                              lurl = login_url) |                 lurl=login_url) | ||||||
|         else: |         else: | ||||||
|             home_url = '<a href="' + reverse('datacenterlight:index') + '">Data Center Light</a>' |             home_url = '<a href="' + reverse('datacenterlight:index') + '">Data Center Light</a>' | ||||||
|             message = '{sorry_message} <br />{go_back_to} {hurl}'.format( |             message = '{sorry_message} <br />{go_back_to} {hurl}'.format( | ||||||
|                     sorry_message = _("Sorry. Your request is invalid."), |                 sorry_message=_("Sorry. Your request is invalid."), | ||||||
|                     go_back_to = _('Go back to'), |                 go_back_to=_('Go back to'), | ||||||
|                     hurl = home_url |                 hurl=home_url | ||||||
|                 ) |             ) | ||||||
|         context['message'] = mark_safe(message) |         context['message'] = mark_safe(message) | ||||||
|         context['section_title'] = section_title |         context['section_title'] = section_title | ||||||
|         return context |         return context | ||||||
|  | @ -351,6 +348,7 @@ class SSHKeyDeleteView(LoginRequiredMixin, DeleteView): | ||||||
| 
 | 
 | ||||||
|         return super(SSHKeyDeleteView, self).delete(request, *args, **kwargs) |         return super(SSHKeyDeleteView, self).delete(request, *args, **kwargs) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class SSHKeyListView(LoginRequiredMixin, ListView): | class SSHKeyListView(LoginRequiredMixin, ListView): | ||||||
|     template_name = "hosting/user_keys.html" |     template_name = "hosting/user_keys.html" | ||||||
|     login_url = reverse_lazy('hosting:login') |     login_url = reverse_lazy('hosting:login') | ||||||
|  | @ -359,7 +357,6 @@ class SSHKeyListView(LoginRequiredMixin, ListView): | ||||||
|     paginate_by = 10 |     paginate_by = 10 | ||||||
|     ordering = '-id' |     ordering = '-id' | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def get_queryset(self): |     def get_queryset(self): | ||||||
|         user = self.request.user |         user = self.request.user | ||||||
|         self.queryset = UserHostingKey.objects.filter(user=user) |         self.queryset = UserHostingKey.objects.filter(user=user) | ||||||
|  | @ -379,7 +376,6 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView): | ||||||
|     context_object_name = "virtual_machine" |     context_object_name = "virtual_machine" | ||||||
|     success_url = reverse_lazy('hosting:ssh_keys') |     success_url = reverse_lazy('hosting:ssh_keys') | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def get_form_kwargs(self): |     def get_form_kwargs(self): | ||||||
|         kwargs = super(SSHKeyCreateView, self).get_form_kwargs() |         kwargs = super(SSHKeyCreateView, self).get_form_kwargs() | ||||||
|         kwargs.update({'request': self.request}) |         kwargs.update({'request': self.request}) | ||||||
|  | @ -476,7 +472,7 @@ class PaymentVMView(LoginRequiredMixin, FormView): | ||||||
|         return context |         return context | ||||||
| 
 | 
 | ||||||
|     def get(self, request, *args, **kwargs): |     def get(self, request, *args, **kwargs): | ||||||
|         if not UserHostingKey.objects.filter( user=self.request.user).exists(): |         if not UserHostingKey.objects.filter(user=self.request.user).exists(): | ||||||
|             messages.success( |             messages.success( | ||||||
|                 request, |                 request, | ||||||
|                 'In order to create a VM, you create/upload your SSH KEY first.' |                 'In order to create a VM, you create/upload your SSH KEY first.' | ||||||
|  | @ -538,7 +534,7 @@ class PaymentVMView(LoginRequiredMixin, FormView): | ||||||
|             manager = OpenNebulaManager(email=owner.email, |             manager = OpenNebulaManager(email=owner.email, | ||||||
|                                         password=owner.password) |                                         password=owner.password) | ||||||
|             # Get user ssh key |             # Get user ssh key | ||||||
|             if not UserHostingKey.objects.filter( user=self.request.user).exists(): |             if not UserHostingKey.objects.filter(user=self.request.user).exists(): | ||||||
|                 context.update({ |                 context.update({ | ||||||
|                     'sshError': 'error', |                     'sshError': 'error', | ||||||
|                     'form': form |                     'form': form | ||||||
|  | @ -546,8 +542,8 @@ class PaymentVMView(LoginRequiredMixin, FormView): | ||||||
|                 return render(request, self.template_name, context) |                 return render(request, self.template_name, context) | ||||||
|             # For now just get first one |             # For now just get first one | ||||||
|             user_key = UserHostingKey.objects.filter( |             user_key = UserHostingKey.objects.filter( | ||||||
|                     user=self.request.user).first() |                 user=self.request.user).first() | ||||||
|              | 
 | ||||||
|             # Create a vm using logged user |             # Create a vm using logged user | ||||||
|             vm_id = manager.create_vm( |             vm_id = manager.create_vm( | ||||||
|                 template_id=vm_template_id, |                 template_id=vm_template_id, | ||||||
|  | @ -565,8 +561,9 @@ class PaymentVMView(LoginRequiredMixin, FormView): | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|             # Create a Hosting Bill |             # Create a Hosting Bill | ||||||
|             bill = HostingBill.create( |             # variable bill is not used | ||||||
|                 customer=customer, billing_address=billing_address) |             # bill = HostingBill.create( | ||||||
|  |             #     customer=customer, billing_address=billing_address) | ||||||
| 
 | 
 | ||||||
|             # Create Billing Address for User if he does not have one |             # Create Billing Address for User if he does not have one | ||||||
|             if not customer.user.billing_addresses.count(): |             if not customer.user.billing_addresses.count(): | ||||||
|  | @ -699,7 +696,7 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View): | ||||||
| 
 | 
 | ||||||
|     def get(self, request, *args, **kwargs): |     def get(self, request, *args, **kwargs): | ||||||
| 
 | 
 | ||||||
|         if not UserHostingKey.objects.filter( user=self.request.user).exists(): |         if not UserHostingKey.objects.filter(user=self.request.user).exists(): | ||||||
|             messages.success( |             messages.success( | ||||||
|                 request, |                 request, | ||||||
|                 'In order to create a VM, you need to create/upload your SSH KEY first.' |                 'In order to create a VM, you need to create/upload your SSH KEY first.' | ||||||
|  | @ -723,7 +720,7 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View): | ||||||
|             ) |             ) | ||||||
|             context = { |             context = { | ||||||
|                 'error': 'connection' |                 'error': 'connection' | ||||||
|             }         |             } | ||||||
| 
 | 
 | ||||||
|         return render(request, self.template_name, context) |         return render(request, self.template_name, context) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -38,26 +38,26 @@ class CustomHTMLCalendar(CustomCalendar): | ||||||
|         self.requested_month = requested_month |         self.requested_month = requested_month | ||||||
|         super(CustomHTMLCalendar, self).__init__() |         super(CustomHTMLCalendar, self).__init__() | ||||||
| 
 | 
 | ||||||
|     def formatday(self, day, weekday, month=None,year=None): |     def formatday(self, day, weekday, month=None, year=None): | ||||||
|         """ |         """ | ||||||
|         Return a day as a table cell. |         Return a day as a table cell. | ||||||
|         """ |         """ | ||||||
| 
 | 
 | ||||||
|         booked = CalendarModel.objects.filter(user_id=self.user.id) |         booked = CalendarModel.objects.filter(user_id=self.user.id) | ||||||
|         is_booked= booked.filter(datebooked=datetime.date(day=day,month=month,year=year)) |         is_booked = booked.filter(datebooked=datetime.date(day=day, month=month, year=year)) | ||||||
| 
 | 
 | ||||||
|         if month < int(self.requested_month): |         if month < int(self.requested_month): | ||||||
|             return '<td class="prev-month %s">%d</td>' % ("selected" if is_booked else "",day) |             return '<td class="prev-month %s">%d</td>' % ("selected" if is_booked else "", day) | ||||||
|         elif month > int(self.requested_month): |         elif month > int(self.requested_month): | ||||||
|             return '<td class="next-month %s">%d</td>' % ("selected" if is_booked else "",day) |             return '<td class="next-month %s">%d</td>' % ("selected" if is_booked else "", day) | ||||||
|         else: |         else: | ||||||
|             return '<td class="%s">%d</td>' % ("selected" if is_booked else "",day) |             return '<td class="%s">%d</td>' % ("selected" if is_booked else "", day) | ||||||
| 
 | 
 | ||||||
|     def formatweek(self, theweek,year): |     def formatweek(self, theweek, year): | ||||||
|         """ |         """ | ||||||
|         Return a complete week as a table row. |         Return a complete week as a table row. | ||||||
|         """ |         """ | ||||||
|         s = ''.join(self.formatday(d, wd, month,year) for (d, wd, month) in theweek) |         s = ''.join(self.formatday(d, wd, month, year) for (d, wd, month) in theweek) | ||||||
|         return '<tr>%s</tr>' % s |         return '<tr>%s</tr>' % s | ||||||
| 
 | 
 | ||||||
|     def formatmonthname(self, theyear, themonth, withyear=True): |     def formatmonthname(self, theyear, themonth, withyear=True): | ||||||
|  | @ -93,7 +93,7 @@ class CustomHTMLCalendar(CustomCalendar): | ||||||
|         a(self.formatweekheader()) |         a(self.formatweekheader()) | ||||||
|         a('\n') |         a('\n') | ||||||
|         for week in self.monthdays2calendar(theyear, themonth): |         for week in self.monthdays2calendar(theyear, themonth): | ||||||
|             a(self.formatweek(week,theyear)) |             a(self.formatweek(week, theyear)) | ||||||
|             a('\n') |             a('\n') | ||||||
|         a('</table>') |         a('</table>') | ||||||
|         a('\n') |         a('\n') | ||||||
|  | @ -102,8 +102,8 @@ class CustomHTMLCalendar(CustomCalendar): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BookCalendar(CustomHTMLCalendar): | class BookCalendar(CustomHTMLCalendar): | ||||||
|     def __init__(self, user,requested_month): |     def __init__(self, user, requested_month): | ||||||
|         self.user=user |         self.user = user | ||||||
|         super(BookCalendar, self).__init__(requested_month) |         super(BookCalendar, self).__init__(requested_month) | ||||||
| 
 | 
 | ||||||
|     def formatmonth(self, year, month): |     def formatmonth(self, year, month): | ||||||
|  | @ -111,7 +111,7 @@ class BookCalendar(CustomHTMLCalendar): | ||||||
|         return super(BookCalendar, self).formatmonth(year, month) |         return super(BookCalendar, self).formatmonth(year, month) | ||||||
| 
 | 
 | ||||||
|     def day_cell(self, cssclass, body): |     def day_cell(self, cssclass, body): | ||||||
|         return '<td>%s</td>' %  body |         return '<td>%s</td>' % body | ||||||
| 
 | 
 | ||||||
|     def formatmonthname(self, theyear, themonth, withyear): |     def formatmonthname(self, theyear, themonth, withyear): | ||||||
|         """ |         """ | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| __author__ = 'tomislav' | __author__ = 'tomislav' | ||||||
| from django import forms | from django import forms | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| from django.contrib.auth import authenticate,login | from django.contrib.auth import authenticate | ||||||
| 
 | 
 | ||||||
| from .models import CreditCards | from .models import CreditCards | ||||||
| 
 | 
 | ||||||
|  | @ -25,7 +25,7 @@ class LoginForm(forms.Form): | ||||||
|             raise forms.ValidationError("Sorry, that login was invalid. Please try again.") |             raise forms.ValidationError("Sorry, that login was invalid. Please try again.") | ||||||
|         return self.cleaned_data |         return self.cleaned_data | ||||||
| 
 | 
 | ||||||
|     def login(self,request): |     def login(self, request): | ||||||
|         username = self.cleaned_data.get('email') |         username = self.cleaned_data.get('email') | ||||||
|         password = self.cleaned_data.get('password') |         password = self.cleaned_data.get('password') | ||||||
|         user = authenticate(email=username, password=password) |         user = authenticate(email=username, password=password) | ||||||
|  | @ -36,6 +36,7 @@ class RegisterForm(SignupFormMixin): | ||||||
|     password = forms.CharField(widget=forms.PasswordInput()) |     password = forms.CharField(widget=forms.PasswordInput()) | ||||||
|     confirm_password = forms.CharField(widget=forms.PasswordInput()) |     confirm_password = forms.CharField(widget=forms.PasswordInput()) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class PaymentForm(forms.ModelForm): | class PaymentForm(forms.ModelForm): | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = CreditCards |         model = CreditCards | ||||||
|  | @ -58,7 +59,7 @@ class PaymentForm(forms.ModelForm): | ||||||
| 
 | 
 | ||||||
|         # if CreditCards.objects.filter(card_number=data.get("card_number")): |         # if CreditCards.objects.filter(card_number=data.get("card_number")): | ||||||
|         #     raise forms.ValidationError({'card_number': _('Credit card is used before.')}) |         #     raise forms.ValidationError({'card_number': _('Credit card is used before.')}) | ||||||
|         return self.cleaned_data |         return data | ||||||
| 
 | 
 | ||||||
|     def save(self, user_id): |     def save(self, user_id): | ||||||
|         self.instance.user_id = user_id |         self.instance.user_id = user_id | ||||||
|  |  | ||||||
|  | @ -1,10 +1,9 @@ | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
| from django.db import models | from django.db import models | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager, AbstractUser, PermissionsMixin | from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin | ||||||
| from django.contrib.auth.hashers import make_password | from django.contrib.auth.hashers import make_password | ||||||
| from django.core.validators import RegexValidator | from django.core.validators import RegexValidator | ||||||
| from django.contrib.auth.models import User |  | ||||||
| from django.contrib.sites.models import Site | from django.contrib.sites.models import Site | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.utils.crypto import get_random_string | from django.utils.crypto import get_random_string | ||||||
|  | @ -15,11 +14,12 @@ from django.core.urlresolvers import reverse | ||||||
| from utils.mailer import BaseEmail | from utils.mailer import BaseEmail | ||||||
| 
 | 
 | ||||||
| REGISTRATION_MESSAGE = {'subject': "Validation mail", | REGISTRATION_MESSAGE = {'subject': "Validation mail", | ||||||
|                         'message': 'Please validate Your account under this link http://localhost:8000/en-us/digitalglarus/login/validate/{}', |                         'message': 'Please validate Your account under this link ' | ||||||
|  |                                    'http://localhost:8000/en-us/digitalglarus/login/validate/{}', | ||||||
|                         'from': 'test@test.com'} |                         'from': 'test@test.com'} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_anonymous_user_instance(User): | def get_anonymous_user_instance(): | ||||||
|     return CustomUser(name='Anonymous', email='anonymous@ungleich.ch', |     return CustomUser(name='Anonymous', email='anonymous@ungleich.ch', | ||||||
|                       validation_slug=make_password(None)) |                       validation_slug=make_password(None)) | ||||||
| 
 | 
 | ||||||
|  | @ -85,16 +85,19 @@ class CustomUser(AbstractBaseUser, PermissionsMixin): | ||||||
|                     dg.send_mail(to=user.email) |                     dg.send_mail(to=user.email) | ||||||
|                 elif app == 'dcl': |                 elif app == 'dcl': | ||||||
|                     dcl_text = settings.DCL_TEXT |                     dcl_text = settings.DCL_TEXT | ||||||
|                     dcl_from_address = settings.DCL_SUPPORT_FROM_ADDRESS |                     # not used | ||||||
|  |                     # dcl_from_address = settings.DCL_SUPPORT_FROM_ADDRESS | ||||||
|                     user.is_active = False |                     user.is_active = False | ||||||
|  | 
 | ||||||
|                     if send_email is True: |                     if send_email is True: | ||||||
|                         email_data = { |                         email_data = { | ||||||
|                             'subject': str(_('Activate your ')) + dcl_text + str(_(' account')), |                             'subject': str(_('Activate your ')) + dcl_text + str(_(' account')), | ||||||
|                             'from_address': settings.DCL_SUPPORT_FROM_ADDRESS, |                             'from_address': settings.DCL_SUPPORT_FROM_ADDRESS, | ||||||
|                             'to': user.email, |                             'to': user.email, | ||||||
|                             'context': {'base_url'  : base_url,  |                             'context': {'base_url': base_url, | ||||||
|                                         'activation_link' : reverse('hosting:validate', kwargs={'validate_slug': user.validation_slug}), |                                         'activation_link': reverse('hosting:validate', | ||||||
|                                         'dcl_text' : dcl_text |                                                                    kwargs={'validate_slug': user.validation_slug}), | ||||||
|  |                                         'dcl_text': dcl_text | ||||||
|                                         }, |                                         }, | ||||||
|                             'template_name': 'user_activation', |                             'template_name': 'user_activation', | ||||||
|                             'template_path': 'datacenterlight/emails/' |                             'template_path': 'datacenterlight/emails/' | ||||||
|  | @ -188,7 +191,7 @@ class StripeCustomer(models.Model): | ||||||
|             if stripe_data.get('response_object'): |             if stripe_data.get('response_object'): | ||||||
|                 stripe_cus_id = stripe_data.get('response_object').get('id') |                 stripe_cus_id = stripe_data.get('response_object').get('id') | ||||||
| 
 | 
 | ||||||
|                 stripe_customer = StripeCustomer.objects.\ |                 stripe_customer = StripeCustomer.objects. \ | ||||||
|                     create(user=user, stripe_id=stripe_cus_id) |                     create(user=user, stripe_id=stripe_cus_id) | ||||||
| 
 | 
 | ||||||
|                 return stripe_customer |                 return stripe_customer | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ stripe.api_key = settings.STRIPE_API_PRIVATE_KEY | ||||||
| 
 | 
 | ||||||
| class StripePayment(object): | class StripePayment(object): | ||||||
|     @classmethod |     @classmethod | ||||||
|     def make_payment(cls,user,amount,token,time): |     def make_payment(cls, user, amount, token, time): | ||||||
|         try: |         try: | ||||||
|             print(amount) |             print(amount) | ||||||
|             print(amount) |             print(amount) | ||||||
|  | @ -19,7 +19,7 @@ class StripePayment(object): | ||||||
|                 source=token, |                 source=token, | ||||||
|                 description=settings.STRIPE_DESCRIPTION_ON_PAYMENT |                 description=settings.STRIPE_DESCRIPTION_ON_PAYMENT | ||||||
|             ) |             ) | ||||||
|             if charge['status'] =='succeeded': |             if charge['status'] == 'succeeded': | ||||||
|                 obj = CreditCards.objects.filter(user_id=user.id).first() |                 obj = CreditCards.objects.filter(user_id=user.id).first() | ||||||
|                 obj.payment_type = time |                 obj.payment_type = time | ||||||
|                 obj.save() |                 obj.save() | ||||||
|  | @ -42,7 +42,7 @@ class StripePayment(object): | ||||||
|             return "Currently its not possible to make payments." |             return "Currently its not possible to make payments." | ||||||
|         except stripe.error.StripeError as e: |         except stripe.error.StripeError as e: | ||||||
|             return "Currently its not possible to make payments." |             return "Currently its not possible to make payments." | ||||||
|             #maybe send email |             # maybe send email | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|             return "Currently its not possible to make payments." |             return "Currently its not possible to make payments." | ||||||
|             #maybe send email |             # maybe send email | ||||||
|  |  | ||||||
|  | @ -26,6 +26,4 @@ class LoginTestCase(TestCase): | ||||||
|         # check fail login |         # check fail login | ||||||
| 
 | 
 | ||||||
|         res4 = self.client.post(url, data={'email': 'test@gmail.com', 'password': 'falsepassword'}) |         res4 = self.client.post(url, data={'email': 'test@gmail.com', 'password': 'falsepassword'}) | ||||||
|         self.assertContains(res4,'Sorry, that login was invalid.',1,200) |         self.assertContains(res4, 'Sorry, that login was invalid.', 1, 200) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ urlpatterns = ( | ||||||
|     url(r"^$", views.LoginRegistrationView.as_view(), name='login_glarus'), |     url(r"^$", views.LoginRegistrationView.as_view(), name='login_glarus'), | ||||||
|     url(r"^validate/(?P<validate_slug>.*)/$", views.validate_email), |     url(r"^validate/(?P<validate_slug>.*)/$", views.validate_email), | ||||||
|     url(r"^membership/$", login_required(views.MembershipView.as_view()), name='membership'), |     url(r"^membership/$", login_required(views.MembershipView.as_view()), name='membership'), | ||||||
|     url(r'logout/?$',views.logout_glarus,name='logout_glarus'), |     url(r'logout/?$', views.logout_glarus, name='logout_glarus'), | ||||||
|     url(r"^buy/(?P<time>\w+)/$", login_required(views.CreditCardView.as_view()), name='payment'), |     url(r"^buy/(?P<time>\w+)/$", login_required(views.CreditCardView.as_view()), name='payment'), | ||||||
|     url(r'^buy/(?P<time>\w+)/reset',login_required(views.reset),name='reset') |     url(r'^buy/(?P<time>\w+)/reset', login_required(views.reset), name='reset') | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | @ -8,22 +8,23 @@ from django.contrib.auth import logout | ||||||
| from django.http import HttpResponseRedirect | from django.http import HttpResponseRedirect | ||||||
| from django.contrib.auth import login | from django.contrib.auth import login | ||||||
| 
 | 
 | ||||||
| from .models import CustomUser,StripeCustomer | from .models import CustomUser, StripeCustomer | ||||||
| from .forms import LoginForm, RegisterForm, PaymentForm | from .forms import LoginForm, RegisterForm, PaymentForm | ||||||
| from utils.stripe_utils import StripeUtils | from utils.stripe_utils import StripeUtils | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| def validate_email(request, validate_slug): | def validate_email(request, validate_slug): | ||||||
|     validated = CustomUser.validate_url(validate_slug) |     validated = CustomUser.validate_url(validate_slug) | ||||||
|     if validated: |     if validated: | ||||||
|         return render(request, 'templates/validated_email.html',{'msg':True}) |         return render(request, 'templates/validated_email.html', {'msg': True}) | ||||||
|     else: |     else: | ||||||
|         return render(request, 'templates/error.html',{'msg':'Validation failed.'}) |         return render(request, 'templates/error.html', {'msg': 'Validation failed.'}) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def reset(request, time): | ||||||
|  |     request.session['next'] = 0 | ||||||
|  |     return redirect('payment', time=time) | ||||||
| 
 | 
 | ||||||
| def reset(request,time): |  | ||||||
|     request.session['next']=0 |  | ||||||
|     return redirect('payment',time=time) |  | ||||||
| 
 | 
 | ||||||
| class CreditCardView(View): | class CreditCardView(View): | ||||||
|     def _get_context(self, request, time): |     def _get_context(self, request, time): | ||||||
|  | @ -42,20 +43,20 @@ class CreditCardView(View): | ||||||
|         context['form'] = PaymentForm() |         context['form'] = PaymentForm() | ||||||
|         return context |         return context | ||||||
| 
 | 
 | ||||||
|     @cache_control(no_cache=True,must_revalidate=True) |     @cache_control(no_cache=True, must_revalidate=True) | ||||||
|     def get(self, request, time=None): |     def get(self, request, time=None): | ||||||
|         context = self._get_context(request, time) |         context = self._get_context(request, time) | ||||||
|         next = request.session.get('next') |         next = request.session.get('next') | ||||||
|         if next == 1 or next ==0: |         if next == 1 or next == 0: | ||||||
|             template = 'templates/creditcard.html' |             template = 'templates/creditcard.html' | ||||||
|             request.session['next'] +=1 |             request.session['next'] += 1 | ||||||
|         elif next == 2: |         elif next == 2: | ||||||
|             customer = StripeCustomer.get_or_create(email=request.user.email,token=request.session['token']) |             customer = StripeCustomer.get_or_create(email=request.user.email, token=request.session['token']) | ||||||
|             stripe_utils = StripeUtils() |             stripe_utils = StripeUtils() | ||||||
|             charge = stripe_utils.make_charge(request.session['amount'],customer=customer.stripe_id) |             charge = stripe_utils.make_charge(request.session['amount'], customer=customer.stripe_id) | ||||||
|             template = 'templates/validated.html' |             template = 'templates/validated.html' | ||||||
|             resp = charge.get('response_object')             |             resp = charge.get('response_object') | ||||||
|             context['msg'] = resp.get('status',None)  |             context['msg'] = resp.get('status', None) | ||||||
|             request.session['next'] = None |             request.session['next'] = None | ||||||
|         return render(request, template, context) |         return render(request, template, context) | ||||||
| 
 | 
 | ||||||
|  | @ -64,11 +65,11 @@ class CreditCardView(View): | ||||||
|         stripe_token = request.POST['stripeToken'] |         stripe_token = request.POST['stripeToken'] | ||||||
| 
 | 
 | ||||||
|         if form.is_valid(): |         if form.is_valid(): | ||||||
|             ret = form.save(request.user) |             form.save(request.user) | ||||||
|             amount = 35 if time == 'month' else 360 |             amount = 35 if time == 'month' else 360 | ||||||
|             request.session['token'] = stripe_token |             request.session['token'] = stripe_token | ||||||
|             request.session['amount'] = amount |             request.session['amount'] = amount | ||||||
|             request.session['next'] +=1 |             request.session['next'] += 1 | ||||||
|             return render(request, 'templates/confirm.html', |             return render(request, 'templates/confirm.html', | ||||||
|                           context={'name': request.user.name, 'email': request.user.email}) |                           context={'name': request.user.name, 'email': request.user.email}) | ||||||
|         else: |         else: | ||||||
|  | @ -121,13 +122,14 @@ class LoginRegistrationView(View): | ||||||
| 
 | 
 | ||||||
| class MembershipView(View): | class MembershipView(View): | ||||||
|     def get(self, request): |     def get(self, request): | ||||||
|         #if the user has payed already |         # if the user has payed already | ||||||
|         member_payed = request.user.creditcards_set.filter(Q(payment_type='month') | Q(payment_type='year')) |         member_payed = request.user.creditcards_set.filter(Q(payment_type='month') | Q(payment_type='year')) | ||||||
|         if member_payed: |         if member_payed: | ||||||
|             return redirect('/') |             return redirect('/') | ||||||
|         request.session['next'] = 0 |         request.session['next'] = 0 | ||||||
|         language = get_language() |         language = get_language() | ||||||
|         return render(request, 'templates/membership.html',context={'language_code':language}) |         return render(request, 'templates/membership.html', context={'language_code': language}) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| def logout_glarus(request): | def logout_glarus(request): | ||||||
|     logout(request) |     logout(request) | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| from django.test import TestCase | # from django.test import TestCase | ||||||
| 
 | 
 | ||||||
| # Create your tests here. | # Create your tests here. | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| from django.contrib import admin | # from django.contrib import admin | ||||||
| 
 | 
 | ||||||
| # Register your models here. | # Register your models here. | ||||||
|  |  | ||||||
|  | @ -1,9 +1,10 @@ | ||||||
| 
 |  | ||||||
| class KeyExistsError(Exception): | class KeyExistsError(Exception): | ||||||
|     pass |     pass | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class UserExistsError(Exception): | class UserExistsError(Exception): | ||||||
|     pass |     pass | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class UserCredentialError(Exception): | class UserCredentialError(Exception): | ||||||
|     pass |     pass | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ from oca.pool import WrongNameError, WrongIdError | ||||||
| from oca.exceptions import OpenNebulaException | from oca.exceptions import OpenNebulaException | ||||||
| 
 | 
 | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.utils.functional import cached_property |  | ||||||
| 
 | 
 | ||||||
| from utils.models import CustomUser | from utils.models import CustomUser | ||||||
| from .exceptions import KeyExistsError, UserExistsError, UserCredentialError | from .exceptions import KeyExistsError, UserExistsError, UserCredentialError | ||||||
|  | @ -38,9 +37,10 @@ class OpenNebulaManager(): | ||||||
|             ) |             ) | ||||||
|         except: |         except: | ||||||
|             pass |             pass | ||||||
|  | 
 | ||||||
|     def _get_client(self, user): |     def _get_client(self, user): | ||||||
|         """Get a opennebula client object for a CustomUser object  |         """Get a opennebula client object for a CustomUser object | ||||||
|          | 
 | ||||||
|         Args: |         Args: | ||||||
|             user (CustomUser): dynamicweb CustomUser object |             user (CustomUser): dynamicweb CustomUser object | ||||||
| 
 | 
 | ||||||
|  | @ -49,7 +49,7 @@ class OpenNebulaManager(): | ||||||
| 
 | 
 | ||||||
|         Raise: |         Raise: | ||||||
|             ConnectionError: If the connection to the opennebula server can't be |             ConnectionError: If the connection to the opennebula server can't be | ||||||
|                 established  |                 established | ||||||
|         """ |         """ | ||||||
|         return oca.Client("{0}:{1}".format( |         return oca.Client("{0}:{1}".format( | ||||||
|             user.email, |             user.email, | ||||||
|  | @ -74,8 +74,8 @@ class OpenNebulaManager(): | ||||||
|         )) |         )) | ||||||
| 
 | 
 | ||||||
|     def _get_user(self, user): |     def _get_user(self, user): | ||||||
|         """Get the corresponding opennebula user for a CustomUser object  |         """Get the corresponding opennebula user for a CustomUser object | ||||||
|          | 
 | ||||||
|         Args: |         Args: | ||||||
|             user (CustomUser): dynamicweb CustomUser object |             user (CustomUser): dynamicweb CustomUser object | ||||||
| 
 | 
 | ||||||
|  | @ -85,7 +85,7 @@ class OpenNebulaManager(): | ||||||
|         Raise: |         Raise: | ||||||
|             WrongNameError: If no openebula user with this credentials exists |             WrongNameError: If no openebula user with this credentials exists | ||||||
|             ConnectionError: If the connection to the opennebula server can't be |             ConnectionError: If the connection to the opennebula server can't be | ||||||
|                 established  |                 established | ||||||
|         """ |         """ | ||||||
|         user_pool = self._get_user_pool() |         user_pool = self._get_user_pool() | ||||||
|         return user_pool.get_by_name(user.email) |         return user_pool.get_by_name(user.email) | ||||||
|  | @ -93,16 +93,16 @@ class OpenNebulaManager(): | ||||||
|     def create_user(self, user: CustomUser): |     def create_user(self, user: CustomUser): | ||||||
|         """Create a new opennebula user or a corresponding CustomUser object |         """Create a new opennebula user or a corresponding CustomUser object | ||||||
| 
 | 
 | ||||||
|          | 
 | ||||||
|         Args: |         Args: | ||||||
|             user (CustomUser): dynamicweb CustomUser object |             user (CustomUser): dynamicweb CustomUser object | ||||||
| 
 | 
 | ||||||
|         Returns: |         Returns: | ||||||
|             int: Return the opennebula user id |             int: Return the opennebula user id | ||||||
|              | 
 | ||||||
|         Raises: |         Raises: | ||||||
|             ConnectionError: If the connection to the opennebula server can't be |             ConnectionError: If the connection to the opennebula server can't be | ||||||
|                 established  |                 established | ||||||
|             UserExistsError: If a user with this credeintals already exits on the |             UserExistsError: If a user with this credeintals already exits on the | ||||||
|                 server |                 server | ||||||
|             UserCredentialError: If a user with this email exists but the |             UserCredentialError: If a user with this email exists but the | ||||||
|  | @ -111,7 +111,7 @@ class OpenNebulaManager(): | ||||||
|         """ |         """ | ||||||
|         try: |         try: | ||||||
|             self._get_user(user) |             self._get_user(user) | ||||||
|             try:  |             try: | ||||||
|                 self._get_client(self, user) |                 self._get_client(self, user) | ||||||
|                 logger.debug('User already exists') |                 logger.debug('User already exists') | ||||||
|                 raise UserExistsError() |                 raise UserExistsError() | ||||||
|  | @ -122,19 +122,18 @@ class OpenNebulaManager(): | ||||||
| 
 | 
 | ||||||
|         except WrongNameError: |         except WrongNameError: | ||||||
|             user_id = self.oneadmin_client.call(oca.User.METHODS['allocate'], |             user_id = self.oneadmin_client.call(oca.User.METHODS['allocate'], | ||||||
|                 user.email, user.password, 'core') |                                                 user.email, user.password, 'core') | ||||||
|             logger.debug('Created a user for CustomObject: {user} with user id = {u_id}', |             logger.debug('Created a user for CustomObject: {user} with user id = {u_id}', | ||||||
|                 user=user, |                          user=user, | ||||||
|                 u_id=user_id |                          u_id=user_id | ||||||
|             ) |                          ) | ||||||
|             return user_id  |             return user_id | ||||||
|         except ConnectionRefusedError: |         except ConnectionRefusedError: | ||||||
|             logger.error('Could not connect to host: {host} via protocol {protocol}'.format( |             logger.error('Could not connect to host: {host} via protocol {protocol}'.format( | ||||||
|                 host=settings.OPENNEBULA_DOMAIN, |                 host=settings.OPENNEBULA_DOMAIN, | ||||||
|                 protocol=settings.OPENNEBULA_PROTOCOL) |                 protocol=settings.OPENNEBULA_PROTOCOL) | ||||||
|             ) |             ) | ||||||
|             raise ConnectionRefusedError |             raise ConnectionRefusedError | ||||||
|          |  | ||||||
| 
 | 
 | ||||||
|     def _get_or_create_user(self, email, password): |     def _get_or_create_user(self, email, password): | ||||||
|         try: |         try: | ||||||
|  | @ -166,7 +165,7 @@ class OpenNebulaManager(): | ||||||
|                 host=settings.OPENNEBULA_DOMAIN, |                 host=settings.OPENNEBULA_DOMAIN, | ||||||
|                 protocol=settings.OPENNEBULA_PROTOCOL) |                 protocol=settings.OPENNEBULA_PROTOCOL) | ||||||
|             ) |             ) | ||||||
|             raise  |             raise | ||||||
|         return user_pool |         return user_pool | ||||||
| 
 | 
 | ||||||
|     def _get_vm_pool(self): |     def _get_vm_pool(self): | ||||||
|  | @ -209,36 +208,6 @@ class OpenNebulaManager(): | ||||||
|         except: |         except: | ||||||
|             raise ConnectionRefusedError |             raise ConnectionRefusedError | ||||||
| 
 | 
 | ||||||
|     def create_template(self, name, cores, memory, disk_size, core_price, memory_price, |  | ||||||
|                         disk_size_price, ssh=''): |  | ||||||
|         """Create and add a new template to opennebula. |  | ||||||
|         :param name:      A string representation describing the template. |  | ||||||
|                           Used as label in view. |  | ||||||
|         :param cores:     Amount of virtual cpu cores for the VM. |  | ||||||
|         :param memory:  Amount of RAM for the VM (GB) |  | ||||||
|         :param disk_size:    Amount of disk space for VM (GB) |  | ||||||
|         :param core_price:     Price of virtual cpu for the VM per core. |  | ||||||
|         :param memory_price:  Price of RAM for the VM per GB |  | ||||||
|         :param disk_size_price:    Price of disk space for VM per GB |  | ||||||
|         :param ssh: User public ssh key |  | ||||||
|         """ |  | ||||||
| 
 |  | ||||||
|         template_id = oca.VmTemplate.allocate( |  | ||||||
|             self.oneadmin_client, |  | ||||||
|             template_string_formatter.format( |  | ||||||
|                 name=name, |  | ||||||
|                 vcpu=cores, |  | ||||||
|                 cpu=0.1 * cores, |  | ||||||
|                 size=1024 * disk_size, |  | ||||||
|                 memory=1024 * memory, |  | ||||||
|                 # * 10 because we set cpu to *0.1 |  | ||||||
|                 cpu_cost=10 * core_price, |  | ||||||
|                 memory_cost=memory_price, |  | ||||||
|                 disk_cost=disk_size_price, |  | ||||||
|                 ssh=ssh |  | ||||||
|             ) |  | ||||||
|         ) |  | ||||||
| 
 |  | ||||||
|     def create_vm(self, template_id, specs, ssh_key=None, vm_name=None): |     def create_vm(self, template_id, specs, ssh_key=None, vm_name=None): | ||||||
| 
 | 
 | ||||||
|         template = self.get_template(template_id) |         template = self.get_template(template_id) | ||||||
|  | @ -306,7 +275,7 @@ class OpenNebulaManager(): | ||||||
|             'release', |             'release', | ||||||
|             vm_id |             vm_id | ||||||
|         ) |         ) | ||||||
|          | 
 | ||||||
|         if vm_name is not None: |         if vm_name is not None: | ||||||
|             self.oneadmin_client.call( |             self.oneadmin_client.call( | ||||||
|                 'vm.rename', |                 'vm.rename', | ||||||
|  | @ -437,30 +406,30 @@ class OpenNebulaManager(): | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def add_public_key(self, user, public_key='', merge=False): |     def add_public_key(self, user, public_key='', merge=False): | ||||||
|         """  |         """ | ||||||
| 
 | 
 | ||||||
|         Args:  |         Args: | ||||||
|             user (CustomUser): Dynamicweb user  |             user (CustomUser): Dynamicweb user | ||||||
|             public_key (string): Public key to add to the user |             public_key (string): Public key to add to the user | ||||||
|             merge (bool): Optional if True the new public key replaces the old |             merge (bool): Optional if True the new public key replaces the old | ||||||
| 
 | 
 | ||||||
|         Raises: |         Raises: | ||||||
|             KeyExistsError: If replace is False and the user already has a |             KeyExistsError: If replace is False and the user already has a | ||||||
|                 public key  |                 public key | ||||||
|             WrongNameError: If no openebula user with this credentials exists |             WrongNameError: If no openebula user with this credentials exists | ||||||
|             ConnectionError: If the connection to the opennebula server can't be |             ConnectionError: If the connection to the opennebula server can't be | ||||||
|                 established  |                 established | ||||||
| 
 | 
 | ||||||
|         Returns: |         Returns: | ||||||
|             True if public_key was added |             True if public_key was added | ||||||
| 
 | 
 | ||||||
|         """ |         """ | ||||||
|         # TODO: Check if we can remove this first try because we basically just |         # TODO: Check if we can remove this first try because we basically just | ||||||
|         # raise the possible Errors  |         # raise the possible Errors | ||||||
|         try: |         try: | ||||||
|             open_user = self._get_user(user) |             open_user = self._get_user(user) | ||||||
|             try: |             try: | ||||||
|                 old_key = open_user.template.ssh_public_key  |                 old_key = open_user.template.ssh_public_key | ||||||
|                 if not merge: |                 if not merge: | ||||||
|                     raise KeyExistsError() |                     raise KeyExistsError() | ||||||
|                 public_key += '\n{key}'.format(key=old_key) |                 public_key += '\n{key}'.format(key=old_key) | ||||||
|  | @ -468,7 +437,8 @@ class OpenNebulaManager(): | ||||||
|             except AttributeError: |             except AttributeError: | ||||||
|                 pass |                 pass | ||||||
|             self.oneadmin_client.call('user.update', open_user.id, |             self.oneadmin_client.call('user.update', open_user.id, | ||||||
|                          '<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>'.format(key=public_key)) |                                       '<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>' | ||||||
|  |                                       .format(key=public_key)) | ||||||
|             return True |             return True | ||||||
|         except WrongNameError: |         except WrongNameError: | ||||||
|             raise |             raise | ||||||
|  | @ -477,18 +447,18 @@ class OpenNebulaManager(): | ||||||
|             raise |             raise | ||||||
| 
 | 
 | ||||||
|     def remove_public_key(self, user, public_key=''): |     def remove_public_key(self, user, public_key=''): | ||||||
|         """  |         """ | ||||||
| 
 | 
 | ||||||
|         Args:  |         Args: | ||||||
|             user (CustomUser): Dynamicweb user  |             user (CustomUser): Dynamicweb user | ||||||
|             public_key (string): Public key to be removed to the user |             public_key (string): Public key to be removed to the user | ||||||
| 
 | 
 | ||||||
|         Raises: |         Raises: | ||||||
|             KeyDoesNotExistsError: If replace is False and the user already has a |             KeyDoesNotExistsError: If replace is False and the user already has a | ||||||
|                 public key  |                 public key | ||||||
|             WrongNameError: If no openebula user with this credentials exists |             WrongNameError: If no openebula user with this credentials exists | ||||||
|             ConnectionError: If the connection to the opennebula server can't be |             ConnectionError: If the connection to the opennebula server can't be | ||||||
|                 established  |                 established | ||||||
| 
 | 
 | ||||||
|         Returns: |         Returns: | ||||||
|             True if public_key was removed |             True if public_key was removed | ||||||
|  | @ -498,21 +468,22 @@ class OpenNebulaManager(): | ||||||
|         try: |         try: | ||||||
|             open_user = self._get_user(user) |             open_user = self._get_user(user) | ||||||
|             try: |             try: | ||||||
|                 old_key = open_user.template.ssh_public_key  |                 old_key = open_user.template.ssh_public_key | ||||||
|                 if public_key not in old_key: |                 if public_key not in old_key: | ||||||
|                     return False |                     return False | ||||||
|                     # raise KeyDoesNotExistsError() |                     # raise KeyDoesNotExistsError() | ||||||
|                 if '\n{}'.format(public_key) in old_key: |                 if '\n{}'.format(public_key) in old_key: | ||||||
|                     public_key = old_key.replace('\n{}'.format(public_key), '') |                     public_key = old_key.replace('\n{}'.format(public_key), '') | ||||||
|                 else:  |                 else: | ||||||
|                     public_key = old_key.replace(public_key, '') |                     public_key = old_key.replace(public_key, '') | ||||||
| 
 | 
 | ||||||
|             except AttributeError: |             except AttributeError: | ||||||
|                 return False |                 return False | ||||||
|                 #raise KeyDoesNotExistsError() |                 # raise KeyDoesNotExistsError() | ||||||
|                  | 
 | ||||||
|             self.oneadmin_client.call('user.update', open_user.id, |             self.oneadmin_client.call('user.update', open_user.id, | ||||||
|                          '<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>'.format(key=public_key)) |                                       '<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>' | ||||||
|  |                                       .format(key=public_key)) | ||||||
|             return True |             return True | ||||||
|         except WrongNameError: |         except WrongNameError: | ||||||
|             raise |             raise | ||||||
|  |  | ||||||
|  | @ -1,20 +1,19 @@ | ||||||
| import oca |  | ||||||
| import ipaddress | import ipaddress | ||||||
| 
 | 
 | ||||||
| from rest_framework import serializers | from rest_framework import serializers | ||||||
| 
 | 
 | ||||||
| from oca import OpenNebulaException | from oca import OpenNebulaException | ||||||
| from oca.template import VmTemplate |  | ||||||
| 
 | 
 | ||||||
| from .models import OpenNebulaManager | from .models import OpenNebulaManager | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class VirtualMachineTemplateSerializer(serializers.Serializer): | class VirtualMachineTemplateSerializer(serializers.Serializer): | ||||||
|     """Serializer to map the virtual machine template instance into JSON format.""" |     """Serializer to map the virtual machine template instance into JSON format.""" | ||||||
|     id          = serializers.IntegerField(read_only=True) |     id = serializers.IntegerField(read_only=True) | ||||||
|     name        = serializers.SerializerMethodField() |     name = serializers.SerializerMethodField() | ||||||
|     cores       = serializers.SerializerMethodField()  |     cores = serializers.SerializerMethodField() | ||||||
|     disk_size   = serializers.SerializerMethodField() |     disk_size = serializers.SerializerMethodField() | ||||||
|     memory      = serializers.SerializerMethodField() |     memory = serializers.SerializerMethodField() | ||||||
| 
 | 
 | ||||||
|     def get_cores(self, obj): |     def get_cores(self, obj): | ||||||
|         if hasattr(obj.template, 'vcpu'): |         if hasattr(obj.template, 'vcpu'): | ||||||
|  | @ -28,7 +27,7 @@ class VirtualMachineTemplateSerializer(serializers.Serializer): | ||||||
|         try: |         try: | ||||||
|             for disk in template.disks: |             for disk in template.disks: | ||||||
|                 disk_size += int(disk.size) |                 disk_size += int(disk.size) | ||||||
|             return disk_size / 1024  |             return disk_size / 1024 | ||||||
|         except: |         except: | ||||||
|             return 0 |             return 0 | ||||||
| 
 | 
 | ||||||
|  | @ -39,30 +38,28 @@ class VirtualMachineTemplateSerializer(serializers.Serializer): | ||||||
|         return obj.name.strip('public-') |         return obj.name.strip('public-') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| class VirtualMachineSerializer(serializers.Serializer): | class VirtualMachineSerializer(serializers.Serializer): | ||||||
|     """Serializer to map the virtual machine instance into JSON format.""" |     """Serializer to map the virtual machine instance into JSON format.""" | ||||||
| 
 | 
 | ||||||
|     name = serializers.SerializerMethodField() |     name = serializers.SerializerMethodField() | ||||||
|     cores       = serializers.IntegerField(source='template.vcpu')  |     cores = serializers.IntegerField(source='template.vcpu') | ||||||
|     disk        = serializers.IntegerField(write_only=True) |     disk = serializers.IntegerField(write_only=True) | ||||||
|     set_memory      = serializers.IntegerField(write_only=True, label='Memory') |     set_memory = serializers.IntegerField(write_only=True, label='Memory') | ||||||
|     memory      = serializers.SerializerMethodField() |     memory = serializers.SerializerMethodField() | ||||||
|      |  | ||||||
| 
 | 
 | ||||||
|     disk_size   = serializers.SerializerMethodField() |     disk_size = serializers.SerializerMethodField() | ||||||
|     ipv4          = serializers.SerializerMethodField() |     ipv4 = serializers.SerializerMethodField() | ||||||
|     ipv6          = serializers.SerializerMethodField() |     ipv6 = serializers.SerializerMethodField() | ||||||
|     vm_id       = serializers.IntegerField(read_only=True, source='id') |     vm_id = serializers.IntegerField(read_only=True, source='id') | ||||||
|     state       = serializers.CharField(read_only=True, source='str_state') |     state = serializers.CharField(read_only=True, source='str_state') | ||||||
|     price       = serializers.SerializerMethodField() |     price = serializers.SerializerMethodField() | ||||||
|     ssh_key     = serializers.CharField(write_only=True) |     ssh_key = serializers.CharField(write_only=True) | ||||||
|     configuration = serializers.SerializerMethodField() |     configuration = serializers.SerializerMethodField() | ||||||
| 
 | 
 | ||||||
|     template_id = serializers.ChoiceField( |     template_id = serializers.ChoiceField( | ||||||
|                 choices=[(key.id, key.name) for key in |                 choices=[(key.id, key.name) for key in | ||||||
|                         OpenNebulaManager().try_get_templates() |                          OpenNebulaManager().try_get_templates() | ||||||
|                         ], |                          ], | ||||||
|                 source='template.template_id', |                 source='template.template_id', | ||||||
|                 write_only=True, |                 write_only=True, | ||||||
|                 default=[] |                 default=[] | ||||||
|  | @ -77,12 +74,11 @@ class VirtualMachineSerializer(serializers.Serializer): | ||||||
| 
 | 
 | ||||||
|         template_id = validated_data['template']['template_id'] |         template_id = validated_data['template']['template_id'] | ||||||
|         specs = { |         specs = { | ||||||
|                     'cpu' : cores, |                     'cpu': cores, | ||||||
|                     'disk_size' : disk, |                     'disk_size': disk, | ||||||
|                     'memory' : memory, |                     'memory': memory, | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         try: |         try: | ||||||
|             manager = OpenNebulaManager(email=owner.email, |             manager = OpenNebulaManager(email=owner.email, | ||||||
|                                         password=owner.password, |                                         password=owner.password, | ||||||
|  | @ -92,7 +88,7 @@ class VirtualMachineSerializer(serializers.Serializer): | ||||||
|                                               specs=specs) |                                               specs=specs) | ||||||
|         except OpenNebulaException as err: |         except OpenNebulaException as err: | ||||||
|             raise serializers.ValidationError("OpenNebulaException occured. {0}".format(err)) |             raise serializers.ValidationError("OpenNebulaException occured. {0}".format(err)) | ||||||
|          | 
 | ||||||
|         return manager.get_vm(opennebula_id) |         return manager.get_vm(opennebula_id) | ||||||
| 
 | 
 | ||||||
|     def get_memory(self, obj): |     def get_memory(self, obj): | ||||||
|  | @ -112,6 +108,7 @@ class VirtualMachineSerializer(serializers.Serializer): | ||||||
|         for disk in template.disks: |         for disk in template.disks: | ||||||
|             price += int(disk.size)/1024 * 0.6 |             price += int(disk.size)/1024 * 0.6 | ||||||
|         return price |         return price | ||||||
|  | 
 | ||||||
|     def get_configuration(self, obj): |     def get_configuration(self, obj): | ||||||
|         template_id = obj.template.template_id |         template_id = obj.template.template_id | ||||||
|         template = OpenNebulaManager().get_template(template_id) |         template = OpenNebulaManager().get_template(template_id) | ||||||
|  | @ -123,7 +120,7 @@ class VirtualMachineSerializer(serializers.Serializer): | ||||||
|             return str(v4_from_mac(nic.mac)) |             return str(v4_from_mac(nic.mac)) | ||||||
|         else: |         else: | ||||||
|             return '-' |             return '-' | ||||||
|          | 
 | ||||||
|     def get_ipv6(self, obj): |     def get_ipv6(self, obj): | ||||||
|         nic = obj.template.nics[0] |         nic = obj.template.nics[0] | ||||||
|         return nic.ip6_global |         return nic.ip6_global | ||||||
|  | @ -131,12 +128,15 @@ class VirtualMachineSerializer(serializers.Serializer): | ||||||
|     def get_name(self, obj): |     def get_name(self, obj): | ||||||
|         return obj.name.strip('public-') |         return obj.name.strip('public-') | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| def hexstr2int(string): | def hexstr2int(string): | ||||||
|     return int(string.replace(':', ''), 16) |     return int(string.replace(':', ''), 16) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| FIRST_MAC = hexstr2int('02:00:b3:39:79:4d') | FIRST_MAC = hexstr2int('02:00:b3:39:79:4d') | ||||||
| FIRST_V4  = ipaddress.ip_address('185.203.112.2') | FIRST_V4 = ipaddress.ip_address('185.203.112.2') | ||||||
| COUNT     = 1000 | COUNT = 1000 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| def v4_from_mac(mac): | def v4_from_mac(mac): | ||||||
|     """Calculates the IPv4 address from a MAC address. |     """Calculates the IPv4 address from a MAC address. | ||||||
|  | @ -146,5 +146,6 @@ def v4_from_mac(mac): | ||||||
|     """ |     """ | ||||||
|     return FIRST_V4 + (hexstr2int(mac) - FIRST_MAC) |     return FIRST_V4 + (hexstr2int(mac) - FIRST_MAC) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| def is_in_v4_range(mac): | def is_in_v4_range(mac): | ||||||
|     return FIRST_MAC <= hexstr2int(mac) < FIRST_MAC + 1000 |     return FIRST_MAC <= hexstr2int(mac) < FIRST_MAC + 1000 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,3 @@ | ||||||
| import socket |  | ||||||
| import random | import random | ||||||
| import string | import string | ||||||
| 
 | 
 | ||||||
|  | @ -8,32 +7,30 @@ from .models import OpenNebulaManager | ||||||
| from .serializers import VirtualMachineSerializer | from .serializers import VirtualMachineSerializer | ||||||
| from utils.models import CustomUser | from utils.models import CustomUser | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class OpenNebulaManagerTestCases(TestCase): | class OpenNebulaManagerTestCases(TestCase): | ||||||
|     """This class defines the test suite for the opennebula manager model.""" |     """This class defines the test suite for the opennebula manager model.""" | ||||||
| 
 | 
 | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         """Define the test client and other test variables.""" |         """Define the test client and other test variables.""" | ||||||
|          |  | ||||||
| 
 |  | ||||||
|         self.email = '{}@ungleich.ch'.format(''.join(random.choices(string.ascii_uppercase, k=10))) |         self.email = '{}@ungleich.ch'.format(''.join(random.choices(string.ascii_uppercase, k=10))) | ||||||
|         self.password = ''.join(random.choices(string.ascii_uppercase + string.digits, k=20))  |         self.password = ''.join(random.choices(string.ascii_uppercase + string.digits, k=20)) | ||||||
| 
 | 
 | ||||||
|         self.user = CustomUser.objects.create(name='test', email=self.email, |         self.user = CustomUser.objects.create(name='test', email=self.email, | ||||||
|                 password=self.password)  |                                               password=self.password) | ||||||
| 
 | 
 | ||||||
|         self.vm_specs = {} |         self.vm_specs = {} | ||||||
|         self.vm_specs['cpu'] = 1 |         self.vm_specs['cpu'] = 1 | ||||||
|         self.vm_specs['memory'] = 2 |         self.vm_specs['memory'] = 2 | ||||||
|         self.vm_specs['disk_size'] = 10 |         self.vm_specs['disk_size'] = 10 | ||||||
| 
 | 
 | ||||||
|         self.manager = OpenNebulaManager()  |         self.manager = OpenNebulaManager() | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|     def test_connect_to_server(self): |     def test_connect_to_server(self): | ||||||
|         """Test the opennebula manager can connect to a server.""" |         """Test the opennebula manager can connect to a server.""" | ||||||
|         try: |         try: | ||||||
|             ver = self.manager.oneadmin_client.version() |             ver = self.manager.oneadmin_client.version() | ||||||
|         except:  |         except: | ||||||
|             ver = None |             ver = None | ||||||
|         self.assertTrue(ver is not None) |         self.assertTrue(ver is not None) | ||||||
| 
 | 
 | ||||||
|  | @ -54,7 +51,7 @@ class OpenNebulaManagerTestCases(TestCase): | ||||||
|         # Remove the user afterwards |         # Remove the user afterwards | ||||||
|         user = user_pool.get_by_name(self.email) |         user = user_pool.get_by_name(self.email) | ||||||
|         user.delete() |         user.delete() | ||||||
|          | 
 | ||||||
|         self.assertNotEqual(old_count, new_count) |         self.assertNotEqual(old_count, new_count) | ||||||
| 
 | 
 | ||||||
|     def test_user_can_login(self): |     def test_user_can_login(self): | ||||||
|  | @ -64,7 +61,7 @@ class OpenNebulaManagerTestCases(TestCase): | ||||||
|         client = self.manager._get_client(self.user) |         client = self.manager._get_client(self.user) | ||||||
|         version = client.version() |         version = client.version() | ||||||
| 
 | 
 | ||||||
|         # Cleanup  |         # Cleanup | ||||||
|         user.delete() |         user.delete() | ||||||
|         self.assertNotEqual(version, None) |         self.assertNotEqual(version, None) | ||||||
| 
 | 
 | ||||||
|  | @ -77,11 +74,11 @@ class OpenNebulaManagerTestCases(TestCase): | ||||||
|         # Fetch new user information from opennebula |         # Fetch new user information from opennebula | ||||||
|         user.info() |         user.info() | ||||||
|         user_public_key = user.template.ssh_public_key |         user_public_key = user.template.ssh_public_key | ||||||
|         # Cleanup  |         # Cleanup | ||||||
|         user.delete() |         user.delete() | ||||||
| 
 | 
 | ||||||
|         self.assertEqual(user_public_key, public_key) |         self.assertEqual(user_public_key, public_key) | ||||||
|          | 
 | ||||||
|     def test_append_public_key_to_user(self): |     def test_append_public_key_to_user(self): | ||||||
|         """ Test the manager can append a new public key to an user """ |         """ Test the manager can append a new public key to an user """ | ||||||
|         self.manager.create_user(self.user) |         self.manager.create_user(self.user) | ||||||
|  | @ -94,11 +91,11 @@ class OpenNebulaManagerTestCases(TestCase): | ||||||
|         self.manager.add_public_key(self.user, public_key, merge=True) |         self.manager.add_public_key(self.user, public_key, merge=True) | ||||||
|         user.info() |         user.info() | ||||||
|         new_public_key = user.template.ssh_public_key |         new_public_key = user.template.ssh_public_key | ||||||
|         # Cleanup  |         # Cleanup | ||||||
|         user.delete() |         user.delete() | ||||||
| 
 | 
 | ||||||
|         self.assertEqual(new_public_key, '{}\n{}'.format(old_public_key, |         self.assertEqual(new_public_key, '{}\n{}'.format(old_public_key, | ||||||
|             public_key)) |                                                          public_key)) | ||||||
| 
 | 
 | ||||||
|     def test_remove_public_key_to_user(self): |     def test_remove_public_key_to_user(self): | ||||||
|         """ Test the manager can remove a public key from an user """ |         """ Test the manager can remove a public key from an user """ | ||||||
|  | @ -112,12 +109,11 @@ class OpenNebulaManagerTestCases(TestCase): | ||||||
|         self.manager.remove_public_key(self.user, public_key) |         self.manager.remove_public_key(self.user, public_key) | ||||||
|         user.info() |         user.info() | ||||||
|         new_public_key = user.template.ssh_public_key |         new_public_key = user.template.ssh_public_key | ||||||
|         # Cleanup  |         # Cleanup | ||||||
|         user.delete() |         user.delete() | ||||||
| 
 | 
 | ||||||
|         self.assertEqual(new_public_key, |         self.assertEqual(new_public_key, | ||||||
|                 old_public_key.replace('{}\n'.format(public_key), '', 1)) |                          old_public_key.replace('{}\n'.format(public_key), '', 1)) | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|     def test_requires_ssh_key_for_new_vm(self): |     def test_requires_ssh_key_for_new_vm(self): | ||||||
|         """Test the opennebula manager requires the user to have a ssh key when |         """Test the opennebula manager requires the user to have a ssh key when | ||||||
|  | @ -128,14 +124,11 @@ class VirtualMachineSerializerTestCase(TestCase): | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         """Define the test client and other test variables.""" |         """Define the test client and other test variables.""" | ||||||
|         self.manager = OpenNebulaManager(email=None, password=None) |         self.manager = OpenNebulaManager(email=None, password=None) | ||||||
|                                             |  | ||||||
| 
 | 
 | ||||||
|     def test_serializer_strips_of_public(self): |     def test_serializer_strips_of_public(self): | ||||||
|         """ Test the serialized virtual machine object contains no 'public-'."""  |         """ Test the serialized virtual machine object contains no 'public-'.""" | ||||||
| 
 | 
 | ||||||
|         for vm in self.manager.get_vms(): |         for vm in self.manager.get_vms(): | ||||||
|             serialized = VirtualMachineSerializer(vm) |             serialized = VirtualMachineSerializer(vm) | ||||||
|             self.assertEqual(serialized.data.get('name'), vm.name.strip('public-')) |             self.assertEqual(serialized.data.get('name'), vm.name.strip('public-')) | ||||||
|             break |             break | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -1,19 +1,11 @@ | ||||||
| from rest_framework import generics | from rest_framework import generics | ||||||
| from rest_framework import permissions | from rest_framework import permissions | ||||||
| 
 | 
 | ||||||
| from django.contrib.auth.mixins import LoginRequiredMixin | from .serializers import VirtualMachineSerializer | ||||||
| from django.contrib.auth import authenticate, login |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| from utils.views import LoginViewMixin |  | ||||||
| from membership.models import CustomUser, StripeCustomer |  | ||||||
| from guardian.mixins import PermissionRequiredMixin |  | ||||||
| 
 |  | ||||||
| from .serializers import VirtualMachineTemplateSerializer, \ |  | ||||||
|                          VirtualMachineSerializer |  | ||||||
| from .models import OpenNebulaManager | from .models import OpenNebulaManager | ||||||
| from rest_framework.exceptions import APIException | from rest_framework.exceptions import APIException | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class ServiceUnavailable(APIException): | class ServiceUnavailable(APIException): | ||||||
|     status_code = 503 |     status_code = 503 | ||||||
|     default_detail = 'Service temporarily unavailable, try again later.' |     default_detail = 'Service temporarily unavailable, try again later.' | ||||||
|  | @ -29,7 +21,7 @@ class VmCreateView(generics.ListCreateAPIView): | ||||||
|         owner = self.request.user |         owner = self.request.user | ||||||
|         manager = OpenNebulaManager(email=owner.email, |         manager = OpenNebulaManager(email=owner.email, | ||||||
|                                     password=owner.password) |                                     password=owner.password) | ||||||
|         # We may have ConnectionRefusedError if we don't have a  |         # We may have ConnectionRefusedError if we don't have a | ||||||
|         # connection to OpenNebula. For now, we raise ServiceUnavailable |         # connection to OpenNebula. For now, we raise ServiceUnavailable | ||||||
|         try: |         try: | ||||||
|             vms = manager.get_vms() |             vms = manager.get_vms() | ||||||
|  | @ -41,6 +33,7 @@ class VmCreateView(generics.ListCreateAPIView): | ||||||
|         """Save the post data when creating a new template.""" |         """Save the post data when creating a new template.""" | ||||||
|         serializer.save(owner=self.request.user) |         serializer.save(owner=self.request.user) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class VmDetailsView(generics.RetrieveUpdateDestroyAPIView): | class VmDetailsView(generics.RetrieveUpdateDestroyAPIView): | ||||||
|     """This class handles the http GET, PUT and DELETE requests.""" |     """This class handles the http GET, PUT and DELETE requests.""" | ||||||
|     permission_classes = (permissions.IsAuthenticated, ) |     permission_classes = (permissions.IsAuthenticated, ) | ||||||
|  | @ -51,7 +44,7 @@ class VmDetailsView(generics.RetrieveUpdateDestroyAPIView): | ||||||
|         owner = self.request.user |         owner = self.request.user | ||||||
|         manager = OpenNebulaManager(email=owner.email, |         manager = OpenNebulaManager(email=owner.email, | ||||||
|                                     password=owner.password) |                                     password=owner.password) | ||||||
|         # We may have ConnectionRefusedError if we don't have a  |         # We may have ConnectionRefusedError if we don't have a | ||||||
|         # connection to OpenNebula. For now, we raise ServiceUnavailable |         # connection to OpenNebula. For now, we raise ServiceUnavailable | ||||||
|         try: |         try: | ||||||
|             vms = manager.get_vms() |             vms = manager.get_vms() | ||||||
|  | @ -63,22 +56,21 @@ class VmDetailsView(generics.RetrieveUpdateDestroyAPIView): | ||||||
|         owner = self.request.user |         owner = self.request.user | ||||||
|         manager = OpenNebulaManager(email=owner.email, |         manager = OpenNebulaManager(email=owner.email, | ||||||
|                                     password=owner.password) |                                     password=owner.password) | ||||||
|         # We may have ConnectionRefusedError if we don't have a  |         # We may have ConnectionRefusedError if we don't have a | ||||||
|         # connection to OpenNebula. For now, we raise ServiceUnavailable |         # connection to OpenNebula. For now, we raise ServiceUnavailable | ||||||
|         try: |         try: | ||||||
|             vm = manager.get_vm(self.kwargs.get('pk')) |             vm = manager.get_vm(self.kwargs.get('pk')) | ||||||
|         except ConnectionRefusedError: |         except ConnectionRefusedError: | ||||||
|             raise ServiceUnavailable |             raise ServiceUnavailable | ||||||
|         return vm                                     |         return vm | ||||||
| 
 | 
 | ||||||
|     def perform_destroy(self, instance): |     def perform_destroy(self, instance): | ||||||
|         owner = self.request.user |         owner = self.request.user | ||||||
|         manager = OpenNebulaManager(email=owner.email, |         manager = OpenNebulaManager(email=owner.email, | ||||||
|                                     password=owner.password) |                                     password=owner.password) | ||||||
|         # We may have ConnectionRefusedError if we don't have a  |         # We may have ConnectionRefusedError if we don't have a | ||||||
|         # connection to OpenNebula. For now, we raise ServiceUnavailable |         # connection to OpenNebula. For now, we raise ServiceUnavailable | ||||||
|         try: |         try: | ||||||
|             manager.delete_vm(instance.id) |             manager.delete_vm(instance.id) | ||||||
|         except ConnectionRefusedError: |         except ConnectionRefusedError: | ||||||
|             raise ServiceUnavailable |             raise ServiceUnavailable | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -84,5 +84,4 @@ django-admin-honeypot==1.0.0 | ||||||
| coverage==4.3.4 | coverage==4.3.4 | ||||||
| git+https://github.com/ungleich/python-oca.git#egg=python-oca | git+https://github.com/ungleich/python-oca.git#egg=python-oca | ||||||
| djangorestframework | djangorestframework | ||||||
| 
 | flake8==3.3.0 | ||||||
| 
 |  | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								setup.cfg
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										3
									
								
								setup.cfg
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | [flake8] | ||||||
|  | max-line-length = 120 | ||||||
|  | exclude = .tox,.git,*/migrations/*,*/static/*,docs,venv,node_modules/* | ||||||
|  | @ -9,4 +9,5 @@ from .models import UngleichPage | ||||||
| class UngleichPageAdmin(PageExtensionAdmin): | class UngleichPageAdmin(PageExtensionAdmin): | ||||||
|     pass |     pass | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| admin.site.register(UngleichPage, UngleichPageAdmin) | admin.site.register(UngleichPage, UngleichPageAdmin) | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ from cms.extensions.toolbar import ExtensionToolbar | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| 
 | 
 | ||||||
| from cms.toolbar_pool import toolbar_pool | from cms.toolbar_pool import toolbar_pool | ||||||
| from cms.toolbar_base import CMSToolbar |  | ||||||
| 
 | 
 | ||||||
| from .models import UngleichPage | from .models import UngleichPage | ||||||
| 
 | 
 | ||||||
|  | @ -22,4 +21,4 @@ class UngleichPageToolbar(ExtensionToolbar): | ||||||
|             if url: |             if url: | ||||||
|                 # adds a toolbar item |                 # adds a toolbar item | ||||||
|                 current_page_menu.add_modal_item(_('Page Header'), url=url, |                 current_page_menu.add_modal_item(_('Page Header'), url=url, | ||||||
|                     disabled=not self.toolbar.edit_mode) |                                                  disabled=not self.toolbar.edit_mode) | ||||||
|  |  | ||||||
|  | @ -1,5 +1,3 @@ | ||||||
| from django.db import models |  | ||||||
| 
 |  | ||||||
| from cms.extensions import PageExtension | from cms.extensions import PageExtension | ||||||
| from cms.extensions.extension_pool import extension_pool | from cms.extensions.extension_pool import extension_pool | ||||||
| from filer.fields.image import FilerImageField | from filer.fields.image import FilerImageField | ||||||
|  | @ -9,11 +7,12 @@ from filer.fields.image import FilerImageField | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class UngleichPage(PageExtension): | class UngleichPage(PageExtension): | ||||||
|     #image_header = models.ImageField(upload_to='image_header') |     # image_header = models.ImageField(upload_to='image_header') | ||||||
|     image = FilerImageField(null=True, blank=True, |     image = FilerImageField(null=True, blank=True, | ||||||
|                            related_name="ungleinch_page_image") |                             related_name="ungleinch_page_image") | ||||||
| 
 | 
 | ||||||
|     class Meta: |     class Meta: | ||||||
|         app_label = 'ungleich' |         app_label = 'ungleich' | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| extension_pool.register(UngleichPage) | extension_pool.register(UngleichPage) | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| from django.utils.translation import ugettext_lazy as _ | # from django.utils.translation import ugettext_lazy as _ | ||||||
| # TEMPLATES = { | # TEMPLATES = { | ||||||
| #     'blog_u.html': _('Blog'), | #     'blog_u.html': _('Blog'), | ||||||
| #     'page.html': _('Page'), | #     'page.html': _('Page'), | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| from django.test import TestCase | # from django.test import TestCase | ||||||
| 
 | 
 | ||||||
| # Create your tests here. | # Create your tests here. | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ from django.utils.translation import get_language | ||||||
| from djangocms_blog.models import Post | from djangocms_blog.models import Post | ||||||
| from djangocms_blog.views import PostListView | from djangocms_blog.views import PostListView | ||||||
| from djangocms_blog.settings import get_setting | from djangocms_blog.settings import get_setting | ||||||
|  | from django.utils.translation import ugettext_lazy as _ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def blog(request): | def blog(request): | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| from django.contrib import admin | # from django.contrib import admin | ||||||
| 
 | 
 | ||||||
| # Register your models here. | # Register your models here. | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| from django.db import models | # from django.db import models | ||||||
| 
 | 
 | ||||||
| # Create your models here. | # Create your models here. | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| from django.test import TestCase | # from django.test import TestCase | ||||||
| 
 | 
 | ||||||
| # Create your tests here. | # Create your tests here. | ||||||
|  |  | ||||||
|  | @ -2,10 +2,9 @@ from django.contrib import messages | ||||||
| 
 | 
 | ||||||
| from django.views.generic.edit import FormView | from django.views.generic.edit import FormView | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| from django.core.urlresolvers import reverse_lazy,reverse | from django.core.urlresolvers import reverse_lazy | ||||||
| from django.views.generic import View | from django.views.generic import View | ||||||
| from django.shortcuts import render,redirect,render_to_response | from django.shortcuts import render | ||||||
| from django.http import HttpResponseRedirect |  | ||||||
| 
 | 
 | ||||||
| from utils.forms import ContactUsForm | from utils.forms import ContactUsForm | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| from django.contrib import admin | from django.contrib import admin | ||||||
| from .models import BillingAddress, UserBillingAddress | from .models import UserBillingAddress | ||||||
| 
 | 
 | ||||||
| # Register your models here. | # Register your models here. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| from django.utils.translation import ugettext as _ | from django.utils.translation import ugettext as _ | ||||||
| from django.db import models | from django.db import models | ||||||
| from django import forms |  | ||||||
| 
 | 
 | ||||||
| # http://xml.coverpages.org/country3166.html | # http://xml.coverpages.org/country3166.html | ||||||
| COUNTRIES = ( | COUNTRIES = ( | ||||||
|  | @ -255,4 +254,4 @@ class CountryField(models.CharField): | ||||||
|         super(CountryField, self).__init__(*args, **kwargs) |         super(CountryField, self).__init__(*args, **kwargs) | ||||||
| 
 | 
 | ||||||
|     def get_internal_type(self): |     def get_internal_type(self): | ||||||
|         return "CharField" |         return "CharField" | ||||||
|  |  | ||||||
|  | @ -115,7 +115,8 @@ class BillingAddressForm(forms.ModelForm): | ||||||
| 
 | 
 | ||||||
| class UserBillingAddressForm(forms.ModelForm): | class UserBillingAddressForm(forms.ModelForm): | ||||||
|     user = forms.ModelChoiceField(queryset=CustomUser.objects.all(), |     user = forms.ModelChoiceField(queryset=CustomUser.objects.all(), | ||||||
|                                              widget=forms.HiddenInput()) |                                   widget=forms.HiddenInput()) | ||||||
|  | 
 | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = UserBillingAddress |         model = UserBillingAddress | ||||||
|         fields = ['street_address', 'city', 'postal_code', 'country', 'user'] |         fields = ['street_address', 'city', 'postal_code', 'country', 'user'] | ||||||
|  | @ -126,6 +127,7 @@ class UserBillingAddressForm(forms.ModelForm): | ||||||
|             'Country': _('Country'), |             'Country': _('Country'), | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class ContactUsForm(forms.ModelForm): | class ContactUsForm(forms.ModelForm): | ||||||
|     error_css_class = 'autofocus' |     error_css_class = 'autofocus' | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -77,4 +77,3 @@ class DigitalGlarusRegistrationMailer(BaseMailer): | ||||||
|         self.registration = self.message |         self.registration = self.message | ||||||
|         self._message = self._message.format(slug=self._slug) |         self._message = self._message.format(slug=self._slug) | ||||||
|         super().__init__() |         super().__init__() | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -1,6 +1,4 @@ | ||||||
| from django.db import models | from django.db import models | ||||||
| from django.core import serializers |  | ||||||
| from django.forms.models import model_to_dict |  | ||||||
| 
 | 
 | ||||||
| from membership.models import CustomUser | from membership.models import CustomUser | ||||||
| 
 | 
 | ||||||
|  | @ -18,6 +16,7 @@ class BaseBillingAddress(models.Model): | ||||||
|     class Meta: |     class Meta: | ||||||
|         abstract = True |         abstract = True | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class BillingAddress(BaseBillingAddress): | class BillingAddress(BaseBillingAddress): | ||||||
| 
 | 
 | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|  |  | ||||||
|  | @ -137,22 +137,10 @@ class StripeUtils(object): | ||||||
|             id=id) |             id=id) | ||||||
| 
 | 
 | ||||||
|     @handleStripeError |     @handleStripeError | ||||||
|     def make_payment(self, user, amount, token): |     def make_payment(self, customer, amount, token): | ||||||
|         charge = self.stripe.Charge.create( |         charge = self.stripe.Charge.create( | ||||||
|             amount=amount,  # in cents |             amount=amount,  # in cents | ||||||
|             currency=self.CURRENCY, |             currency=self.CURRENCY, | ||||||
|             customer=customer |             customer=customer | ||||||
|         ) |         ) | ||||||
|         return charge |         return charge | ||||||
| 
 |  | ||||||
|     @handleStripeError |  | ||||||
|     def create_plan(self, amount, name, id): |  | ||||||
|         self.stripe.Plan.create( |  | ||||||
|             amount=amount, |  | ||||||
|             interval=self.INTERVAL, |  | ||||||
|             name=name, |  | ||||||
|             currency=self.CURRENCY, |  | ||||||
|             id=id) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue