Merge branch 'master' of https://github.com/siarheipuhach/dynamicweb
Merge upsteam/master
This commit is contained in:
commit
1f0bb9f72a
66 changed files with 389 additions and 435 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,20 +5,18 @@ 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
|
|
||||||
|
|
|
@ -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
|
||||||
|
@ -13,29 +13,31 @@ from django.core.exceptions import ValidationError
|
||||||
from django.views.decorators.cache import cache_control
|
from django.views.decorators.cache import cache_control
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from utils.forms import BillingAddressForm, UserBillingAddressForm
|
from utils.forms import BillingAddressForm, UserBillingAddressForm
|
||||||
from membership.models import StripeCustomer
|
from hosting.models import HostingOrder
|
||||||
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"
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
if 'specs' not in request.session or 'user' not in request.session:
|
if 'specs' not in request.session or 'user' not in request.session:
|
||||||
return HttpResponseRedirect(reverse('datacenterlight:index'))
|
return HttpResponseRedirect(reverse('datacenterlight:index'))
|
||||||
else :
|
else:
|
||||||
del request.session['specs']
|
del request.session['specs']
|
||||||
del request.session['user']
|
del request.session['user']
|
||||||
return render(request, self.template_name)
|
return render(request, self.template_name)
|
||||||
|
|
||||||
|
|
||||||
class PricingView(TemplateView):
|
class PricingView(TemplateView):
|
||||||
template_name = "datacenterlight/pricing.html"
|
template_name = "datacenterlight/pricing.html"
|
||||||
|
|
||||||
|
@ -48,17 +50,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')
|
||||||
|
@ -77,7 +78,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,
|
||||||
|
@ -92,7 +93,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())
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,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
|
||||||
|
@ -185,12 +186,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']
|
||||||
try:
|
try:
|
||||||
manager = OpenNebulaManager()
|
manager = OpenNebulaManager()
|
||||||
|
@ -199,13 +200,13 @@ class IndexView(CreateView):
|
||||||
'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):
|
||||||
|
@ -217,7 +218,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()
|
||||||
|
@ -228,7 +229,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))
|
||||||
|
@ -240,12 +241,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
|
||||||
|
@ -330,17 +331,16 @@ class PaymentOrderView(FormView):
|
||||||
final_price = specs.get('price')
|
final_price = specs.get('price')
|
||||||
token = form.cleaned_data.get('token')
|
token = form.cleaned_data.get('token')
|
||||||
try:
|
try:
|
||||||
custom_user = CustomUser.objects.get(email=user.get('email'))
|
CustomUser.objects.get(email=user.get('email'))
|
||||||
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
|
||||||
customer = StripeCustomer.get_or_create(email=user.get('email'),
|
customer = StripeCustomer.get_or_create(email=user.get('email'),
|
||||||
token=token)
|
token=token)
|
||||||
|
@ -366,21 +366,21 @@ class PaymentOrderView(FormView):
|
||||||
return render(request, self.template_name, context)
|
return render(request, self.template_name, context)
|
||||||
|
|
||||||
charge = charge_response.get('response_object')
|
charge = charge_response.get('response_object')
|
||||||
|
|
||||||
# Create OpenNebulaManager
|
# Create OpenNebulaManager
|
||||||
manager = OpenNebulaManager(email=settings.OPENNEBULA_USERNAME,
|
manager = OpenNebulaManager(email=settings.OPENNEBULA_USERNAME,
|
||||||
password=settings.OPENNEBULA_PASSWORD)
|
password=settings.OPENNEBULA_PASSWORD)
|
||||||
|
|
||||||
# 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,
|
||||||
specs=specs,
|
specs=specs,
|
||||||
vm_name="{email}-{template_name}-{date}".format(
|
vm_name="{email}-{template_name}-{date}".format(
|
||||||
email=user.get('email'),
|
email=user.get('email'),
|
||||||
template_name=template.get('name'),
|
template_name=template.get('name'),
|
||||||
date=int(datetime.now().strftime("%s")))
|
date=int(datetime.now().strftime("%s")))
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a Hosting Order
|
# Create a Hosting Order
|
||||||
order = HostingOrder.create(
|
order = HostingOrder.create(
|
||||||
price=final_price,
|
price=final_price,
|
||||||
|
@ -388,10 +388,11 @@ class PaymentOrderView(FormView):
|
||||||
customer=customer,
|
customer=customer,
|
||||||
billing_address=billing_address
|
billing_address=billing_address
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a Hosting Bill
|
# Create a Hosting Bill
|
||||||
bill = HostingBill.create(
|
# 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():
|
||||||
|
@ -408,9 +409,9 @@ class PaymentOrderView(FormView):
|
||||||
|
|
||||||
# If the Stripe payment was successed, set order status approved
|
# If the Stripe payment was successed, set order status approved
|
||||||
order.set_approved()
|
order.set_approved()
|
||||||
|
|
||||||
vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data
|
vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'name': user.get('name'),
|
'name': user.get('name'),
|
||||||
'email': user.get('email'),
|
'email': user.get('email'),
|
||||||
|
@ -436,10 +437,12 @@ 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"
|
||||||
context_object_name = "order"
|
context_object_name = "order"
|
||||||
model = HostingOrder
|
model = HostingOrder
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
# Get context
|
# Get context
|
||||||
context = super(DetailView, self).get_context_data(**kwargs)
|
context = super(DetailView, self).get_context_data(**kwargs)
|
||||||
|
|
|
@ -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">
|
||||||
|
@ -29,7 +29,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>
|
||||||
|
@ -56,7 +56,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" %}
|
||||||
|
@ -86,7 +86,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">
|
||||||
|
@ -128,7 +128,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -143,7 +143,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 () {
|
||||||
|
@ -154,7 +154,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):
|
||||||
|
|
|
@ -127,22 +127,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…
Reference in a new issue